Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/dotnet/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ Installing only the latest .NET SDK version (the default).

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

``` json
``` jsonc
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "latest", // (this can be omitted)
"additionalVersions": "lts"
}
}
Expand Down Expand Up @@ -71,6 +72,19 @@ Installing .NET workloads. Multiple workloads can be specified as comma-separate
}
```

Installing prerelease builds. Supports `preview` and `daily` suffixes.

``` json
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "10.0-preview",
"additionalVersions": "10.0.1xx-daily",
"dotnetRuntimeVersions": "10.0-daily",
"aspnetCoreRuntimeVersions": "10.0-daily"
}
}
```

## OS Support

This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
Expand Down
13 changes: 8 additions & 5 deletions src/dotnet/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "dotnet",
"version": "2.3.0",
"version": "2.4.0",
"name": "Dotnet CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet",
"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.",
Expand All @@ -11,28 +11,31 @@
"latest",
"lts",
"none",
"10.0",
"10.0-preview",
"10.0-daily",
"9.0",
"8.0",
"7.0",
"6.0"
],
"default": "latest",
"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."
"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."
},
"additionalVersions": {
"type": "string",
"default": "",
"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."
"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."
},
"dotnetRuntimeVersions": {
"type": "string",
"default": "",
"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."
"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."
},
"aspNetCoreRuntimeVersions": {
"type": "string",
"default": "",
"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."
"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."
},
"workloads": {
"type": "string",
Expand Down
20 changes: 15 additions & 5 deletions src/dotnet/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,27 @@ done
check_packages wget ca-certificates icu-devtools

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

for version in "${dotnetRuntimeVersions[@]}"; do
install_runtime "dotnet" "$version"
read -r clean_version quality < <(parse_version_and_quality "$version")
if [ -n "$quality" ]; then
echo "Interpreting requested runtime version '$version' as version '$clean_version' with quality '$quality'"
fi
install_runtime "dotnet" "$clean_version" "$quality"
done

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

workloads=()
Expand Down
94 changes: 76 additions & 18 deletions src/dotnet/scripts/dotnet-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ fetch_latest_version() {
}

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

# Currently this script does not make it possible to qualify the version, 'GA' is always implied
echo "Executing $DOTNET_INSTALL_SCRIPT --version $version --channel $channel --install-dir $DOTNET_ROOT"
"$DOTNET_INSTALL_SCRIPT" \
--version "$version" \
--channel "$channel" \
--install-dir "$DOTNET_ROOT"
local cmd=("$DOTNET_INSTALL_SCRIPT" "--version" "$version" "--install-dir" "$DOTNET_ROOT")
if [ -n "$channel" ]; then
cmd+=("--channel" "$channel")
fi
if [ -n "$quality" ]; then
cmd+=("--quality" "$quality")
fi
echo "Executing ${cmd[*]}"
"${cmd[@]}"
}

# Installs a version of the .NET Runtime
# Usage: install_runtime <runtime> <version>
# Usage: install_runtime <runtime> <version> [<quality>]
# Example: install_runtime "dotnet" "9.0"
# Example: install_runtime "aspnetcore" "10.0" "preview"
install_runtime() {
local runtime="$1"
local inputVersion="$2"
local inputVersion="$2" # Could be 'latest', 'lts', 'X.Y', 'X.Y.Z'
local quality="$3" # Optional quality: GA, preview, daily (empty implies GA)
local version=""
local channel=""
if [[ "$inputVersion" == "latest" ]]; then
Expand All @@ -105,14 +114,16 @@ install_runtime() {
# Assume version is an exact version string like '6.0.21' or '8.0.0-preview.7.23375.6'
version="$inputVersion"
fi

echo "Executing $DOTNET_INSTALL_SCRIPT --runtime $runtime --version $version --channel $channel --install-dir $DOTNET_ROOT --no-path"
"$DOTNET_INSTALL_SCRIPT" \
--runtime "$runtime" \
--version "$version" \
--channel "$channel" \
--install-dir "$DOTNET_ROOT" \
--no-path

local cmd=("$DOTNET_INSTALL_SCRIPT" "--runtime" "$runtime" "--version" "$version" "--install-dir" "$DOTNET_ROOT" "--no-path")
if [ -n "$channel" ]; then
cmd+=("--channel" "$channel")
fi
if [ -n "$quality" ]; then
cmd+=("--quality" "$quality")
fi
echo "Executing ${cmd[*]}"
"${cmd[@]}"
}

# Installs one or more .NET workloads
Expand All @@ -127,3 +138,50 @@ install_workloads() {
# Clean up
rm -r /tmp/dotnet-workload-temp-dir
}

# Input: version spec possibly containing -preview or -daily
# Supports channels in the forms:
# A.B (e.g. 10.0)
# A.B.Cxx (feature band e.g. 6.0.4xx)
# A.B-preview (adds quality)
# A.B-daily
# A.B.Cxx-preview
# A.B.Cxx-daily
# Output (stdout): "<clean_version> <quality>"
# - For channel specs (A.B or A.B.Cxx) without suffix -> quality is GA
# - For channel specs with -preview/-daily suffix -> quality is preview/daily
# - 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
# Examples:
# parse_version_and_quality "10.0-preview" => "10.0 preview"
# parse_version_and_quality "10.0-daily" => "10.0 daily"
# parse_version_and_quality "10.0" => "10.0 GA"
# parse_version_and_quality "6.0.4xx" => "6.0.4xx GA"
# parse_version_and_quality "6.0.4xx-preview" => "6.0.4xx preview"
# parse_version_and_quality "6.0.4xx-daily" => "6.0.4xx daily"
parse_version_and_quality() {
local input="$1"
local quality=""
local clean_version="$input"
# Match feature band with quality
if [[ "$input" =~ ^([0-9]+\.[0-9]+\.[0-9]xx)-(preview|daily)$ ]]; then
clean_version="${BASH_REMATCH[1]}"
quality="${BASH_REMATCH[2]}"
# Match simple channel with quality
elif [[ "$input" =~ ^([0-9]+\.[0-9]+)-(preview|daily)$ ]]; then
clean_version="${BASH_REMATCH[1]}"
quality="${BASH_REMATCH[2]}"
# Match plain feature band channel (defaults to GA)
elif [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]xx$ ]]; then
clean_version="$input"
quality="GA"
# Match simple channel (defaults to GA)
elif [[ "$input" =~ ^[0-9]+\.[0-9]+$ ]]; then
clean_version="$input"
quality="GA"
else
# Exact version (leave quality empty)
clean_version="$input"
quality=""
fi
echo "$clean_version" "$quality"
}
Loading