From 3590672ec3f45b8df3820d65fc0946dc760292ec Mon Sep 17 00:00:00 2001 From: tranch Date: Wed, 15 Jul 2026 14:04:06 +0800 Subject: Integrate Instruments release seed Download and verify the selected release during image builds. Bootstrap it once into the first graphical user's XDG directories. --- build_files/build.sh | 2 + build_files/install-instruments.sh | 182 +++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100755 build_files/install-instruments.sh (limited to 'build_files') diff --git a/build_files/build.sh b/build_files/build.sh index f1709da..b89907a 100755 --- a/build_files/build.sh +++ b/build_files/build.sh @@ -32,3 +32,5 @@ if [[ -n "${HOMEBREW_API_DOMAIN:-}" ]]; then fi find /etc/environment.d /etc/skel/.config/environment.d -name 99-aerocore-mirrors.conf -type f -exec chmod 0644 {} + 2>/dev/null || true + +/ctx/install-instruments.sh diff --git a/build_files/install-instruments.sh b/build_files/install-instruments.sh new file mode 100755 index 0000000..f85bd3b --- /dev/null +++ b/build_files/install-instruments.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash + +set -euo pipefail + +: "${INSTRUMENTS_ENABLED:=true}" +: "${INSTRUMENTS_RELEASE_REPOSITORY:=AeroCore-IO/booster-installer}" +: "${INSTRUMENTS_VERSION:=latest}" +: "${INSTRUMENTS_RELEASE_API_BASE:=https://api.github.com}" +: "${INSTRUMENTS_SEED_ROOT:=/usr/share/aerocore-booster-release}" + +if [[ "${INSTRUMENTS_ENABLED}" != "true" ]]; then + echo "AeroCore Booster image integration is disabled" + exit 0 +fi + +case "$(uname -m)" in + x86_64 | amd64) + asset_suffix="_linux-x86_64.tar.gz" + ;; + *) + echo "Unsupported AeroCore Booster image architecture: $(uname -m)" >&2 + exit 1 + ;; +esac + +for command in curl jq sha256sum tar; do + command -v "$command" >/dev/null 2>&1 || { + echo "Required command is unavailable: $command" >&2 + exit 1 + } +done + +workdir="$(mktemp -d)" +trap 'rm -rf "$workdir"' EXIT + +github_curl() { + local args=( + --fail + --location + --retry 3 + --retry-delay 2 + --retry-max-time 60 + --silent + --show-error + ) + + if [[ -s /run/secrets/GITHUB_TOKEN ]]; then + args+=(--header "Authorization: Bearer $(&2 + exit 1 +fi + +IFS=$'\t' read -r asset_name asset_url <<<"${payload_assets[0]}" +checksum_name="${asset_name}.sha256" +checksum_url="$( + jq -er --arg name "$checksum_name" \ + '.assets[] | select(.name == $name) | .browser_download_url' \ + "$release_json" +)" + +archive="$workdir/$asset_name" +checksum_file="$workdir/$checksum_name" +github_curl "$asset_url" --output "$archive" +github_curl "$checksum_url" --output "$checksum_file" + +expected_checksum="$(awk 'NR == 1 { print $1 }' "$checksum_file")" +actual_checksum="$(sha256sum "$archive" | awk '{ print $1 }')" +if [[ ! "$expected_checksum" =~ ^[[:xdigit:]]{64}$ ]] || + [[ "${actual_checksum,,}" != "${expected_checksum,,}" ]]; then + echo "Checksum verification failed for $asset_name" >&2 + exit 1 +fi + +while IFS= read -r entry; do + case "$entry" in + /* | ../* | */../* | */..) + echo "Unsafe path in release archive: $entry" >&2 + exit 1 + ;; + esac +done < <(tar -tzf "$archive") + +extract_dir="$workdir/extracted" +install -d "$extract_dir" +tar --extract --gzip --file "$archive" --directory "$extract_dir" \ + --no-same-owner + +if [[ -d "$extract_dir/aerocore-booster-release" ]]; then + payload="$extract_dir/aerocore-booster-release" +elif [[ -d "$extract_dir/instruments-ng-release" ]]; then + payload="$extract_dir/instruments-ng-release" +else + echo "Release archive does not contain a supported payload root" >&2 + exit 1 +fi + +required_paths=( + install.sh + appimage/AppRun + appimage/AppRun.wrapped + sidecar/hhd-input-helper.cjs + sidecar/vendor/hhd-input-helper/instruments_hhd_input/__init__.py + runtime/avionics + runtime/cabin + runtime/wing + runtime/node/bin/node + python-wheelhouse + pkg/systemd/ac-avionics.service + pkg/systemd/ac-cabin.service + pkg/systemd/ac-wing.service + pkg/systemd/ac-instruments.service + scripts/check-runtime-health.cjs + manifest.yaml +) + +for path in "${required_paths[@]}"; do + if [[ ! -e "$payload/$path" ]]; then + echo "Required path is missing from Booster release: $path" >&2 + exit 1 + fi +done + +if [[ ! -f "$payload/pkg/aerocore-booster.sh" && + ! -f "$payload/pkg/instruments-ng.sh" ]]; then + echo "Booster launcher is missing from the release payload" >&2 + exit 1 +fi + +# Remove the first implementation's image-owned runtime when upgrading an +# existing AeroCore OS image. The release seed itself remains immutable. +rm -rf /usr/lib/aerocore-booster +rm -f /usr/bin/aerocore-booster +for unit in ac-avionics.service ac-cabin.service ac-wing.service \ + ac-instruments.service; do + rm -f "/usr/lib/systemd/system/$unit" +done + +rm -rf "$INSTRUMENTS_SEED_ROOT" +install -d -m 0755 "$INSTRUMENTS_SEED_ROOT" +cp -a "$payload/." "$INSTRUMENTS_SEED_ROOT/" + +cat >"$INSTRUMENTS_SEED_ROOT/image-release" <