1#!/usr/bin/env nix-shell
2#!nix-shell -I nixpkgs=../../../../. -i bash -p curl jq nix gnused
3# shellcheck shell=bash
4
5set -euo pipefail
6
7release () {
8 local content="$1"
9 local version="$2"
10
11 jq -r '.releases[] | select(."release-version" == "'"$version"'")' <<< "$content"
12}
13
14release_files () {
15 local release="$1"
16 local type="$2"
17
18 jq -r '[."'"$type"'".files[] | select(.name | test("^.*.tar.gz$"))]' <<< "$release"
19}
20
21release_platform_attr () {
22 local release_files="$1"
23 local platform="$2"
24 local attr="$3"
25
26 jq -r '.[] | select(.rid == "'"$platform"'") | ."'"$attr"'"' <<< "$release_files"
27}
28
29platform_sources () {
30 local release_files="$1"
31 local platforms=( \
32 "x86_64-linux linux-x64" \
33 "aarch64-linux linux-arm64" \
34 "x86_64-darwin osx-x64" \
35 "aarch64-darwin osx-arm64" \
36 )
37
38 echo "srcs = {"
39 for kv in "${platforms[@]}"; do
40 local nix_platform=${kv%% *}
41 local ms_platform=${kv##* }
42
43 local url=$(release_platform_attr "$release_files" "$ms_platform" url)
44 local hash=$(release_platform_attr "$release_files" "$ms_platform" hash)
45
46 [[ -z "$url" || -z "$hash" ]] && continue
47 echo " $nix_platform = {
48 url = \"$url\";
49 sha512 = \"$hash\";
50 };"
51 done
52 echo " };"
53}
54
55generate_package_list() {
56 local version pkgs nuget_url
57 version="$1"
58 shift
59 pkgs=( "$@" )
60
61 nuget_url="$(curl -f "https://api.nuget.org/v3/index.json" | jq --raw-output '.resources[] | select(."@type" == "PackageBaseAddress/3.0.0")."@id"')"
62
63 for pkg in "${pkgs[@]}"; do
64 local url hash
65 url="${nuget_url}${pkg,,}/${version,,}/${pkg,,}.${version,,}.nupkg"
66 hash="$(nix-prefetch-url "$url")"
67 echo " (fetchNuGet { pname = \"${pkg}\"; version = \"${version}\"; sha256 = \"${hash}\"; })"
68 done
69}
70
71version_older () {
72 cur_version=$1
73 max_version=$2
74 result=$(nix-instantiate -I ../../../../. \
75 --eval -E "(import <nixpkgs> {}).lib.versionOlder \"$cur_version\" \"$max_version\"")
76 if [[ "$result" == "true" ]]; then
77 return 0
78 else
79 return 1
80 fi
81}
82
83aspnetcore_packages () {
84 local version=$1
85 # These packages are implicitly references by the build process,
86 # based on the specific project configurations (RIDs, used features, etc.)
87 # They are always referenced with the same version as the SDK used for building.
88 # Since we lock nuget dependencies, when these packages are included in the generated
89 # lock files (deps.nix), every update of SDK required those lock files to be
90 # updated to reflect the new versions of these packages - otherwise, the build
91 # would fail due to missing dependencies.
92 #
93 # Moving them to a separate list stored alongside the SDK package definitions,
94 # and implicitly including them along in buildDotnetModule allows us
95 # to make updating .NET SDK packages a lot easier - we now just update
96 # the versions of these packages in one place, and all packages that
97 # use buildDotnetModule continue building with the new .NET version without changes.
98 #
99 # Keep in mind that there is no canonical list of these implicitly
100 # referenced packages - this list was created based on looking into
101 # the deps.nix files of existing packages, and which dependencies required
102 # updating after a SDK version bump.
103 #
104 # Due to this, make sure to check if new SDK versions introduce any new packages.
105 # This should not happend in minor or bugfix updates, but probably happens
106 # with every new major .NET release.
107 local pkgs=( \
108 "Microsoft.AspNetCore.App.Runtime.linux-arm" \
109 "Microsoft.AspNetCore.App.Runtime.linux-arm64" \
110 "Microsoft.AspNetCore.App.Runtime.linux-musl-arm64" \
111 "Microsoft.AspNetCore.App.Runtime.linux-musl-x64" \
112 "Microsoft.AspNetCore.App.Runtime.linux-x64" \
113 "Microsoft.AspNetCore.App.Runtime.osx-x64" \
114 "Microsoft.AspNetCore.App.Runtime.win-arm" \
115 "Microsoft.AspNetCore.App.Runtime.win-arm64" \
116 "Microsoft.AspNetCore.App.Runtime.win-x64" \
117 "Microsoft.AspNetCore.App.Runtime.win-x86" \
118 )
119
120 # Packages that only apply to .NET 6 and up
121 if ! version_older "$version" "6"; then
122 pkgs+=( \
123 "Microsoft.AspNetCore.App.Ref" \
124 "Microsoft.AspNetCore.App.Runtime.linux-musl-arm" \
125 "Microsoft.AspNetCore.App.Runtime.osx-arm64" \
126 )
127 fi
128
129
130 generate_package_list "$version" "${pkgs[@]}"
131}
132
133sdk_packages () {
134 local version=$1
135 # These packages are implicitly references by the build process,
136 # based on the specific project configurations (RIDs, used features, etc.)
137 # They are always referenced with the same version as the SDK used for building.
138 # Since we lock nuget dependencies, when these packages are included in the generated
139 # lock files (deps.nix), every update of SDK required those lock files to be
140 # updated to reflect the new versions of these packages - otherwise, the build
141 # would fail due to missing dependencies.
142 #
143 # Moving them to a separate list stored alongside the SDK package definitions,
144 # and implicitly including them along in buildDotnetModule allows us
145 # to make updating .NET SDK packages a lot easier - we now just update
146 # the versions of these packages in one place, and all packages that
147 # use buildDotnetModule continue building with the new .NET version without changes.
148 #
149 # Keep in mind that there is no canonical list of these implicitly
150 # referenced packages - this list was created based on looking into
151 # the deps.nix files of existing packages, and which dependencies required
152 # updating after a SDK version bump.
153 #
154 # Due to this, make sure to check if new SDK versions introduce any new packages.
155 # This should not happend in minor or bugfix updates, but probably happens
156 # with every new major .NET release.
157 local pkgs=( \
158 "Microsoft.NETCore.App.Host.linux-arm" \
159 "Microsoft.NETCore.App.Host.linux-arm64" \
160 "Microsoft.NETCore.App.Host.linux-musl-arm64" \
161 "Microsoft.NETCore.App.Host.linux-musl-x64" \
162 "Microsoft.NETCore.App.Host.linux-x64" \
163 "Microsoft.NETCore.App.Host.osx-x64" \
164 "Microsoft.NETCore.App.Host.win-arm" \
165 "Microsoft.NETCore.App.Host.win-arm64" \
166 "Microsoft.NETCore.App.Host.win-x64" \
167 "Microsoft.NETCore.App.Host.win-x86" \
168 "Microsoft.NETCore.App.Runtime.linux-arm" \
169 "Microsoft.NETCore.App.Runtime.linux-arm64" \
170 "Microsoft.NETCore.App.Runtime.linux-musl-arm64" \
171 "Microsoft.NETCore.App.Runtime.linux-musl-x64" \
172 "Microsoft.NETCore.App.Runtime.linux-x64" \
173 "Microsoft.NETCore.App.Runtime.osx-x64" \
174 "Microsoft.NETCore.App.Runtime.win-arm" \
175 "Microsoft.NETCore.App.Runtime.win-arm64" \
176 "Microsoft.NETCore.App.Runtime.win-x64" \
177 "Microsoft.NETCore.App.Runtime.win-x86" \
178 "Microsoft.NETCore.DotNetAppHost" \
179 "Microsoft.NETCore.DotNetHost" \
180 "Microsoft.NETCore.DotNetHostPolicy" \
181 "Microsoft.NETCore.DotNetHostResolver" \
182 "runtime.linux-arm64.Microsoft.NETCore.DotNetAppHost" \
183 "runtime.linux-arm64.Microsoft.NETCore.DotNetHost" \
184 "runtime.linux-arm64.Microsoft.NETCore.DotNetHostPolicy" \
185 "runtime.linux-arm64.Microsoft.NETCore.DotNetHostResolver" \
186 "runtime.linux-arm.Microsoft.NETCore.DotNetAppHost" \
187 "runtime.linux-arm.Microsoft.NETCore.DotNetHost" \
188 "runtime.linux-arm.Microsoft.NETCore.DotNetHostPolicy" \
189 "runtime.linux-arm.Microsoft.NETCore.DotNetHostResolver" \
190 "runtime.linux-musl-arm64.Microsoft.NETCore.DotNetAppHost" \
191 "runtime.linux-musl-arm64.Microsoft.NETCore.DotNetHost" \
192 "runtime.linux-musl-arm64.Microsoft.NETCore.DotNetHostPolicy" \
193 "runtime.linux-musl-arm64.Microsoft.NETCore.DotNetHostResolver" \
194 "runtime.linux-musl-x64.Microsoft.NETCore.DotNetAppHost" \
195 "runtime.linux-musl-x64.Microsoft.NETCore.DotNetHost" \
196 "runtime.linux-musl-x64.Microsoft.NETCore.DotNetHostPolicy" \
197 "runtime.linux-musl-x64.Microsoft.NETCore.DotNetHostResolver" \
198 "runtime.linux-x64.Microsoft.NETCore.DotNetAppHost" \
199 "runtime.linux-x64.Microsoft.NETCore.DotNetHost" \
200 "runtime.linux-x64.Microsoft.NETCore.DotNetHostPolicy" \
201 "runtime.linux-x64.Microsoft.NETCore.DotNetHostResolver" \
202 "runtime.osx-x64.Microsoft.NETCore.DotNetAppHost" \
203 "runtime.osx-x64.Microsoft.NETCore.DotNetHost" \
204 "runtime.osx-x64.Microsoft.NETCore.DotNetHostPolicy" \
205 "runtime.osx-x64.Microsoft.NETCore.DotNetHostResolver" \
206 "runtime.win-arm64.Microsoft.NETCore.DotNetAppHost" \
207 "runtime.win-arm64.Microsoft.NETCore.DotNetHost" \
208 "runtime.win-arm64.Microsoft.NETCore.DotNetHostPolicy" \
209 "runtime.win-arm64.Microsoft.NETCore.DotNetHostResolver" \
210 "runtime.win-arm.Microsoft.NETCore.DotNetAppHost" \
211 "runtime.win-arm.Microsoft.NETCore.DotNetHost" \
212 "runtime.win-arm.Microsoft.NETCore.DotNetHostPolicy" \
213 "runtime.win-arm.Microsoft.NETCore.DotNetHostResolver" \
214 "runtime.win-x64.Microsoft.NETCore.DotNetAppHost" \
215 "runtime.win-x64.Microsoft.NETCore.DotNetHost" \
216 "runtime.win-x64.Microsoft.NETCore.DotNetHostPolicy" \
217 "runtime.win-x64.Microsoft.NETCore.DotNetHostResolver" \
218 "runtime.win-x86.Microsoft.NETCore.DotNetAppHost" \
219 "runtime.win-x86.Microsoft.NETCore.DotNetHost" \
220 "runtime.win-x86.Microsoft.NETCore.DotNetHostPolicy" \
221 "runtime.win-x86.Microsoft.NETCore.DotNetHostResolver" \
222 "Microsoft.NETCore.App.Composite" \
223 "Microsoft.NETCore.App.Host.linux-musl-arm" \
224 "Microsoft.NETCore.App.Host.osx-arm64" \
225 "Microsoft.NETCore.App.Runtime.linux-musl-arm" \
226 "Microsoft.NETCore.App.Runtime.osx-arm64" \
227 "Microsoft.NETCore.App.Ref" \
228 "Microsoft.NETCore.App.Runtime.Mono.linux-arm" \
229 "Microsoft.NETCore.App.Runtime.Mono.linux-arm64" \
230 "Microsoft.NETCore.App.Runtime.Mono.linux-musl-x64" \
231 "Microsoft.NETCore.App.Runtime.Mono.linux-x64" \
232 "Microsoft.NETCore.App.Runtime.Mono.osx-arm64" \
233 "Microsoft.NETCore.App.Runtime.Mono.osx-x64" \
234 "Microsoft.NETCore.App.Runtime.Mono.win-x64" \
235 "Microsoft.NETCore.App.Runtime.Mono.win-x86" \
236 "runtime.linux-musl-arm.Microsoft.NETCore.DotNetAppHost" \
237 "runtime.linux-musl-arm.Microsoft.NETCore.DotNetHost" \
238 "runtime.linux-musl-arm.Microsoft.NETCore.DotNetHostPolicy" \
239 "runtime.linux-musl-arm.Microsoft.NETCore.DotNetHostResolver" \
240 "runtime.osx-arm64.Microsoft.NETCore.DotNetAppHost" \
241 "runtime.osx-arm64.Microsoft.NETCore.DotNetHost" \
242 "runtime.osx-arm64.Microsoft.NETCore.DotNetHostPolicy" \
243 "runtime.osx-arm64.Microsoft.NETCore.DotNetHostResolver" \
244 )
245
246 # Packages that only apply to .NET 7 and up
247 if ! version_older "$version" "7"; then
248 # ILCompiler requires nixpkgs#181373 to be fixed to work properly
249 pkgs+=( \
250 "runtime.linux-arm64.Microsoft.DotNet.ILCompiler" \
251 "runtime.linux-musl-arm64.Microsoft.DotNet.ILCompiler" \
252 "runtime.linux-musl-x64.Microsoft.DotNet.ILCompiler" \
253 "runtime.linux-x64.Microsoft.DotNet.ILCompiler" \
254 "runtime.osx-x64.Microsoft.DotNet.ILCompiler" \
255 "runtime.win-arm64.Microsoft.DotNet.ILCompiler" \
256 "runtime.win-x64.Microsoft.DotNet.ILCompiler" \
257 )
258 fi
259
260 generate_package_list "$version" "${pkgs[@]}"
261}
262
263main () {
264 pname=$(basename "$0")
265 if [[ ! "$*" =~ ^.*[0-9]{1,}\.[0-9]{1,}.*$ ]]; then
266 echo "Usage: $pname [sem-versions]
267Get updated dotnet src (platform - url & sha512) expressions for specified versions
268
269Examples:
270 $pname 6.0.14 7.0.201 - specific x.y.z versions
271 $pname 6.0 7.0 - latest x.y versions
272" >&2
273 exit 1
274 fi
275
276 for sem_version in "$@"; do
277 echo "Generating ./versions/${sem_version}.nix"
278 patch_specified=false
279 # Check if a patch was specified as an argument.
280 # If so, generate file for the specific version.
281 # If only x.y version was provided, get the latest patch
282 # version of the given x.y version.
283 if [[ "$sem_version" =~ ^[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}$ ]]; then
284 patch_specified=true
285 elif [[ ! "$sem_version" =~ ^[0-9]{1,}\.[0-9]{1,}$ ]]; then
286 continue
287 fi
288
289 # Make sure the x.y version is properly passed to .NET release metadata url.
290 # Then get the json file and parse it to find the latest patch release.
291 major_minor=$(sed 's/^\([0-9]*\.[0-9]*\).*$/\1/' <<< "$sem_version")
292 content=$(curl -sL https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/"$major_minor"/releases.json)
293 major_minor_patch=$([ "$patch_specified" == true ] && echo "$sem_version" || jq -r '."latest-release"' <<< "$content")
294 major_minor_underscore=${major_minor/./_}
295
296 release_content=$(release "$content" "$major_minor_patch")
297 aspnetcore_version=$(jq -r '."aspnetcore-runtime".version' <<< "$release_content")
298 runtime_version=$(jq -r '.runtime.version' <<< "$release_content")
299 sdk_version=$(jq -r '.sdk.version' <<< "$release_content")
300
301 # If patch was not specified, check if the package is already the latest version
302 # If it is, exit early
303 if [ "$patch_specified" == false ] && [ -f "./versions/${sem_version}.nix" ]; then
304 current_version=$(nix-instantiate --eval -E "(import ./versions/${sem_version}.nix { \
305 buildAspNetCore = { ... }: {}; \
306 buildNetRuntime = { ... }: {}; \
307 buildNetSdk = { version, ... }: version; \
308 }).sdk_${major_minor_underscore}" | jq -r)
309
310 if [[ "$current_version" == "$sdk_version" ]]; then
311 echo "Nothing to update."
312 exit
313 fi
314 fi
315
316 aspnetcore_files="$(release_files "$release_content" "aspnetcore-runtime")"
317 runtime_files="$(release_files "$release_content" "runtime")"
318 sdk_files="$(release_files "$release_content" "sdk")"
319
320 channel_version=$(jq -r '."channel-version"' <<< "$content")
321 support_phase=$(jq -r '."support-phase"' <<< "$content")
322 echo "{ buildAspNetCore, buildNetRuntime, buildNetSdk }:
323
324# v$channel_version ($support_phase)
325{
326 aspnetcore_$major_minor_underscore = buildAspNetCore {
327 version = \"${aspnetcore_version}\";
328 $(platform_sources "$aspnetcore_files")
329 };
330
331 runtime_$major_minor_underscore = buildNetRuntime {
332 version = \"${runtime_version}\";
333 $(platform_sources "$runtime_files")
334 };
335
336 sdk_$major_minor_underscore = buildNetSdk {
337 version = \"${sdk_version}\";
338 $(platform_sources "$sdk_files")
339 packages = { fetchNuGet }: [
340$(aspnetcore_packages "${aspnetcore_version}")
341$(sdk_packages "${runtime_version}")
342 ];
343 };
344}" > "./versions/${sem_version}.nix"
345 echo "Generated ./versions/${sem_version}.nix"
346 done
347}
348
349main "$@"