Compare commits

...

39 commits

Author SHA1 Message Date
JP Ungaretti
7d818c27a8 Check sha256 2023-03-10 23:17:16 +00:00
JP Ungaretti
4b1855cc6c Add lts test 2023-03-03 01:10:12 +00:00
JP Ungaretti
2b64508a1a Add route for LTS option 2023-03-03 00:37:53 +00:00
JP Ungaretti
b00c079602 Update additional versions scenario 2023-03-01 22:13:40 +00:00
JP Ungaretti
de13e76cb7 Revert name change 2023-03-01 19:26:52 +00:00
JP Ungaretti
31b093b161 Merge branch 'jungaretti/dotnet-2' of https://github.com/devcontainers/features into jungaretti/dotnet-2 2023-03-01 19:23:14 +00:00
JP Ungaretti
56e18319ac Add version format to descriptions 2023-03-01 19:22:58 +00:00
JP Ungaretti
dcbd98f08e Run project tests as non-root user 2023-03-01 19:19:02 +00:00
JP Ungaretti
ca6f581c8f Use X.Y.Z to describe version 2023-03-01 19:18:29 +00:00
JP Ungaretti
4011911c2a
Fix version
Co-authored-by: Josh Spicer <joshspicer@github.com>
2023-03-01 10:02:25 -08:00
JP Ungaretti
5bb6f303a1 Finishing touches 2023-03-01 17:22:14 +00:00
JP Ungaretti
387dc5346e Add missing reportResults 2023-03-01 17:20:17 +00:00
JP Ungaretti
c1ce660cac Add scenarios for build and run 2023-03-01 08:29:45 +00:00
JP Ungaretti
b80a77bcb5 Remove assert scripts 2023-03-01 08:24:39 +00:00
JP Ungaretti
c95f761193 Update descriptions and proposals 2023-03-01 08:20:09 +00:00
JP Ungaretti
85505f1804 Use project asserts 2023-03-01 08:15:18 +00:00
JP Ungaretti
1a91d3bf13 Copy project asserts 2023-03-01 08:15:11 +00:00
JP Ungaretti
a091bc67dd Add example_project 2023-03-01 08:10:34 +00:00
JP Ungaretti
ab80288568 Add runtime test 2023-03-01 07:57:41 +00:00
JP Ungaretti
a4746b2feb Update version tests 2023-03-01 07:53:55 +00:00
JP Ungaretti
018003a291 Update additional version test 2023-03-01 07:34:31 +00:00
JP Ungaretti
7d4845e677 Use ls to check install directory 2023-03-01 07:33:44 +00:00
JP Ungaretti
d432ed1d6d Fix quoting bug 2023-03-01 07:07:28 +00:00
JP Ungaretti
6b84b694ad Install additional versions 2023-03-01 02:34:31 +00:00
JP Ungaretti
11d0be5f67 Add echos for version and runtime 2023-03-01 02:15:13 +00:00
JP Ungaretti
a716332dfa Add more helpful version error 2023-03-01 02:08:32 +00:00
JP Ungaretti
1a655bfa0d Rename to runtime_args 2023-03-01 02:02:14 +00:00
JP Ungaretti
f7fa5fc302 Remove lts scenario 2023-03-01 01:41:57 +00:00
JP Ungaretti
2927e6e495 Restore customizations 2023-03-01 01:40:55 +00:00
JP Ungaretti
519c3ef6d6 Clean up comments 2023-03-01 01:37:38 +00:00
JP Ungaretti
1ff0df6f4e Revert test changes 2023-03-01 01:28:09 +00:00
JP Ungaretti
26ba3fb9b7 Add a couple of comments 2023-03-01 01:25:05 +00:00
JP Ungaretti
6b54ebde57 Add install_version helper to parse version 2023-03-01 01:23:13 +00:00
JP Ungaretti
b4b7d05ec8 Mention LTS in version description 2023-03-01 01:20:58 +00:00
JP Ungaretti
00f0c506f7 Clean up installer script 2023-02-28 01:41:48 +00:00
JP Ungaretti
c1daca8958 Bump version and reword all descriptions 2023-02-28 01:40:02 +00:00
JP Ungaretti
31b98d4ddc Remove apt test 2023-02-28 01:07:17 +00:00
JP Ungaretti
d664137814 Rewrite dotnet feature 2023-02-28 00:58:07 +00:00
JP Ungaretti
df4db859fb Add newline 2023-02-28 00:48:56 +00:00
20 changed files with 199 additions and 534 deletions

