update-distro-packages
Update Distro Packages
Create and maintain per-distro JSON files in release-notes/{version}/distros/. Each file declares the native packages .NET depends on for a specific distribution, scoped to a single .NET version.
Directory structure
release-notes/{version}/distros/
├── dependencies.json # distro-agnostic dependency list (what .NET needs)
├── index.json # lists all per-distro file names
├── alpine.json # per-distro: dependencies with distro-specific names
├── ubuntu.json
├── fedora.json
└── ...
When to use
- A new .NET version needs its
distros/directory created for the first time - A distro release is added or removed from the support matrix
- A dependency package name changes (e.g.
libicu74→libicu76on a new Ubuntu) - Periodic audit to keep dependency data current
Prerequisites
The release-notes tool must be installed for markdown generation and package availability queries. The public dotnet-release tool is now for browsing release data and CVEs.
# Check if already installed
release-notes --version
If not installed:
dotnet tool install -g release-notes \
--add-source https://nuget.pkg.github.com/richlander/index.json
If already installed, update to latest:
dotnet tool update -g release-notes \
--add-source https://nuget.pkg.github.com/richlander/index.json
Inputs
The user provides:
- .NET version — which version to work on (e.g. "11.0")
- Task — what to do: create new distros/ directory, add a distro release, update package names, populate dotnet packages, etc.
Ask the user: Do you want to update dotnet packages (which .NET packages are available in each distro)? If so, ask them to provide or set PKGS_ORG_TOKEN. This requires a pkgs.org Gold+ subscription.
File schemas
dependencies.json
Distro-agnostic list of packages .NET requires. Updated once per major release — rarely changes.
{
"channel_version": "11.0",
"packages": [
{
"id": "libc",
"name": "C Library",
"required_scenarios": ["all"],
"references": ["https://..."]
},
{
"id": "openssl",
"name": "OpenSSL",
"required_scenarios": ["https", "cryptography"],
"min_version": "1.1.1",
"references": ["https://..."]
}
]
}
Omit min_version and references when null/empty.
index.json
{
"channel_version": "11.0",
"distros": [
"alpine.json",
"azure_linux.json",
"ubuntu.json"
]
}
Alphabetically sorted list of per-distro file names.
Per-distro files (e.g. ubuntu.json)
Scoped to the .NET version of the parent directory. No dotnet_versions field — the version is the directory.
{
"name": "Ubuntu",
"install_command": "apt-get install -y {packages}",
"releases": [
{
"name": "Ubuntu 24.04 (Noble Numbat)",
"release": "24.04",
"dependencies": [
{ "id": "ca-certificates", "name": "ca-certificates" },
{ "id": "libc", "name": "libc6" },
{ "id": "libicu", "name": "libicu74" },
{ "id": "openssl", "name": "libssl3t64" }
]
}
]
}
Optional fields on each release (populated by package availability queries):
{
"dotnet_packages": [
{ "component": "sdk", "name": "dotnet-sdk-11.0" },
{ "component": "runtime", "name": "dotnet-runtime-11.0" }
],
"dotnet_packages_other": {
"backports": {
"install_command": "sudo apt-get install -y software-properties-common && sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update",
"packages": [
{ "component": "sdk", "name": "dotnet-sdk-11.0" }
]
}
}
}
The install_command in dotnet_packages_other is the command to register the feed — it must be run before packages can be installed with the distro's normal install command. This field is required for every alternative feed entry. See Known alternative feed commands for values.
Process
Creating distros/ for a new .NET version
1. Identify source data
Use os-packages.json from the same version (if it exists) or the previous .NET version as the source for dependency data:
cat release-notes/{version}/os-packages.json
# or from a previous version:
cat release-notes/{prev-version}/os-packages.json
Also reference release-notes/{version}/supported-os.json for the list of supported Linux distributions and versions.
2. Create dependencies.json
Extract the packages array from os-packages.json. Convert keys to snake_case:
required-scenarios→required_scenariosmin-version→min_version
This file changes very rarely — it lists what .NET needs, not what distros call things.
3. Create per-distro files
For each distribution in os-packages.json:
- File name: lowercase distro name, spaces →
_(e.g.azure_linux.json,centos_stream.json) install_command: From the distro'sinstall-commands— use the last command, format as{command-root} {command-parts}, normalize{packageName}→{packages}releases: One entry per distro release, withdependenciessorted alphabetically byid- Do NOT include
dotnet_packagesordotnet_packages_other— those are populated separately
The scope of distros/ is broader than supported-os.json. Include pre-release distro versions and permanent rolling channels where the package information is helpful:
- Alpine edge — always include; it tracks the rolling release
- Debian sid (Unstable) — always include
- Pre-release distro versions — e.g. Fedora beta, Ubuntu interim release before GA
These are informational — their presence does not imply official .NET support.
4. Create index.json
List all per-distro file names alphabetically.
5. Validate
# Verify all JSON parses
for f in release-notes/{version}/distros/*.json; do
python3 -c "import json; json.load(open('$f'))" && echo "OK: $f"
done
Confirm every Linux distro in supported-os.json has a corresponding file.
6. Generate markdown
Regenerate dotnet-dependencies.md from the JSON files:
release-notes generate dotnet-dependencies {version} release-notes
This produces release-notes/{version}/dotnet-dependencies.md with copy-pasteable install commands for each distro and release. Never hand-edit this file — it is generated from the JSON.
Updating existing distros/ files
Adding a new distro release
- Check
supported-os.jsonfor the new release - In the distro's JSON file, copy the most recent release entry
- Update
name,release, and any changed package names (e.g.libicu74→libicu76) - Insert in version order (newest first)
Removing a distro release
Delete the release object from the releases array. If the entire distro is dropped, delete the file and remove it from index.json.
Fixing package names
Update the name field in the relevant dependency entry. Package names change between distro releases due to shared library versioning (e.g. libicu70 on Ubuntu 22.04 → libicu74 on 24.04).
Populating dotnet packages
This populates dotnet_packages and dotnet_packages_other in each per-distro file — recording which .NET packages (SDK, runtime, ASP.NET Core) are available in each distro's package feeds.
Requires PKGS_ORG_TOKEN to be set.
1. Query package feeds
export PKGS_ORG_TOKEN=<token>
release-notes query distro-packages --dotnet-version {version} --output /tmp/distro-packages.json
This queries pkgs.org and supplemental feeds (Ubuntu backports via Launchpad, Homebrew, NixOS) and writes a JSON file with package availability per distro.
2. Read query results
The output file has this structure:
{
"channel_version": "10.0",
"last_verified": "2026-03-25",
"distributions": [
{
"name": "Ubuntu",
"releases": [
{
"name": "Ubuntu 24.04",
"release": "24.04",
"feeds": {
"builtin": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" },
{ "component_id": "runtime", "package_name": "dotnet-runtime-10.0" },
{ "component_id": "aspnetcore-runtime", "package_name": "aspnetcore-runtime-10.0" }
],
"backports": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
]
}
}
]
}
]
}
3. Map into per-distro files
For each distro+release in the query results, match it to the corresponding per-distro file and update:
feeds["builtin"]→dotnet_packages(flat list)- Any other feed (e.g.
feeds["backports"]) →dotnet_packages_other["backports"]
Field mapping from query → per-distro file:
| Query field | Per-distro field |
|---|---|
component_id |
component |
package_name |
name |
Every dotnet_packages_other entry must include an install_command — the command to register that feed before packages can be installed. See Known alternative feed commands for the values to use.
Example — if the query returns this for Ubuntu 24.04:
"feeds": {
"builtin": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
],
"backports": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
]
}
Then ubuntu.json release 24.04 becomes:
{
"name": "Ubuntu 24.04 (Noble Numbat)",
"release": "24.04",
"dependencies": [ ... ],
"dotnet_packages": [
{ "component": "sdk", "name": "dotnet-sdk-10.0" }
],
"dotnet_packages_other": {
"backports": {
"install_command": "sudo apt-get install -y software-properties-common && sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update",
"packages": [
{ "component": "sdk", "name": "dotnet-sdk-10.0" }
]
}
}
}
4. Handle distros not in query results
Not all distros appear in the query results (e.g. RHEL packages are in a subscription-only repo). Leave dotnet_packages absent for those — do not add an empty list.
5. Query distro package lists directly
pkgs.org may not have data for newly released distro versions yet. When a supported distro release is missing from the query results, check the distro's own package list as a fallback.
Ubuntu — query packages.ubuntu.com for the release codename:
curl -s "https://packages.ubuntu.com/{codename}/allpackages?format=txt.gz" \
| gunzip | grep -i "dotnet.*{major}"
curl -s "https://packages.ubuntu.com/{codename}/allpackages?format=txt.gz" \
| gunzip | grep -i "aspnetcore.*{major}"
For example, to check Ubuntu 26.04 (codename resolute) for .NET 10:
curl -s "https://packages.ubuntu.com/resolute/allpackages?format=txt.gz" \
| gunzip | grep -iE "(dotnet|aspnetcore).*10"
If the packages are found (e.g. dotnet-sdk-10.0, dotnet-runtime-10.0, aspnetcore-runtime-10.0 in the universe component), add them as dotnet_packages for that release.
Fedora — query the Bodhi update system and source RPM spec:
# Check which Fedora releases have dotnet builds
curl -s "https://bodhi.fedoraproject.org/updates/?packages=dotnet{major}.{minor}&rows_per_page=20" \
| python3 -c "
import sys, json
for u in json.load(sys.stdin).get('updates', []):
print(f\"{u['release']['name']}: {u['title']} ({u['status']})\")"
For example, to check .NET 10.0:
curl -s "https://bodhi.fedoraproject.org/updates/?packages=dotnet10.0&rows_per_page=20" \
| python3 -c "
import sys, json
for u in json.load(sys.stdin).get('updates', []):
print(f\"{u['release']['name']}: {u['title']} ({u['status']})\")"
Results show each Fedora release with its build status (e.g. F44: dotnet10.0-10.0.104-1.fc44 (testing)). To confirm the subpackage names, check the spec file:
curl -s "https://src.fedoraproject.org/rpms/dotnet{major}.{minor}/blob/f{release}/f/dotnet{major}.{minor}.spec" \
| grep -E "^%package|^Name:"
Fedora packages follow a consistent naming scheme (dotnet-sdk-{major}.{minor}, dotnet-runtime-{major}.{minor}, aspnetcore-runtime-{major}.{minor}), so this is mainly a confirmation step.
Other distros — Alpine packages can be checked at pkgs.alpinelinux.org. For most other distros, pkgs.org covers them well. Only fall back to direct queries when pkgs.org is missing data for a release you expect to have packages.
6. Present summary
Show the user a summary of which distros+releases have packages and from which feeds, and flag any gaps (supported distro but no packages found).
Regenerate markdown
After any JSON changes, regenerate both markdown files:
release-notes generate dotnet-dependencies {version} release-notes
release-notes generate dotnet-packages {version} release-notes
dotnet-dependencies.md— what OS packages .NET requires (from dependency data)dotnet-packages.md— where to get .NET packages (fromdotnet_packages/dotnet_packages_otherdata)
Important: Do not hand-edit these markdown files. They are generated from the distros/ JSON files. If the output needs to change, update the generator or template in dotnet-release.
Commit
git add release-notes/{version}/distros/ release-notes/{version}/dotnet-dependencies.md release-notes/{version}/dotnet-packages.md
git commit -m "Update {version} distro packages — <summary>"
Known alternative feed commands
When packages come from a non-builtin feed, the install_command field tells users how to register that feed before installing packages. Use the exact commands below.
Ubuntu backports PPA
Feed name: backports
sudo apt-get install -y software-properties-common && sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update
This PPA provides .NET packages for older Ubuntu LTS releases that don't carry .NET in the default archive. add-apt-repository comes from software-properties-common, which is often missing in containers and other minimal environments. After registering, packages are installed with the normal apt-get install command.
Microsoft packages.microsoft.com (PMC)
Feed name: microsoft
wget https://packages.microsoft.com/config/{distro}/{version}/packages-microsoft-prod.deb -O /tmp/packages-microsoft-prod.deb && sudo dpkg -i /tmp/packages-microsoft-prod.deb && rm /tmp/packages-microsoft-prod.deb
Replace {distro} and {version} with the distro name and version (e.g. ubuntu/22.04, debian/12). Note: Microsoft is phasing out PMC for Ubuntu 24.04+ — prefer the builtin or backports feed when available.
Other feeds
If the query returns a feed name not listed above, ask the user for the registration command. Do not guess — incorrect feed setup commands are worse than none.
Key facts
- Files are version-scoped —
release-notes/11.0/distros/ubuntu.jsonis about .NET 11.0 on Ubuntu - Dependencies use an agnostic
id(e.g.libicu) with a distro-specificname(e.g.libicu74) dependencies.jsonis the "what .NET needs" list; per-distro files map those to real package names- Package names like
libicuare versioned on Debian/Ubuntu (e.g.libicu76) but not on Fedora/RHEL (justlibicu) - Alpine uses a different naming scheme for .NET packages:
dotnet{major}-{component}(e.g.dotnet9-sdk) - Debian/Ubuntu/Fedora use:
dotnet-sdk-{major}.{minor},dotnet-runtime-{major}.{minor} - Microsoft is phasing out packages.microsoft.com for Ubuntu 24.04+ and newer Fedora
install_commanduses{packages}as a placeholder for the package list
Display name rules
The name fields (both top-level distro name and per-release names) must use full display names, never acronyms. These names appear in generated markdown and user-facing documentation.
| ❌ Acronym | ✅ Full display name |
|---|---|
| RHEL | Red Hat Enterprise Linux |
| SLES | SUSE Linux Enterprise Server |
Examples:
- Top-level:
"name": "Red Hat Enterprise Linux"(not"RHEL") - Release:
"name": "Red Hat Enterprise Linux 9"(not"RHEL 9") - Top-level:
"name": "SUSE Linux Enterprise Server"(not"SLES") - Release:
"name": "SUSE Linux Enterprise Server 15.7"(not"SLES 15.7")
File names (rhel.json, sles.json) remain short — only the name fields inside must use full names. When creating new distro files or adding releases, always verify the display name is the full product name, not an abbreviation.