Fixed dup #66
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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' || '' }} |