Add .NET SDK installation phase
This commit is contained in:
parent
6ff3a79cea
commit
4655260986
@ -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
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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/`
|
||||||
|
|||||||
@ -98,4 +98,3 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
atlas_log_ok "Bootstrap scaffold completed"
|
atlas_log_ok "Bootstrap scaffold completed"
|
||||||
|
|
||||||
|
|||||||
@ -41,4 +41,3 @@ atlas_pending_update_count() {
|
|||||||
atlas_reboot_required() {
|
atlas_reboot_required() {
|
||||||
[[ -f /var/run/reboot-required ]]
|
[[ -f /var/run/reboot-required ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
178
install/phases/10-dotnet.sh
Executable 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
|
||||||
@ -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`
|
||||||
|
|||||||
@ -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.`
|
||||||
|
|
||||||
|
|||||||
@ -270,4 +270,3 @@ fi
|
|||||||
printf '\n'
|
printf '\n'
|
||||||
atlas_validation_summary
|
atlas_validation_summary
|
||||||
atlas_validation_exit_code
|
atlas_validation_exit_code
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user