Add .NET SDK installation phase

This commit is contained in:
Nick Beckley 2026-07-10 11:25:25 +00:00
parent 6ff3a79cea
commit 4655260986
12 changed files with 272 additions and 11 deletions

View File

@ -10,6 +10,55 @@ This file records chronological Atlas build and infrastructure milestones. Do no
### Phase ### Phase
Phase 2 .NET development platform.
### Objective
Install the .NET SDKs required for Atlas and PlotDirector development.
### Changes
- Added `install/phases/10-dotnet.sh`.
- Installed .NET 8 SDK `8.0.128`.
- Installed .NET 10 SDK `10.0.109`.
- Used the official Ubuntu .NET backports PPA for .NET 8.
- Used the built-in Ubuntu `resolute-updates` and `resolute-security` package sources for .NET 10.
- Did not install .NET 9, SQL Server, nginx, or Docker.
### Validation
- `bash -n install/phases/10-dotnet.sh` passed.
- `install/phases/10-dotnet.sh --help` passed.
- `install/phases/10-dotnet.sh --dry-run` passed.
- `install/phases/10-dotnet.sh` installed the missing SDKs.
- A second `install/phases/10-dotnet.sh` run detected both SDKs already installed.
- `dotnet --info`, `dotnet --list-sdks`, and `dotnet --list-runtimes` passed.
- Temporary .NET 8 and .NET 10 console projects built and ran outside the repository.
- `scripts/system/validate-host.sh` passed after installation.
### Problems
- Initial package-candidate detection in `10-dotnet.sh` was corrected after it failed under `pipefail` before installing SDK packages.
- No unresolved .NET installation problems recorded.
### Decisions
- Use Ubuntu package feeds for .NET SDK installation on Ubuntu 26.04.
### Git Commit
Not yet committed.
### Operator
Codex.
### Date
2026-07-10
### Phase
Phase 2A. Phase 2A.
### Objective ### Objective

View File

@ -8,7 +8,8 @@ This guide describes the planned rebuild path for Atlas. At Phase 1, the reposit
- Shared installation framework: present. - Shared installation framework: present.
- System discovery script: present. - System discovery script: present.
- Host validation script: present. - Host validation script: present.
- Component installation scripts: not yet created. - .NET installation script: present.
- Other component installation scripts: not yet created.
- Configuration templates: not yet created. - Configuration templates: not yet created.
- Operational scripts: not yet created. - Operational scripts: not yet created.
- Smoke tests: not yet created. - Smoke tests: not yet created.
@ -112,8 +113,9 @@ Planned bootstrap flow:
4. Run `scripts/system/discover-system.sh`. 4. Run `scripts/system/discover-system.sh`.
5. Run `scripts/system/validate-host.sh`. 5. Run `scripts/system/validate-host.sh`.
6. Run `install/bootstrap.sh --dry-run`. 6. Run `install/bootstrap.sh --dry-run`.
7. Run ordered installation scripts from `install/phases/` when they exist. 7. Run `install/phases/10-dotnet.sh` when .NET SDKs are required.
8. Run smoke tests from `tests/` when they exist. 8. Run additional ordered installation scripts from `install/phases/` when they exist.
9. Run smoke tests from `tests/` when they exist.
Bootstrap command sequence is `TODO: Confirm during the relevant implementation phase.` Bootstrap command sequence is `TODO: Confirm during the relevant implementation phase.`
@ -137,6 +139,22 @@ These scripts do not exist yet. When created, each script must:
- Document rollback expectations. - Document rollback expectations.
- Include or reference validation steps. - Include or reference validation steps.
Current .NET installation command:
```bash
install/phases/10-dotnet.sh
```
Current .NET verification commands:
```bash
dotnet --info
dotnet --list-sdks
dotnet --list-runtimes
```
The current installed SDKs are .NET 8 SDK `8.0.128` and .NET 10 SDK `10.0.109`.
## 8. Validation ## 8. Validation
Minimum rebuild validation should confirm: Minimum rebuild validation should confirm:

