Skip to content

Commit 572770d

Browse files
authored
dotnet: add support for prerelease versions (#1470)
* dotnet: add support for prerelease versions * Add 'additionalVersions' tests * Improve handling of empty 'channel' and 'quality' values * Fix invalid version spec in aspnetCoreRuntimeVersions
1 parent 0a82ddb commit 572770d

File tree

9 files changed

+194
-173
lines changed

9 files changed

+194
-173
lines changed

src/dotnet/NOTES.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ Installing only the latest .NET SDK version (the default).
1010

1111
Installing an additional SDK version. Multiple versions can be specified as comma-separated values.
1212

13-
``` json
13+
``` jsonc
1414
"features": {
1515
"ghcr.io/devcontainers/features/dotnet:2": {
16+
"version": "latest", // (this can be omitted)
1617
"additionalVersions": "lts"
1718
}
1819
}
@@ -71,6 +72,19 @@ Installing .NET workloads. Multiple workloads can be specified as comma-separate
7172
}
7273
```
7374

75+
Installing prerelease builds. Supports `preview` and `daily` suffixes.
76+
77+
``` json
78+
"features": {
79+
"ghcr.io/devcontainers/features/dotnet:2": {
80+
"version": "10.0-preview",
81+
"additionalVersions": "10.0.1xx-daily",
82+
"dotnetRuntimeVersions": "10.0-daily",
83+
"aspnetCoreRuntimeVersions": "10.0-daily"
84+
}
85+
}
86+
```
87+
7488
## OS Support
7589

7690
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.

src/dotnet/devcontainer-feature.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "dotnet",
3-
"version": "2.3.0",
3+
"version": "2.4.0",
44
"name": "Dotnet CLI",
55
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet",
66
"description": "This Feature installs the latest .NET SDK, which includes the .NET CLI and the shared runtime. Options are provided to choose a different version or additional versions.",
@@ -11,28 +11,31 @@
1111
"latest",
1212
"lts",
1313
"none",
14+
"10.0",
1415
"10.0-preview",
16+
"10.0-daily",
17+
"9.0",
1518
"8.0",
1619
"7.0",
1720
"6.0"
1821
],
1922
"default": "latest",
20-
"description": "Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
23+
"description": "Select or enter a .NET SDK version. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases."
2124
},
2225
"additionalVersions": {
2326
"type": "string",
2427
"default": "",
25-
"description": "Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
28+
"description": "Enter additional .NET SDK versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases."
2629
},
2730
"dotnetRuntimeVersions": {
2831
"type": "string",
2932
"default": "",
30-
"description": "Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
33+
"description": "Enter additional .NET runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases."
3134
},
3235
"aspNetCoreRuntimeVersions": {
3336
"type": "string",
3437
"default": "",
35-
"description": "Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version."
38+
"description": "Enter additional ASP.NET Core runtime versions, separated by commas. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X.Y' or 'X.Y.Z' for a specific version, 'X.Y-preview' or 'X.Y-daily' for prereleases."
3639
},
3740
"workloads": {
3841
"type": "string",

src/dotnet/install.sh

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,27 @@ done
108108
check_packages wget ca-certificates icu-devtools
109109

110110
for version in "${versions[@]}"; do
111-
# Remove '-preview' from version if suffixed with the version label
112-
clean_version="$(echo "$version" | sed 's/-preview$//')"
113-
install_sdk "$clean_version"
111+
read -r clean_version quality < <(parse_version_and_quality "$version")
112+
if [ -n "$quality" ]; then
113+
echo "Interpreting requested version '$version' as version '$clean_version' with quality '$quality'"
114+
fi
115+
install_sdk "$clean_version" "$quality"
114116
done
115117

116118
for version in "${dotnetRuntimeVersions[@]}"; do
117-
install_runtime "dotnet" "$version"
119+
read -r clean_version quality < <(parse_version_and_quality "$version")
120+
if [ -n "$quality" ]; then
121+
echo "Interpreting requested runtime version '$version' as version '$clean_version' with quality '$quality'"
122+
fi
123+
install_runtime "dotnet" "$clean_version" "$quality"
118124
done
119125

120126
for version in "${aspNetCoreRuntimeVersions[@]}"; do
121-
install_runtime "aspnetcore" "$version"
127+
read -r clean_version quality < <(parse_version_and_quality "$version")
128+
if [ -n "$quality" ]; then
129+
echo "Interpreting requested ASP.NET Core runtime version '$version' as version '$clean_version' with quality '$quality'"
130+
fi
131+
install_runtime "aspnetcore" "$clean_version" "$quality"
122132
done
123133

124134
workloads=()

src/dotnet/scripts/dotnet-helpers.sh

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@ fetch_latest_version() {
4545
}
4646

4747
# Installs a version of the .NET SDK
48-
# Usage: install_sdk <version>
48+
# Usage: install_sdk <version> [<quality>]
49+
# Example: install_sdk "9.0"
50+
# Example: install_sdk "10.0" "preview"
4951
install_sdk() {
50-
local inputVersion="$1"
52+
local inputVersion="$1" # Could be 'latest', 'lts', 'X.Y', 'X.Y.Z', 'X.Y.4xx', or base channel when paired with quality
53+
local quality="$2" # Optional quality: GA, preview, daily (empty implies GA)
5154
local version=""
5255
local channel=""
5356
if [[ "$inputVersion" == "latest" ]]; then
@@ -73,19 +76,25 @@ install_sdk() {
7376
version="$inputVersion"
7477
fi
7578

76-
# Currently this script does not make it possible to qualify the version, 'GA' is always implied
77-
echo "Executing $DOTNET_INSTALL_SCRIPT --version $version --channel $channel --install-dir $DOTNET_ROOT"
78-
"$DOTNET_INSTALL_SCRIPT" \
79-
--version "$version" \
80-
--channel "$channel" \
81-
--install-dir "$DOTNET_ROOT"
79+
local cmd=("$DOTNET_INSTALL_SCRIPT" "--version" "$version" "--install-dir" "$DOTNET_ROOT")
80+
if [ -n "$channel" ]; then
81+
cmd+=("--channel" "$channel")
82+
fi
83+
if [ -n "$quality" ]; then
84+
cmd+=("--quality" "$quality")
85+
fi
86+
echo "Executing ${cmd[*]}"
87+
"${cmd[@]}"
8288
}
8389

8490
# Installs a version of the .NET Runtime
85-
# Usage: install_runtime <runtime> <version>
91+
# Usage: install_runtime <runtime> <version> [<quality>]
92+
# Example: install_runtime "dotnet" "9.0"
93+
# Example: install_runtime "aspnetcore" "10.0" "preview"
8694
install_runtime() {
8795
local runtime="$1"
88-
local inputVersion="$2"
96+
local inputVersion="$2" # Could be 'latest', 'lts', 'X.Y', 'X.Y.Z'
97+
local quality="$3" # Optional quality: GA, preview, daily (empty implies GA)
8998
local version=""
9099
local channel=""
91100
if [[ "$inputVersion" == "latest" ]]; then
@@ -105,14 +114,16 @@ install_runtime() {
105114
# Assume version is an exact version string like '6.0.21' or '8.0.0-preview.7.23375.6'
106115
version="$inputVersion"
107116
fi
108-
109-
echo "Executing $DOTNET_INSTALL_SCRIPT --runtime $runtime --version $version --channel $channel --install-dir $DOTNET_ROOT --no-path"
110-
"$DOTNET_INSTALL_SCRIPT" \
111-
--runtime "$runtime" \
112-
--version "$version" \
113-
--channel "$channel" \
114-
--install-dir "$DOTNET_ROOT" \
115-
--no-path
117+
118+
local cmd=("$DOTNET_INSTALL_SCRIPT" "--runtime" "$runtime" "--version" "$version" "--install-dir" "$DOTNET_ROOT" "--no-path")
119+
if [ -n "$channel" ]; then
120+
cmd+=("--channel" "$channel")
121+
fi
122+
if [ -n "$quality" ]; then
123+
cmd+=("--quality" "$quality")
124+
fi
125+
echo "Executing ${cmd[*]}"
126+
"${cmd[@]}"
116127
}
117128

118129
# Installs one or more .NET workloads
@@ -127,3 +138,50 @@ install_workloads() {
127138
# Clean up
128139
rm -r /tmp/dotnet-workload-temp-dir
129140
}
141+
142+
# Input: version spec possibly containing -preview or -daily
143+
# Supports channels in the forms:
144+
# A.B (e.g. 10.0)
145+
# A.B.Cxx (feature band e.g. 6.0.4xx)
146+
# A.B-preview (adds quality)
147+
# A.B-daily
148+
# A.B.Cxx-preview
149+
# A.B.Cxx-daily
150+
# Output (stdout): "<clean_version> <quality>"
151+
# - For channel specs (A.B or A.B.Cxx) without suffix -> quality is GA
152+
# - For channel specs with -preview/-daily suffix -> quality is preview/daily
153+
# - For exact version specs (contain a third numeric segment or prerelease labels beyond channel patterns, e.g. 8.0.100-rc.2.23502.2) -> quality is empty
154+
# Examples:
155+
# parse_version_and_quality "10.0-preview" => "10.0 preview"
156+
# parse_version_and_quality "10.0-daily" => "10.0 daily"
157+
# parse_version_and_quality "10.0" => "10.0 GA"
158+
# parse_version_and_quality "6.0.4xx" => "6.0.4xx GA"
159+
# parse_version_and_quality "6.0.4xx-preview" => "6.0.4xx preview"
160+
# parse_version_and_quality "6.0.4xx-daily" => "6.0.4xx daily"
161+
parse_version_and_quality() {
162+
local input="$1"
163+
local quality=""
164+
local clean_version="$input"
165+
# Match feature band with quality
166+
if [[ "$input" =~ ^([0-9]+\.[0-9]+\.[0-9]xx)-(preview|daily)$ ]]; then
167+
clean_version="${BASH_REMATCH[1]}"
168+
quality="${BASH_REMATCH[2]}"
169+
# Match simple channel with quality
170+
elif [[ "$input" =~ ^([0-9]+\.[0-9]+)-(preview|daily)$ ]]; then
171+
clean_version="${BASH_REMATCH[1]}"
172+
quality="${BASH_REMATCH[2]}"
173+
# Match plain feature band channel (defaults to GA)
174+
elif [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]xx$ ]]; then
175+
clean_version="$input"
176+
quality="GA"
177+
# Match simple channel (defaults to GA)
178+
elif [[ "$input" =~ ^[0-9]+\.[0-9]+$ ]]; then
179+
clean_version="$input"
180+
quality="GA"
181+
else
182+
# Exact version (leave quality empty)
183+
clean_version="$input"
184+
quality=""
185+
fi
186+
echo "$clean_version" "$quality"
187+
}

0 commit comments

Comments
 (0)