Skip to content

Fixed dup

Fixed dup #66

Workflow file for this run

name: Build and Publish
on:
schedule:
# At 04:00 on day-of-month 1.
- cron: "0 4 1 * *"
workflow_dispatch:
push:
branches:
- "main"
jobs:
prepare-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
latest: ${{ steps.latest-version.outputs.matrix }}
devcontainer_matrix: ${{ steps.prepare-dev-matrix.outputs.matrix }}
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@master
- name: Check Docker image platforms
id: check-platforms
run: |
# Get Node.js versions
curl -s "https://nodejs.org/download/release/index.json" > node_versions.json
# Filter out versions older than 2 years
two_years_ago=$(date -u -d "2 years ago" +%s)
jq --argjson two_years_ago "$two_years_ago" '[.[] | select((.date | sub("T.*"; "") | strptime("%Y-%m-%d") | mktime) > $two_years_ago)]' node_versions.json > node_versions_recent.json
# Function to check Docker image platforms
check_platforms() {
version=$1
# Get platforms from manifest
if manifest=$(docker manifest inspect "node:$version-alpine" 2>/dev/null); then
# Extract all valid platforms (excluding unknown)
platforms=$(echo "$manifest" | jq -r '.manifests[] |
select(.platform.os != "unknown" and .platform.architecture != "unknown") |
if .platform.variant then
"linux/" + .platform.architecture + "/" + .platform.variant
else
"linux/" + .platform.architecture
end' | tr '\n' ',' | sed 's/,$//')
if [ -n "$platforms" ]; then
echo "$platforms"
return
fi
fi
# Default platforms if manifest check fails
echo "linux/amd64,linux/arm64/v8"
}
# Process versions and add platform information (using filtered recent versions)
jq -c '[.[] | select(.version | test("v(1[8-9]|[2-9][0-9]).*"))] | group_by(.version | match("v(\\d+).*").captures[0].string | tonumber) | map(max_by(.version | match("v(\\d+\\.\\d+).*").captures[0].string | split(".") as $parts | ($parts[0] | tonumber) * 1000 + ($parts[1] | tonumber))) | map({version: .version, major: (.version | match("v(\\d+).*").captures[0].string | tonumber)})' node_versions_recent.json > versions.json
# Add platform information to each version
platforms_json="["
first=true
while IFS= read -r version_info; do
version=$(echo "$version_info" | jq -r '.version')
major=$(echo "$version_info" | jq -r '.major')
version_without_v="${version#v}" # Remove 'v' prefix for Docker tag
platforms=$(check_platforms "$version_without_v")
if [ "$first" = true ]; then
first=false
else
platforms_json="$platforms_json,"
fi
platforms_json="$platforms_json{\"version\":\"$version\",\"major\":$major,\"platforms\":\"$platforms\"}"
done < <(jq -c '.[]' versions.json)
platforms_json="$platforms_json]"
echo "$platforms_json" > config.json
- uses: cloudposse/github-action-jq@main
id: latest-version
with:
compact: true
input: node_versions.json
script: 'map(select(.version | startswith("v20"))) | max_by(.version) | .version'
- uses: cloudposse/github-action-jq@main
id: reparse-tags
with:
compact: true
input: config.json
script: '{"tag": . }'
- run: echo 'matrix=${{ steps.reparse-tags.outputs.output }}' >> $GITHUB_OUTPUT
id: set-matrix
- name: Prepare devcontainer matrix
id: prepare-dev-matrix
run: |
# Only keep the highest version of the last 3 major versions for devcontainers
jq '[. | sort_by(.major) | reverse | group_by(.major) | map(.[0]) | sort_by(.major) | reverse | .[:3]]' config.json > devcontainer_matrix.json
echo "matrix=$(jq -c '{"tag": .}' devcontainer_matrix.json)" >> $GITHUB_OUTPUT
build:
needs: prepare-matrix
runs-on: ubuntu-latest
strategy:
matrix: ${{fromJson(needs.prepare-matrix.outputs.matrix)}}
env:
LATEST_VERSION: ${{ needs.prepare-matrix.outputs.latest }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
logout: true
- name: Parse version
id: parse_version
run: |
VERSION=${{ matrix.tag.version }}
PARSED_VERSION=${VERSION#v}
echo "PARSED_VERSION=$PARSED_VERSION" >> $GITHUB_OUTPUT
shell: bash
- name: Build
uses: docker/build-push-action@v5
with:
build-args: |
NODE_MAJOR=${{ matrix.tag.major }}
NODE_VERSION=${{ steps.parse_version.outputs.PARSED_VERSION }}
context: .
platforms: ${{ matrix.tag.platforms }}
push: true
tags: |
betterweb/node:${{steps.parse_version.outputs.PARSED_VERSION}}
betterweb/node:${{matrix.tag.major}}
${{ steps.is_latest.outputs.IS_LATEST == 'true' && 'betterweb/node:latest' || '' }}
build-devcontainers:
needs: prepare-matrix
runs-on: ubuntu-latest
strategy:
matrix: ${{fromJson(needs.prepare-matrix.outputs.devcontainer_matrix)}}
env:
LATEST_VERSION: ${{ needs.prepare-matrix.outputs.latest }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
logout: true
- name: Parse version
id: parse_version
run: |
VERSION=${{ matrix.tag.version }}
PARSED_VERSION=${VERSION#v}
echo "PARSED_VERSION=$PARSED_VERSION" >> $GITHUB_OUTPUT
shell: bash
- name: Is Latest
id: is_latest
run: |
if [ "${{ matrix.tag.version }}" = "${{ env.LATEST_VERSION }}" ]; then
echo "IS_LATEST=true" >> $GITHUB_OUTPUT
else
echo "IS_LATEST=false" >> $GITHUB_OUTPUT
fi
- name: Build and push devcontainer image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.devcontainer
push: true
build-args: |
NODE_MAJOR=${{ matrix.tag.major }}
NODE_VERSION=${{ steps.parse_version.outputs.PARSED_VERSION }}
tags: |
betterweb/node:devcontainer-${{steps.parse_version.outputs.PARSED_VERSION}}
betterweb/node:devcontainer-${{matrix.tag.major}}
${{ steps.is_latest.outputs.IS_LATEST == 'true' && 'betterweb/node:devcontainer-latest' || '' }}