View file

@ -1,30 +1,31 @@
{
"id": "dotnet",
"version": "1.1.3",
"version": "2.0.0",
"name": "Dotnet CLI",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet",
"description": "Installs the .NET CLI. Provides option of installing sdk or runtime, and option of versions to install. Uses latest version of .NET sdk as defaults to install.",
"description": "Installs .NET and its CLI. Offers options to install a specific version of .NET, additional versions of .NET, or just the .NET runtime.",
"options": {
"version": {
"type": "string",
"proposals": [
"latest",
"lts",
"7",
"6",
"3.1"
"3"
],
"default": "latest",
"description": "Select or enter a dotnet CLI version. (Available versions may vary by Linux distribution.)"
"description": "Version of .NET to install. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X' for the latest of a major version, or 'X.Y.Z' for a specific version."
},
"additionalVersions": {
"type": "string",
"default": "",
"description": "Comma-separated list of additional .NET versions to install. Use 'latest' for the latest version, 'lts' for the latest LTS version, 'X' for the latest of a major version, or 'X.Y.Z' for a specific version."
},
"runtimeOnly": {
"type": "boolean",
"default": false,
"description": "Install just the dotnet runtime if true, and sdk if false."
},
"installUsingApt": {
"type": "boolean",
"default": true,
"description": "If true, it installs using apt instead of the release URL"
"description": "Only install the .NET runtime. If true, then the .NET SDK is not installed."
}
},
"containerEnv": {

View file

@ -4,111 +4,28 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/dotnet.md
# Docs: https://github.com/devcontainers/features/tree/main/src/dotnet
# Maintainer: The VS Code and Codespaces Teams
DOTNET_VERSION="${VERSION:-"latest"}"
DOTNET_ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}"
DOTNET_RUNTIME_ONLY="${RUNTIMEONLY:-"false"}"
OVERRIDE_DEFAULT_VERSION="${OVERRIDEDEFAULTVERSION:-"true"}"
INSTALL_USING_APT="${INSTALLUSINGAPT:-"true"}"
DOTNET_LATEST="7"
DOTNET_LTS="6"
USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
UPDATE_RC="${UPDATE_RC:-"true"}"
TARGET_DOTNET_ROOT="${TARGET_DOTNET_ROOT:-"/usr/local/dotnet"}"
ACCESS_GROUP="${ACCESS_GROUP:-"dotnet"}"
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
DOTNET_ARCHIVE_ARCHITECTURES="amd64"
DOTNET_ARCHIVE_VERSION_CODENAMES="buster bullseye bionic focal hirsute jammy"
# Feed URI sourced from the official dotnet-install.sh
# https://github.com/dotnet/install-scripts/blob/1b98b94a6f6d81cc4845eb88e0195fac67caa0a6/src/dotnet-install.sh#L1342-L1343
DOTNET_CDN_FEED_URI="https://dotnetcli.azureedge.net"
# Ubuntu 22.04 and on do not ship with libssl1.1, which is required for versions of .NET < 6.0
DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1="buster bullseye bionic focal hirsute"
# Comma-separated list of dotnet versions to be installed
# alongside DOTNET_VERSION, but not set as default.
ADDITIONAL_VERSIONS=${ADDITIONALVERSIONS:-""}
DOTNET_INSTALL_SCRIPT_URL='https://dot.net/v1/dotnet-install.sh'
DOTNET_INSTALL_SCRIPT_SHA256='3d5a87bc29fb96e8dac8c2f88d95ff619c3a921903b4c9ff720e07ca0906d55e /tmp/dotnet-install.sh'
DOTNET_INSTALL_SCRIPT='/tmp/dotnet-install.sh'
DOTNET_INSTALL_DIR='/usr/local/dotnet/current'
set -e
# Clean up
rm -rf /var/lib/apt/lists/*
# Setup STDERR.
err() {
echo "(!) $*" >&2
}
# Ensure the appropriate root user is running the script.
if [ "$(id -u)" -ne 0 ]; then
err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user.
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u "${CURRENT_USER}" > /dev/null 2>&1; then
USERNAME="${CURRENT_USER}"
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
###################
# Helper Functions
###################
# Cleanup temporary directory and associated files when exiting the script.
cleanup() {
EXIT_CODE=$?
set +e
if [[ -n "${TMP_DIR}" ]]; then
echo "Executing cleanup of tmp files"
rm -Rf "${TMP_DIR}"
fi
exit $EXIT_CODE
}
trap cleanup EXIT
# Add dotnet directory to PATH in bashrc/zshrc files if OVERRIDE_DEFAULT_VERSION=true.
updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/bash.bashrc
fi
if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi
}
apt_get_update()
{
apt_get_update() {
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
}
# Check if packages are installed and installs them if not.
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update
@ -116,353 +33,73 @@ check_packages() {
fi
}
# Get appropriate architecture name for .NET binaries for the target OS
get_architecture_name_for_target_os() {
local architecture
architecture="$(uname -m)"
case $architecture in
x86_64) architecture="x64";;
aarch64 | armv8*) architecture="arm64";;
*) err "Architecture ${architecture} unsupported"; exit 1 ;;
esac
# Installs a version of .NET using the DOTNET_INSTALLER_SCRIPT
# The version must be 'latest', use the form 'X', or use the form 'X.Y.Z'
install_version() {
local version="$1"
local channel="STS"
local runtime_arg=""
echo "${architecture}"
}
echo "Installing version '$version'..."
# Soft version matching that resolves a version for a given package in the *current apt-cache*
# Return value is stored in first argument (the unprocessed version)
apt_cache_package_and_version_soft_match() {
# Version
local version_variable_name="$1"
local requested_version=${!version_variable_name}
# Package Name
local package_variable_name="$2"
local partial_package_name=${!package_variable_name}
local package_name
# Exit on no match?
local exit_on_no_match="${3:-true}"
local major_minor_version
# Ensure we've exported useful variables
. /etc/os-release
local architecture="$(dpkg --print-architecture)"
major_minor_version="$(echo "${requested_version}" | cut -d "." --field=1,2)"
package_name="$(apt-cache search "${partial_package_name}-[0-9].[0-9]" | awk -F" - " '{print $1}' | grep -m 1 "${partial_package_name}-${major_minor_version}")"
dot_escaped="${requested_version//./\\.}"
dot_plus_escaped="${dot_escaped//+/\\+}"
# Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/
version_regex="^(.+:)?${dot_plus_escaped}([\\.\\+ ~:-]|$)"
set +e # Don't exit if finding version fails - handle gracefully
fuzzy_version="$(apt-cache madison ${package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${version_regex}")"
set -e
if [ -z "${fuzzy_version}" ]; then
echo "(!) No full or partial for package \"${partial_package_name}\" (resolved: \"${package_name}\") match found in apt-cache for \"${requested_version}\" on OS ${ID} ${VERSION_CODENAME} (${architecture})."
if $exit_on_no_match; then
echo "Available versions:"
apt-cache madison ${package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+'
exit 1 # Fail entire script
else
echo "Continuing to fallback method if available"
return 1;
fi
# If version is just a major value (form 'X'), assume it is a channel
if [[ "$version" =~ ^[0-9]+$ ]]; then
channel="$version.0"
version="latest"
fi
# Globally assign fuzzy_version to this value
# Use this value as the return value of this function
declare -g ${version_variable_name}="=${fuzzy_version}"
echo "${version_variable_name} ${!version_variable_name}"
# Globally assign package to this value
# Use this value as the return value of this function
declare -g ${package_variable_name}="${package_name}"
echo "${package_variable_name} ${!package_variable_name}"
}
# Install .NET CLI using apt-get package installer
install_using_apt() {
local sdk_or_runtime="$1"
local target_dotnet_version="$2"
local use_msft_repo="$3"
if [ "${use_msft_repo}" = "true" ]; then
# Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr
# Import key safely and import Microsoft apt repo
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
apt-get update -y
# If version is 'lts', then update the channel
if [ "$version" = "lts" ]; then
channel="LTS"
version="latest"
fi
# .NET 7 is not a LTS version, so handle latest and LTS versions differently
export APT_DOTNET_VERSION="$target_dotnet_version"
if [ "${APT_DOTNET_VERSION}" = "latest" ]; then
APT_DOTNET_VERSION="${DOTNET_LATEST}.0"
elif [ "${APT_DOTNET_VERSION}" = "lts" ]; then
APT_DOTNET_VERSION="${DOTNET_LTS}.0"
fi
# Sets target_dotnet_version and dotnet_package if matches found.
local base_dotnet_package="dotnet-${sdk_or_runtime}"
export DOTNET_PACKAGE="${base_dotnet_package}"
apt_cache_package_and_version_soft_match APT_DOTNET_VERSION DOTNET_PACKAGE false
if [ "$?" != 0 ] || [ ${DOTNET_PACKAGE} == "${base_dotnet_package}" ]; then
echo "Failed to find requested version."
# Make sure the version is formatted correctly (form 'X' is handled before this)
if ! [[ "$version" = "latest" || "$version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then
echo "Invalid version '$version': version must be 'latest' or use the form 'X.Y.Z'"
return 1
fi
if type dotnet > /dev/null 2>&1 && [[ "$(dotnet --version)" == *"${APT_DOTNET_VERSION}"* ]] ; then
echo "dotnet version ${APT_DOTNET_VERSION} is already installed"
return 1
if [ "$DOTNET_RUNTIME_ONLY" = 'true' ]; then
echo "Installing runtime only..."
runtime_arg='--runtime dotnet'
fi
echo "Installing '${DOTNET_PACKAGE}${APT_DOTNET_VERSION}'..."
apt-get install -yq ${DOTNET_PACKAGE}${APT_DOTNET_VERSION}
if [ "$?" != 0 ]; then
echo "Failed to complete apt install of ${DOTNET_PACKAGE}${TARGET_DOTNET_VERSION}"
return 1
fi
# Add symlink for current
CURRENT_DIR="${TARGET_DOTNET_ROOT}/current"
if [[ -d "${CURRENT_DIR}" ]]; then
rm -rf "${CURRENT_DIR}"
fi
mkdir -p "${TARGET_DOTNET_ROOT}"
local dotnet_installed_version="$(dotnet --version)"
# See if its the distro version
if [[ "$(dotnet --info)" == *"Base Path: /usr/lib/dotnet/dotnet${dotnet_installed_version:0:1}-${dotnet_installed_version}"* ]]; then
ln -s "/usr/lib/dotnet/dotnet${dotnet_installed_version:0:1}" "${CURRENT_DIR}"
else
# Location used by MS repo versions
ln -s "/usr/share/dotnet" "${CURRENT_DIR}"
fi
"$DOTNET_INSTALL_SCRIPT" \
--install-dir "$DOTNET_INSTALL_DIR" \
--version "$version" \
--channel "$channel" \
$runtime_arg
}
# Find and extract .NET binary download details based on user-requested version
# args:
# sdk_or_runtime $1
# dotnet_version_to_download $2
# exports:
# DOTNET_DOWNLOAD_URL
# DOTNET_DOWNLOAD_HASH
# DOTNET_DOWNLOAD_NAME
get_full_version_details() {
local sdk_or_runtime="$1"
local architecture
local dotnet_channel_version
local dotnet_releases_url
local dotnet_releases_json
local dotnet_latest_version
local dotnet_download_details
export DOTNET_DOWNLOAD_VERSION="$2"
export DOTNET_DOWNLOAD_URL
export DOTNET_DOWNLOAD_HASH
export DOTNET_DOWNLOAD_NAME
# Set architecture variable to current user's architecture (x64 or ARM64).
architecture="$(get_architecture_name_for_target_os)"
# Set VERSION to empty string to ensure jq includes all .NET versions in reverse sort below
if [ "${DOTNET_DOWNLOAD_VERSION}" = "latest" ]; then
DOTNET_DOWNLOAD_VERSION=""
fi
dotnet_patchless_version="$(echo "${DOTNET_DOWNLOAD_VERSION}" | cut -d "." --field=1,2)"
set +e
dotnet_channel_version="$(curl -s "${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/releases-index.json" | jq -r --arg channel_version "${dotnet_patchless_version}" '[."releases-index"[]] | sort_by(."channel-version") | reverse | map( select(."channel-version" | startswith($channel_version))) | first | ."channel-version"')"
set -e
# Construct the releases URL using the official channel-version if one was found. Otherwise make a best-effort using the user input.
if [ -n "${dotnet_channel_version}" ] && [ "${dotnet_channel_version}" != "null" ]; then
dotnet_releases_url="${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/${dotnet_channel_version}/releases.json"
else
dotnet_releases_url="${DOTNET_CDN_FEED_URI}/dotnet/release-metadata/${dotnet_patchless_version}/releases.json"
fi
set +e
dotnet_releases_json="$(curl -s "${dotnet_releases_url}")"
set -e
if [ -n "${dotnet_releases_json}" ] && [[ ! "${dotnet_releases_json}" = *"Error"* ]]; then
dotnet_latest_version="$(echo "${dotnet_releases_json}" | jq -r --arg sdk_or_runtime "${sdk_or_runtime}" '."latest-\($sdk_or_runtime)"')"
# If user-specified version has 2 or more dots, use it as is. Otherwise use latest version.
if [ "$(echo "${DOTNET_DOWNLOAD_VERSION}" | grep -o "\." | wc -l)" -lt "2" ]; then
DOTNET_DOWNLOAD_VERSION="${dotnet_latest_version}"
fi
dotnet_download_details="$(echo "${dotnet_releases_json}" | jq -r --arg sdk_or_runtime "${sdk_or_runtime}" --arg dotnet_version "${DOTNET_DOWNLOAD_VERSION}" --arg arch "${architecture}" '.releases[]."\($sdk_or_runtime)" | select(.version==$dotnet_version) | .files[] | select(.name=="dotnet-\($sdk_or_runtime)-linux-\($arch).tar.gz")')"
if [ -n "${dotnet_download_details}" ]; then
echo "Found .NET binary version ${DOTNET_DOWNLOAD_VERSION}"
DOTNET_DOWNLOAD_URL="$(echo "${dotnet_download_details}" | jq -r '.url')"
DOTNET_DOWNLOAD_HASH="$(echo "${dotnet_download_details}" | jq -r '.hash')"
DOTNET_DOWNLOAD_NAME="$(echo "${dotnet_download_details}" | jq -r '.name')"
else
err "Unable to find .NET binary for version ${DOTNET_DOWNLOAD_VERSION}"
exit 1
fi
else
err "Unable to find .NET release details for version ${DOTNET_DOWNLOAD_VERSION} at ${dotnet_releases_url}"
exit 1
fi
}
# Install .NET CLI using the .NET releases url
install_using_dotnet_releases_url() {
local sdk_or_runtime="$1"
local version="$2"
# Check listed package dependencies and install them if they are not already installed.
# NOTE: icu-devtools is a small package with similar dependencies to .NET.
# It will install the appropriate dependencies based on the OS:
# - libgcc-s1 OR libgcc1 depending on OS
# - the latest libicuXX depending on OS (eg libicu57 for stretch)
# - also installs libc6 and libstdc++6 which are required by .NET
check_packages curl ca-certificates tar jq icu-devtools libgssapi-krb5-2 zlib1g
# Starting with Ubuntu 22.04 (jammy), libssl1.1 does not ship with the OS anymore.
if [[ "${DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1}" = *"${VERSION_CODENAME}"* ]]; then
check_packages libssl1.1
else
check_packages libssl3
fi
get_full_version_details "${sdk_or_runtime}" "${version}"
DOTNET_INSTALL_PATH="${TARGET_DOTNET_ROOT}/${DOTNET_DOWNLOAD_VERSION}"
if [ -d "${DOTNET_INSTALL_PATH}" ]; then
echo "(!) Dotnet version ${DOTNET_DOWNLOAD_VERSION} already exists."
exit 1
fi
# exports DOTNET_DOWNLOAD_URL, DOTNET_DOWNLOAD_HASH, DOTNET_DOWNLOAD_NAME
echo "DOWNLOAD LINK: ${DOTNET_DOWNLOAD_URL}"
# Setup the access group and add the user to it.
umask 0002
if ! cat /etc/group | grep -e "^${ACCESS_GROUP}:" > /dev/null 2>&1; then
groupadd -r "${ACCESS_GROUP}"
fi
usermod -a -G "${ACCESS_GROUP}" "${USERNAME}"
# Download the .NET binaries.
echo "DOWNLOADING BINARY..."
TMP_DIR="/tmp/dotnetinstall"
mkdir -p "${TMP_DIR}"
curl -sSL "${DOTNET_DOWNLOAD_URL}" -o "${TMP_DIR}/${DOTNET_DOWNLOAD_NAME}"
# Get checksum from .NET CLI blob storage using the runtime version and
# run validation (sha512sum) of checksum against the expected checksum hash.
echo "VERIFY CHECKSUM"
cd "${TMP_DIR}"
echo "${DOTNET_DOWNLOAD_HASH} *${DOTNET_DOWNLOAD_NAME}" | sha512sum -c -
# Extract binaries and add to path.
mkdir -p "${DOTNET_INSTALL_PATH}"
echo "Extract Binary to ${DOTNET_INSTALL_PATH}"
tar -xzf "${TMP_DIR}/${DOTNET_DOWNLOAD_NAME}" -C "${DOTNET_INSTALL_PATH}" --strip-components=1
CURRENT_DIR="${TARGET_DOTNET_ROOT}/current"
if [[ ! -d "${CURRENT_DIR}" ]]; then
ln -s "${DOTNET_INSTALL_PATH}" "${CURRENT_DIR}"
fi
# Give write permissions to the user.
chown -R "${USERNAME}:${USERNAME}" "${CURRENT_DIR}"
chmod g+r+w+s "${CURRENT_DIR}"
chmod -R g+r+w "${CURRENT_DIR}"
if [[ "${OVERRIDE_DEFAULT_VERSION}" = "true" ]]; then
if [[ $(ls -l ${CURRENT_DIR}) != *"-> ${DOTNET_INSTALL_PATH}"* ]] ; then
rm "${CURRENT_DIR}"
ln -s "${DOTNET_INSTALL_PATH}" "${CURRENT_DIR}"
fi
fi
updaterc "if [[ \"\${PATH}\" != *\"${CURRENT_DIR}\"* ]]; then export PATH=${CURRENT_DIR}:\${PATH}; fi"
}
###########################
# Start .NET installation
###########################
export DEBIAN_FRONTEND=noninteractive
. /etc/os-release
architecture="$(dpkg --print-architecture)"
# Dotnet 3.1 and 5 are not supported on Ubuntu 22.04 (jammy)+,
# due to lack of libssl3.0 support.
# See: https://github.com/microsoft/vscode-dev-containers/issues/1458#issuecomment-1135077775
# NOTE: This will only guard against installation of the dotnet versions we propose via 'features'.
# The user can attempt to install any other version at their own risk.
if [[ "${DOTNET_VERSION}" = "3"* ]] || [[ "${DOTNET_VERSION}" = "5"* ]]; then
if [[ ! "${DOTNET_VERSION_CODENAMES_REQUIRE_OLDER_LIBSSL_1}" = *"${VERSION_CODENAME}"* ]]; then
err "Dotnet ${DOTNET_VERSION} is not supported on Ubuntu ${VERSION_CODENAME} due to a change in the 'libssl' dependency across distributions.\n Please upgrade your version of dotnet, or downgrade your OS version."
exit 1
fi
fi
# Determine if the user wants to download .NET Runtime only, or .NET SDK & Runtime
# and set the appropriate variables.
if [ "${DOTNET_RUNTIME_ONLY}" = "true" ]; then
DOTNET_SDK_OR_RUNTIME="runtime"
elif [ "${DOTNET_RUNTIME_ONLY}" = "false" ]; then
DOTNET_SDK_OR_RUNTIME="sdk"
else
err "Expected true for installing dotnet Runtime only or false for installing SDK and Runtime. Received ${DOTNET_RUNTIME_ONLY}."
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Install the .NET CLI
echo "(*) Installing .NET CLI..."
# icu-devtools includes dependencies for .NET
check_packages wget ca-certificates icu-devtools
CHANGE_OWNERSHIP="false"
if [[ "${DOTNET_ARCHIVE_ARCHITECTURES}" = *"${architecture}"* ]] && [[ "${DOTNET_ARCHIVE_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]] && [[ "${INSTALL_USING_APT}" = "true" ]]; then
echo "Detected ${VERSION_CODENAME} on ${architecture}. Attempting to install dotnet from apt"
wget -O "$DOTNET_INSTALL_SCRIPT" "$DOTNET_INSTALL_SCRIPT_URL"
sha256sum --check <<< $DOTNET_INSTALL_SCRIPT_SHA256
chmod +x "$DOTNET_INSTALL_SCRIPT"
install_using_apt "${DOTNET_SDK_OR_RUNTIME}" "${DOTNET_VERSION}" false || install_using_apt "${DOTNET_SDK_OR_RUNTIME}" "${DOTNET_VERSION}" true
if [ "$?" != 0 ]; then
echo "Could not install requested version from apt on current distribution."
exit 1
fi
else
if [[ "${INSTALL_USING_APT}" = "false" ]]; then
echo "Installing dotnet from releases url"
else
echo "Attempting to install dotnet from releases url"
fi
install_using_dotnet_releases_url "${DOTNET_SDK_OR_RUNTIME}" "${DOTNET_VERSION}"
CHANGE_OWNERSHIP="true"
fi
# Install primary version
install_version "$DOTNET_VERSION"
# Additional dotnet versions to be installed but not be set as default.
if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then
OLDIFS=$IFS
# Install additional versions
if [ -n "$DOTNET_ADDITIONAL_VERSIONS" ]; then
OLD_IFS=$IFS
IFS=","
read -a additional_versions <<< "$ADDITIONAL_VERSIONS"
read -a additional_versions <<< "$DOTNET_ADDITIONAL_VERSIONS"
for version in "${additional_versions[@]}"; do
OVERRIDE_DEFAULT_VERSION="false"
install_using_dotnet_releases_url "${DOTNET_SDK_OR_RUNTIME}" "${version}"
# Trim whitespace from version
version="$(echo -e "$version" | tr -d '[:space:]')"
install_version "$version"
done
IFS=$OLDIFS
IFS=$OLD_IFS
fi
if [ "${CHANGE_OWNERSHIP}" = "true" ]; then
if ! cat /etc/group | grep -e "^dotnet:" > /dev/null 2>&1; then
groupadd -r dotnet
fi
usermod -a -G dotnet "${USERNAME}"
chown -R "${USERNAME}:dotnet" "${TARGET_DOTNET_ROOT}"
chmod -R g+r+w "${TARGET_DOTNET_ROOT}"
find "${TARGET_DOTNET_ROOT}" -type d -print0 | xargs -n 1 -0 chmod g+s
fi
# Clean up
rm -rf /var/lib/apt/lists/*
rm "$DOTNET_INSTALL_SCRIPT"
echo "Done!"

View file

@ -0,0 +1,13 @@
#!/bin/bash
set -e
source dev-container-features-test-lib
check "non-root user" test "$(id -u)" -ne 0
pushd example_project
check "dotnet restore" dotnet restore
check "dotnet build" dotnet build
reportResults

View file

@ -0,0 +1,2 @@
bin
obj

View file

@ -0,0 +1,8 @@
// See https://aka.ms/new-console-template for more information
internal class Movie
{
public string Name { get; set; } = "Default Name";
public DateTime ReleaseDate { get; set; }
public List<string> Genres { get; set; } = new List<string>();
}

View file

@ -0,0 +1,27 @@
// See https://aka.ms/new-console-template for more information
using Newtonsoft.Json;
Console.WriteLine("Hello, World!");
string json = @"{
'Name': 'Inception',
'ReleaseDate': '2010-07-08T00:00:00',
'Genres': [
'Action',
'Thriller'
]
}";
Movie? m = JsonConvert.DeserializeObject<Movie>(json);
if (m == default)
{
Console.WriteLine("Decoding failed!");
}
else
{
Console.WriteLine($"Name: {m.Name}");
Console.WriteLine($"Release Date: {m.ReleaseDate}");
Console.WriteLine($"Genres: {string.Join(", ", m.Genres)}");
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

View file

@ -2,16 +2,15 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet version 6.0.301 installed as default" bash -c "dotnet --version | grep 6.0.301"
check "dotnet version 5.0 installed" bash -c "ls -l /usr/local/dotnet | grep 5.0"
check "dotnet version 3.1.420 installed" bash -c "ls -l /usr/local/dotnet | grep 3.1.420"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "version 6.0.405 installed" bash -c 'dotnet --list-sdks | grep 6.0.405'
check "version 6.0.402 installed" bash -c 'dotnet --list-sdks | grep 6.0.402'
check "version 3.1.416 installed" bash -c 'dotnet --list-sdks | grep 3.1.416'
# Primary version plus 2 additional versions
check "latest version installed" bash -c 'test "$(dotnet --list-sdks | wc -l)" -eq 4'
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 3 is installed" bash -c "dotnet --list-sdks | grep '3\.[0-9]*\.[0-9]*'"
check "dotnet version 3 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '3\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "some major version of dotnet 3 is installed" bash -c "dotnet --list-sdks | grep '3\.[0-9]*\.[0-9]*'"
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 6 is installed" bash -c "dotnet --list-sdks | grep '6\.[0-9]*\.[0-9]*'"
check "dotnet version 6 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '6\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "some major version of dotnet 6 is installed" bash -c "dotnet --list-sdks | grep '6\.[0-9]*\.[0-9]*'"
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 6 is installed" bash -c "dotnet --list-sdks | grep '6\.[0-9]*\.[0-9]*'"
check "dotnet version 6 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '6\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "some major version of dotnet 6 is installed" bash -c "dotnet --list-sdks | grep '6\.[0-9]*\.[0-9]*'"
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
check "dotnet version 7 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '7\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
check "dotnet version 7 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '7\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
# Report result
reportResults

View file

@ -1,17 +0,0 @@
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
check "dotnet version 7 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '7\.[0-9]*\.[0-9]*'"
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
# Report result
reportResults

View file

@ -2,16 +2,10 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 6 is installed" bash -c "dotnet --list-sdks | grep '6\.[0-9]*\.[0-9]*'"
check "dotnet version 6 installed" bash -c "ls -l /usr/share/dotnet/sdk | grep '6\.[0-9]*\.[0-9]*'"
./test.sh
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "lts version installed" bash -c 'test "$(dotnet --list-sdks | wc -l)" -eq 1'
# Report result
reportResults

View file

@ -0,0 +1,13 @@
#!/bin/bash
set -e
source dev-container-features-test-lib
# Some runtime installed
check "runtime" bash -c 'test "$(dotnet --list-runtimes | wc -l)" -gt 0'
# No sdk installed
check "no sdk" bash -c 'test "$(dotnet --list-sdks | wc -l)" -eq 0'
reportResults

View file

@ -1,17 +0,0 @@
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "dotnet sdks" dotnet --list-sdks
check "some major version of dotnet 7 is installed" bash -c "dotnet --list-sdks | grep '7\.[0-9]*\.[0-9]*'"
check "dotnet version 7 installed" bash -c "ls -l /usr/local/dotnet | grep '7\.[0-9]*\.[0-9]*'"
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
# Report result
reportResults

View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
source dev-container-features-test-lib
check "non-root user" test "$(id -u)" -ne 0
pushd example_project
check "dotnet run" bash -c "dotnet run | grep 'Inception'"
reportResults

View file

@ -3,8 +3,16 @@
"image": "ubuntu:focal",
"features": {
"dotnet": {
"version": "6.0.301",
"additionalVersions": "5.0,3.1.420"
"version": "latest",
"additionalVersions": "6.0.405, 6.0.402,3.1.416"
}
}
},
"install_dotnet_lts": {
"image": "ubuntu:focal",
"features": {
"dotnet": {
"version": "latest"
}
}
},
@ -48,28 +56,30 @@
}
}
},
"install_dotnet_latest": {
"install_dotnet_runtime": {
"image": "ubuntu:jammy",
"features": {
"dotnet": {
"version": "latest"
"version": "6.0.14",
"runtimeOnly": true
}
}
},
"install_dotnet_lts": {
"image": "ubuntu:focal",
"build_dotnet_7": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"dotnet": {
"version": "lts"
"version": "7"
}
}
},
"install_wo_apt": {
"image": "ubuntu:jammy",
"run_dotnet_7": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode",
"features": {
"dotnet": {
"version": "7",
"installUsingApt": false
"version": "7"
}
}
}

View file

@ -2,20 +2,19 @@
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "dotnet" dotnet --info
check "sdks" dotnet --list-sdks
check "version" dotnet --version
echo "Validating expected version present..."
check "some major version of dotnet 7 is installed" bash -c "dotnet --version | grep '7\.[0-9]*\.[0-9]*'"
# Verify current symlink exists and works
check "current link dotnet" /usr/local/dotnet/current/dotnet --info
check "current link sdk" ls -l /usr/local/dotnet/current/sdk
check "current link sdks" /usr/local/dotnet/current/dotnet --list-sdks
check "current link version" /usr/local/dotnet/current/dotnet --version
# Verify installation location
check "dotnet in /usr/local/dotnet" bash -c 'test "$(ls /usr/local/dotnet | wc -l)" -gt 0'
check "sdks in /usr/local/dotnet/sdk" bash -c 'test "$(ls /usr/local/dotnet/current/sdk | wc -l)" -gt 0'
# Report result
reportResults