#!/usr/bin/env bash set -Eeuo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INSTALL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" REPO_ROOT="$(cd "${INSTALL_DIR}/.." && pwd)" # shellcheck source=install/lib/common.sh source "${INSTALL_DIR}/lib/common.sh" # shellcheck source=install/lib/logging.sh source "${INSTALL_DIR}/lib/logging.sh" # shellcheck source=install/lib/packages.sh source "${INSTALL_DIR}/lib/packages.sh" atlas_set_script_name "10-dotnet.sh" atlas_install_error_trap REQUIRED_OS_ID="ubuntu" REQUIRED_OS_VERSION="26.04" DOTNET_BACKPORTS_PPA="ppa:dotnet/backports" DOTNET_REQUIRED_PACKAGES=("dotnet-sdk-8.0" "dotnet-sdk-10.0") usage() { cat <<'USAGE' Usage: install/phases/10-dotnet.sh [options] Install the Atlas .NET development SDKs from official Ubuntu package feeds. Required SDKs: dotnet-sdk-8.0 dotnet-sdk-10.0 Options: --help Show this help text. --version Show script/framework version. --dry-run Show intended actions without making changes. --verbose Print additional diagnostic output. USAGE } while [[ "$#" -gt 0 ]]; do case "$1" in --help) usage exit "${ATLAS_EXIT_OK}" ;; --version) atlas_print_version exit "${ATLAS_EXIT_OK}" ;; --dry-run) atlas_enable_dry_run ;; --verbose) atlas_enable_verbose ;; *) atlas_usage_error "Unknown option: $1" exit "${ATLAS_EXIT_USAGE}" ;; esac shift done load_os_release() { if [[ ! -r /etc/os-release ]]; then atlas_log_error "/etc/os-release is not readable" exit "${ATLAS_EXIT_PREREQ}" fi # shellcheck disable=SC1091 . /etc/os-release if [[ "${ID:-}" != "${REQUIRED_OS_ID}" || "${VERSION_ID:-}" != "${REQUIRED_OS_VERSION}" ]]; then atlas_log_error "Unsupported OS: ${PRETTY_NAME:-unknown}; expected Ubuntu 26.04" exit "${ATLAS_EXIT_PREREQ}" fi } package_has_candidate() { local package_name="$1" local candidate candidate="$(apt-cache policy "$package_name" 2>/dev/null | awk -F: '/Candidate:/ {gsub(/^[ \t]+/, "", $2); print $2; exit}')" [[ -n "$candidate" && "$candidate" != "(none)" ]] } backports_configured() { grep -RqsE 'ppa\\.launchpadcontent\\.net/dotnet/backports|LP-PPA-dotnet-backports|dotnet-ubuntu-backports' /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null } ensure_backports_if_needed() { if package_has_candidate dotnet-sdk-8.0; then atlas_log_info "dotnet-sdk-8.0 is available from configured package sources" return 0 fi if backports_configured; then atlas_log_info "Ubuntu .NET backports repository is configured; refreshing package metadata" atlas_sudo_run apt-get update return 0 fi atlas_log_info "dotnet-sdk-8.0 is not available; adding official Ubuntu .NET backports repository" if [[ "${ATLAS_DRY_RUN}" == "1" ]]; then atlas_log_info "Dry-run mode: would run add-apt-repository -y ${DOTNET_BACKPORTS_PPA}" atlas_log_info "Dry-run mode: would run apt-get update" return 0 fi atlas_require_command add-apt-repository atlas_sudo_run add-apt-repository -y "${DOTNET_BACKPORTS_PPA}" atlas_sudo_run apt-get update } install_missing_sdks() { local missing=() local package_name for package_name in "${DOTNET_REQUIRED_PACKAGES[@]}"; do if atlas_package_installed "$package_name"; then atlas_log_ok "${package_name} is already installed" else missing+=("$package_name") fi done if [[ "${#missing[@]}" -eq 0 ]]; then atlas_log_ok "All required .NET SDK packages are installed" return 0 fi for package_name in "${missing[@]}"; do if [[ "${ATLAS_DRY_RUN}" == "1" ]]; then atlas_log_info "Dry-run mode: would verify package candidate for ${package_name}" continue fi if ! package_has_candidate "$package_name"; then atlas_log_error "No official configured package candidate found for ${package_name}" exit "${ATLAS_EXIT_PREREQ}" fi done atlas_install_packages "${missing[@]}" } verify_dotnet() { atlas_require_command dotnet dotnet --list-sdks | grep -q '^8\.' || { atlas_log_error ".NET 8 SDK was not found after installation" exit "${ATLAS_EXIT_VALIDATION}" } dotnet --list-sdks | grep -q '^10\.' || { atlas_log_error ".NET 10 SDK was not found after installation" exit "${ATLAS_EXIT_VALIDATION}" } atlas_log_ok ".NET SDK verification passed" } main() { load_os_release atlas_require_sudo_noninteractive || { atlas_log_error "Passwordless non-interactive sudo is required" exit "${ATLAS_EXIT_PREREQ}" } atlas_require_command apt-cache atlas_require_command apt-get atlas_require_command dpkg-query ensure_backports_if_needed install_missing_sdks if [[ "${ATLAS_DRY_RUN}" == "1" ]]; then atlas_log_info "Dry-run mode: skipping post-install dotnet verification" else verify_dotnet fi } main