View File

@ -48,6 +48,21 @@ manifests/
phases/ phases/
``` ```
Current Phase 2 installer:
```bash
install/phases/10-dotnet.sh
```
The .NET installer installs only the required .NET SDK packages and verifies them with `dotnet --list-sdks`.
Current installed SDKs:
- .NET 8 SDK `8.0.128`
- .NET 10 SDK `10.0.109`
.NET 8 is installed from the official Ubuntu .NET backports PPA. .NET 10 is installed from the built-in Ubuntu package feeds.
Runtime output belongs outside the repository: Runtime output belongs outside the repository:
- `/var/log/atlas/install/` - `/var/log/atlas/install/`

View File

@ -98,4 +98,3 @@ else
fi fi
atlas_log_ok "Bootstrap scaffold completed" atlas_log_ok "Bootstrap scaffold completed"

View File

@ -41,4 +41,3 @@ atlas_pending_update_count() {
atlas_reboot_required() { atlas_reboot_required() {
[[ -f /var/run/reboot-required ]] [[ -f /var/run/reboot-required ]]
} }

View File

@ -55,4 +55,3 @@ atlas_service_restart() {
atlas_log_info "Restarting service ${service_name}" atlas_log_info "Restarting service ${service_name}"
atlas_sudo_run systemctl restart "$service_name" atlas_sudo_run systemctl restart "$service_name"
} }

View File

@ -65,4 +65,3 @@ atlas_gib_to_bytes() {
local gib="$1" local gib="$1"
awk -v gib="$gib" 'BEGIN {printf "%.0f\n", gib * 1024 * 1024 * 1024}' awk -v gib="$gib" 'BEGIN {printf "%.0f\n", gib * 1024 * 1024 * 1024}'
} }

View File

@ -29,4 +29,3 @@ awk|required|Text processing
sed|required|Text processing sed|required|Text processing
grep|required|Text searching grep|required|Text searching
sudo|required|Non-interactive privileged command execution sudo|required|Non-interactive privileged command execution

178
install/phases/10-dotnet.sh Executable file
View File

@ -0,0 +1,178 @@
#!/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

View File

@ -2,7 +2,7 @@
This directory is reserved for future ordered Atlas installation phases. This directory is reserved for future ordered Atlas installation phases.
Phase 2A intentionally does not create speculative .NET, SQL Server, nginx, or Docker installer scripts. Future scripts should be added only when their implementation phase is approved. Phase 2A intentionally did not create speculative .NET, SQL Server, nginx, or Docker installer scripts. Phase 2 adds the .NET installer only.
## Naming Convention ## Naming Convention
@ -18,3 +18,11 @@ Use a two-digit phase number and lower-case hyphenated component name:
Each phase must source the shared framework under `install/lib/`, support dry-run behaviour where practical, and follow [../../SERVER-STANDARDS.md](../../SERVER-STANDARDS.md). Each phase must source the shared framework under `install/lib/`, support dry-run behaviour where practical, and follow [../../SERVER-STANDARDS.md](../../SERVER-STANDARDS.md).
## Current Phases
- `10-dotnet.sh`: installs the required .NET 8 and .NET 10 SDKs from official Ubuntu package sources.
Installed SDKs after the current Phase 2 run:
- .NET 8 SDK `8.0.128`
- .NET 10 SDK `10.0.109`

View File

@ -5,4 +5,3 @@ This directory is reserved for development workflow helpers that do not belong t
Do not store secrets, generated logs, package caches, or one-off experiments here. Do not store secrets, generated logs, package caches, or one-off experiments here.
Future structure is `TODO: Confirm during the relevant implementation phase.` Future structure is `TODO: Confirm during the relevant implementation phase.`

View File

@ -270,4 +270,3 @@ fi
printf '\n' printf '\n'
atlas_validation_summary atlas_validation_summary
atlas_validation_exit_code atlas_validation_exit_code