Audit and update supported-os.json/md files to reflect current OS version support. Uses the release-notes tool for automated verification against upstream lifecycle data and markdown regeneration. USE FOR: adding new OS versions, moving EOL versions to unsupported, periodic support matrix audits. DO NOT USE FOR: os-packages.json changes (use update-os-packages skill), editing supported-os.md directly (it is generated from JSON).
Audit and update supported-os.json files in this repository. These files declare which operating system versions are supported for each .NET release. The corresponding supported-os.md files are generated from JSON — never hand-edit them.
The following tools must be installed:
The release-notes tool is used to verify and generate supported OS files. The public dotnet-release tool is now for browsing release data and CVEs. Packages are published to GitHub Packages.
# GitHub Packages requires authentication — use a GitHub token (PAT or GITHUB_TOKEN)
dotnet tool install -g release-notes \
--add-source https://nuget.pkg.github.com/richlander/index.json
# Verify
release-notes --help
Note: GitHub Packages requires authentication even for public repositories. If you get a 401 error, configure credentials for the source:
dotnet nuget add source https://nuget.pkg.github.com/richlander/index.json \ --name github-richlander \ --username USERNAME \ --password "$GITHUB_TOKEN" \ --store-password-in-clear-textIn GitHub Actions,
GITHUB_TOKENis available automatically. For local use, create a personal access token withread:packagesscope.
The markdownlint-cli tool is used to validate generated markdown. Install via npm:
npm install -g markdownlint-cli
# Verify
npx markdownlint --version
If npm is not available, install Node.js first (e.g. brew install node on macOS). This is a required step — do not skip linting.
The user provides:
Run the verify command for each .NET version to audit:
release-notes verify supported-os <version> release-notes
Examples:
# Check 10.0 against local files
release-notes verify supported-os 10.0 release-notes
# Check against live data on GitHub (no local clone needed)
release-notes verify supported-os 10.0
Interpret the exit code:
The report uses GitHub callout blocks to categorize issues:
| Callout | Meaning |
|---|---|
> [!WARNING] | EOL but still listed as "supported" |
> [!IMPORTANT] | Active release not listed in "supported" |
> [!TIP] | Active but listed as "unsupported" |
> [!CAUTION] | Supported release approaching EOL within 3 months |
See references/verify-output-example.md for example output.
If all versions return exit code 0, the matrix is current. Stop here.
First, determine whether this .NET version is GA or pre-GA (preview/RC). Check releases-index.json for the support-phase field, or ask the user.
unsupported-versions.supported-versions unless there's a known reason to exclude.Apply the preview release rules below. The support matrix should reflect what will be supported at GA, not what happens to be active today.
supported-versions entirely. Do not add to unsupported-versions (Rule 1). Exception: skip Windows versions covered by ESU — unless the ESU itself expires before GA (see Rule 1).supported-versions (Rule 1). If EOL is after GA but before GA + 6 months, remove as well (Rule 2). If EOL is after GA + 6 months, no action needed.Present findings to the user with recommendations before making changes.
For each confirmed change, edit release-notes/<version>/supported-os.json:
supported-versions, add to unsupported-versionssupported-versions only — do not add to unsupported-versionssupported-versions (keep sorted, newest first)last-updated: Set to today's date (format: YYYY-MM-DD) in every JSON file that is modified — this is required for every change, no matter how smalledit tool for surgical JSON changes"3.22" not 3.22After updating the JSON, regenerate the markdown file:
release-notes generate supported-os <version> release-notes
This overwrites supported-os.md with content derived from the updated JSON.
Important: Do not hand-edit
supported-os.md. It is generated from JSON by the tool. If the markdown output needs to change, update the generator or its Markout template in dotnet-release instead.
Verify the generated markdown passes linting (see prerequisites):
npx markdownlint --config .github/linters/.markdown-lint.yml release-notes/<version>/supported-os.md
CI runs markdownlint via super-linter and will block the PR if linting fails. If linting fails on generated content, fix the generator or its Markout template in dotnet-release — do not patch the markdown by hand.
Check if any newly added distro versions need entries in os-packages.json. If so, inform the user to run the update-os-packages skill next.
Run verify again to confirm issues are resolved:
release-notes verify supported-os <version> release-notes
Remaining items are acceptable if they are:
Spot-check the generated markdown renders correctly.
Create a branch:
git checkout -b update-supported-os-<date>
Commit all changed files (supported-os.json and supported-os.md for each version):
git add release-notes/*/supported-os.json release-notes/*/supported-os.md
git commit -m "Update supported OS matrix — <summary of changes>"
Push and open a PR:
gh pr create --title "Update supported OS matrix" --body "<description of changes>"
.NET releases go through a preview period before GA (General Availability). During this period, special rules apply to limit documentation cruft at GA and prevent users from deploying to environments that will soon lose support.
.NET releases always GA in November. The version number and GA year follow a predictable pattern:
For example: .NET 10 GAs November 2025, .NET 11 GAs November 2026, .NET 12 GAs November 2027.
To confirm, check releases-index.json for the release-date of the target version. If the GA date is not yet populated, use the November convention above.
While a .NET release is in preview, remove OS versions from supported-versions if they are already EOL or will reach EOL before the GA date. Do not add them to unsupported-versions — the unsupported list is for versions that were supported during a GA release and later went EOL. Since the .NET release hasn't shipped yet, there is no GA history to preserve.
This rule applies to both WARNING items (already EOL) and CAUTION items (approaching EOL with an EOL date before GA).
Windows ESU exception: Windows versions covered by Extended Security Updates (ESU) are not considered EOL while ESU is active. The verify tool flags these based on mainstream support dates, but ESU extends their lifecycle. However, check whether the ESU program itself expires before the GA date — if it does, the version should be removed.
Rationale: The unsupported-versions list exists as a historical record for users of a shipped release. During preview, no users depend on the support matrix, so versions that won't survive to GA should simply be removed to keep the document clean.
When evaluating whether an OS version should be in supported-versions — whether adding a new version or reviewing one already listed — check whether the version will still be supported (not EOL) at GA date + 6 months.
Rationale: Users should be able to adopt a .NET release at GA and have confidence their OS will remain supported for a reasonable period. Listing OS versions that go EOL shortly after GA creates a "rug-pulling" scenario.
If a distro version is currently in preview but is expected to GA before the .NET GA date, it can be added to supported-versions if all of the following are true:
To check for published images, query the image-info JSON which tracks currently active images:
# Check for published images (preferred — shows currently active images)
curl -sL https://github.com/dotnet/versions/raw/refs/heads/main/build-info/docker/image-info.dotnet-dotnet-buildtools-prereqs-docker-main.json \
| jq '[.repos[].images[].platforms[].simpleTags[]] | map(select(startswith("<os-name>-<version>"))) | .[]'
# Examples
curl -sL <same-url> | jq '[.repos[].images[].platforms[].simpleTags[]] | map(select(startswith("ubuntu-26.04"))) | .[]'
curl -sL <same-url> | jq '[.repos[].images[].platforms[].simpleTags[]] | map(select(startswith("fedora-44"))) | .[]'
You can also check the full MCR tags list which includes all ever-published tags:
curl -s https://mcr.microsoft.com/v2/dotnet-buildtools/prereqs/tags/list \
| jq '.tags[] | select(startswith("<os-name>-<version>"))'
If no published images are found, check whether Dockerfiles exist in the repo (images may be in preparation):
gh search code "<os-name>/<version>" --repo dotnet/dotnet-buildtools-prereqs-docker
For example: gh search code "fedora/44" or gh search code "ubuntu/26.04". Do not use spaces (e.g. "ubuntu 26.04") — the images are organized by folder path.
If conditions 1–3 are met but there is no container image at dotnet-buildtools-prereqs-docker:
If the distro GAs after .NET GA → do not add it yet.
Rationale: By the time .NET ships, these distro versions will be fully released. Adding them early ensures the support matrix is complete at GA without requiring a last-minute update. However, we can only validate support for a distro version when we have build infrastructure (container images) for it.
.NET 11 (STS, odd version) GAs November 2026. GA + 6 months = May 2027.
Rule 1 — Remove EOL versions:
Rule 1 — Remove approaching-EOL versions (CAUTION items with EOL before GA):
Rule 2 — GA + 6 months gate:
Rule 3 — Preview distros:
id field in each distribution matches endoflife.date product IDs"3.22" not 3.22supported-versions should be ordered newest-firstunsupported-versions tracks previously-supported versions for historical referencelast-updated field should reflect the date of any changesupported-os.json: 8.0, 9.0, 10.0, 11.0