diff --git a/.gitea/workflows/update-check.yaml b/.gitea/workflows/update-check.yaml
index cb56ec9..f8a0ab4 100644
--- a/.gitea/workflows/update-check.yaml
+++ b/.gitea/workflows/update-check.yaml
@@ -33,34 +33,132 @@ jobs:
# Filter active/go-live versions (excludes EOL automatically)
SUPPORTED=$(echo "$RELEASES" | jq -c '[.["releases-index"][] | select(.["support-phase"] == "active" or .["support-phase"] == "go-live")]')
- NEEDS_BUILD=false
+ # 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] // ""')
- echo "$SUPPORTED" | jq -r '.[] | "\(.["channel-version"]) \(.["latest-runtime"]) \(.["latest-sdk"]) \(.["release-type"])"' | \
+ # 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"
- # Check if runtime image for this exact version exists
- if docker manifest inspect "$DOCKER_IMAGE:runtime-$RUNTIME" > /dev/null 2>&1; then
- echo " Image runtime-$RUNTIME already exists, skipping"
- else
+ if ! docker manifest inspect "$DOCKER_IMAGE:runtime-$RUNTIME" > /dev/null 2>&1; then
echo " New version detected: runtime-$RUNTIME"
NEEDS_BUILD=true
- fi
- done
-
- # Re-check outside the pipe (subshell issue)
- NEEDS_BUILD=false
- while read -r CHANNEL RUNTIME SDK TYPE; do
- MAJOR=$(echo "$CHANNEL" | cut -d. -f1)
- if ! docker manifest inspect "$DOCKER_IMAGE:runtime-$RUNTIME" > /dev/null 2>&1; then
- 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='
'
+
+ # Build version rows from API data (sorted by major descending)
+ README_ROWS=""
+ DOCKERHUB_ROWS=""
+ BADGE_VERSIONS=""
+
+ 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|.*|
|" 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
diff --git a/DOCKERHUB.md b/DOCKERHUB.md
index 3d0da65..f7728c9 100644
--- a/DOCKERHUB.md
+++ b/DOCKERHUB.md
@@ -9,9 +9,11 @@ Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wo
| Version | `runtime` | `runtime-invariant` | `sdk` | Arch | EOL |
|---------|-----------|---------------------|-------|------|-----|
+
| **.NET 10** (LTS) | `runtime-10` `runtime-lts` | `runtime-invariant-10` `runtime-invariant-lts` | `sdk-10` `sdk-lts` | amd64 arm64 | 2028-11-14 |
| **.NET 9** (STS) | `runtime-9` `runtime-sts` | `runtime-invariant-9` `runtime-invariant-sts` | `sdk-9` `sdk-sts` | amd64 arm64 | 2026-11-10 |
| **.NET 8** | `runtime-8` | `runtime-invariant-8` | `sdk-8` | amd64 arm64 | 2026-11-10 |
+
## Variants
diff --git a/README.md b/README.md
index ee3fb39..3ad389e 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wolfi.dev), a security-focused Linux distribution designed for containers. All supported (non-EOL) .NET versions are rebuilt automatically.
@@ -12,9 +12,11 @@ Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wo
| Version |
|
|
| Arch | EOL |
|---------|---------|-------------------|-----|------|-----|
+
| **.NET 10** (LTS) | `runtime-10` `runtime-lts` | `runtime-invariant-10` `runtime-invariant-lts` | `sdk-10` `sdk-lts` |
| 2028-11-14 |
| **.NET 9** (STS) | `runtime-9` `runtime-sts` | `runtime-invariant-9` `runtime-invariant-sts` | `sdk-9` `sdk-sts` |
| 2026-11-10 |
| **.NET 8** | `runtime-8` | `runtime-invariant-8` | `sdk-8` |
| 2026-11-10 |
+
## Variants