name: Daily .NET Version Check on: schedule: - cron: "0 8 * * *" workflow_dispatch: env: DOCKER_IMAGE: docker.io/svrnty/dotnet RELEASES_INDEX_URL: https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json jobs: check-versions: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Log in to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} - name: Check for new .NET versions id: check run: | set -euo pipefail # Fetch release metadata RELEASES=$(curl -fsSL "$RELEASES_INDEX_URL") # Filter active/go-live versions (excludes EOL automatically) SUPPORTED=$(echo "$RELEASES" | jq -c '[.["releases-index"][] | select(.["support-phase"] == "active" or .["support-phase"] == "go-live")]') # Find highest LTS and STS majors LTS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "lts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0]') STS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "sts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0] // ""') # Export for later steps echo "supported=$SUPPORTED" >> $GITHUB_OUTPUT echo "lts_major=$LTS_MAJOR" >> $GITHUB_OUTPUT echo "sts_major=$STS_MAJOR" >> $GITHUB_OUTPUT # Check if any new images need building NEEDS_BUILD=false while read -r CHANNEL RUNTIME SDK TYPE; do MAJOR=$(echo "$CHANNEL" | cut -d. -f1) echo "Checking .NET $MAJOR: runtime=$RUNTIME sdk=$SDK type=$TYPE" if ! docker manifest inspect "$DOCKER_IMAGE:runtime-$RUNTIME" > /dev/null 2>&1; then echo " New version detected: runtime-$RUNTIME" NEEDS_BUILD=true break else echo " Image runtime-$RUNTIME already exists, skipping" fi done < <(echo "$SUPPORTED" | jq -r '.[] | "\(.["channel-version"]) \(.["latest-runtime"]) \(.["latest-sdk"]) \(.["release-type"])"') echo "needs_build=$NEEDS_BUILD" >> $GITHUB_OUTPUT - name: Update README version tables id: readme run: | set -euo pipefail SUPPORTED='${{ steps.check.outputs.supported }}' LTS_MAJOR="${{ steps.check.outputs.lts_major }}" STS_MAJOR="${{ steps.check.outputs.sts_major }}" ARCH_BADGES='amd64 arm64' # Table headers README_HEADER='| Version | runtime | runtime-invariant | sdk | Arch | EOL |' README_SEP='|---------|---------|-------------------|-----|------|-----|' DOCKERHUB_HEADER='| Version | `runtime` | `runtime-invariant` | `sdk` | Arch | EOL |' DOCKERHUB_SEP='|---------|-----------|---------------------|-------|------|-----|' echo "$README_HEADER" > /tmp/readme_rows.txt echo "$README_SEP" >> /tmp/readme_rows.txt echo "$DOCKERHUB_HEADER" > /tmp/dockerhub_rows.txt echo "$DOCKERHUB_SEP" >> /tmp/dockerhub_rows.txt > /tmp/badge_versions.txt # Build version rows from API data (sorted by major descending) echo "$SUPPORTED" | jq -r 'sort_by(.["channel-version"] | split(".") | map(tonumber)) | reverse | .[] | "\(.["channel-version"]) \(.["latest-runtime"]) \(.["latest-sdk"]) \(.["release-type"]) \(.["eol-date"] // "TBD")"' | \ while read -r CHANNEL RUNTIME SDK TYPE EOL; do MAJOR=$(echo "$CHANNEL" | cut -d. -f1) # Version label if [ "$TYPE" = "lts" ]; then LABEL="**.NET ${MAJOR}** (LTS)" elif [ "$TYPE" = "sts" ]; then LABEL="**.NET ${MAJOR}** (STS)" else LABEL="**.NET ${MAJOR}**" fi # Floating tags only for highest LTS/STS if [ "$MAJOR" = "$LTS_MAJOR" ]; then RT_TAGS="\`runtime-${MAJOR}\` \`runtime-lts\`" RI_TAGS="\`runtime-invariant-${MAJOR}\` \`runtime-invariant-lts\`" SDK_TAGS="\`sdk-${MAJOR}\` \`sdk-lts\`" elif [ "$MAJOR" = "$STS_MAJOR" ]; then RT_TAGS="\`runtime-${MAJOR}\` \`runtime-sts\`" RI_TAGS="\`runtime-invariant-${MAJOR}\` \`runtime-invariant-sts\`" SDK_TAGS="\`sdk-${MAJOR}\` \`sdk-sts\`" else RT_TAGS="\`runtime-${MAJOR}\`" RI_TAGS="\`runtime-invariant-${MAJOR}\`" SDK_TAGS="\`sdk-${MAJOR}\`" fi echo "| ${LABEL} | ${RT_TAGS} | ${RI_TAGS} | ${SDK_TAGS} | ${ARCH_BADGES} | ${EOL} |" >> /tmp/readme_rows.txt echo "| ${LABEL} | ${RT_TAGS} | ${RI_TAGS} | ${SDK_TAGS} | amd64 arm64 | ${EOL} |" >> /tmp/dockerhub_rows.txt echo -n "${MAJOR} " >> /tmp/badge_versions.txt done README_ROWS=$(cat /tmp/readme_rows.txt) DOCKERHUB_ROWS=$(cat /tmp/dockerhub_rows.txt) BADGE_VERSIONS=$(cat /tmp/badge_versions.txt | xargs | sed 's/ /%20|%20/g') # Update README.md — version table awk ' // { print; found=1; next } // { found=0 } found { next } { print } ' README.md > /tmp/readme_new.md # Insert new rows after BEGIN marker awk -v rows="$README_ROWS" ' // { print; print rows; next } { print } ' /tmp/readme_new.md > README.md # Update README.md — .NET badge sed -i "s|.*|\".NET\"|" README.md # Update DOCKERHUB.md — version table awk ' // { print; found=1; next } // { found=0 } found { next } { print } ' DOCKERHUB.md > /tmp/dockerhub_new.md awk -v rows="$DOCKERHUB_ROWS" ' // { print; print rows; next } { print } ' /tmp/dockerhub_new.md > DOCKERHUB.md # Check if anything changed if git diff --quiet README.md DOCKERHUB.md; then echo "readme_changed=false" >> $GITHUB_OUTPUT echo "READMEs are up to date" else echo "readme_changed=true" >> $GITHUB_OUTPUT echo "READMEs need updating" git diff README.md DOCKERHUB.md fi - name: Commit README updates if: steps.readme.outputs.readme_changed == 'true' run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add README.md DOCKERHUB.md git commit -m "Update supported .NET versions in README" git push - name: Trigger build workflow if: steps.check.outputs.needs_build == 'true' uses: actions/github-script@v7 with: script: | await github.rest.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'build.yaml', ref: context.ref })