From cbfe376a4208f8397c108485869fbd8595bcee4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Fri, 14 Aug 2026 05:54:56 +0000 Subject: [PATCH] accept the repo URL as an argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bun setup -- --repo https://github.com/you/platform.git The default is a private Gitea over SSH, which only authenticates on a machine whose key it already knows — so a genuinely fresh server could not clone at all without editing lib/repo.sh or knowing OFFICER_REPO existed. Added to both entry points. install.sh exports it rather than forwarding an argument it does not own; officer-setup.sh sets it before lib/repo.sh is sourced, which reads `${OFFICER_REPO:-}`, so an absent flag still defaults. Two bugs found doing it, both pre-existing: - officer-setup.sh ALREADY had an arg parser, at the top, before the sources. My first attempt added a second one further down that was unreachable — every argument had already been consumed and `*)` would have exited 2 on --repo. Caught because `--help` printed the wrong usage. - both scripts re-execute through sudo passing `"$@"`, which the parse loop had already emptied with `shift`. So `officer-setup.sh --only build` run as a normal user silently became a FULL run the moment it escalated, and `install.sh --officer-only` re-ran the machine half. Nothing said so; the flag just stopped existing. ORIGINAL_ARGS is captured before the loop now. `${ORIGINAL_ARGS[@]+"${ORIGINAL_ARGS[@]}"}` is the set -u safe form — expanding an empty array is an error on bash before 4.4, and this runs on whatever the machine came with. Verified: bash -n on both, --help/--list/--repo/--repo=/unknown-option on both, the set -e behaviour of the guarded export, and that args survive the shift loop. Co-Authored-By: Claude Opus 5 --- scripts/install.sh | 38 +++++++++++++++++++++++++++++----- scripts/setup/officer-setup.sh | 33 +++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 18f0ee0e..60082fb5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -45,22 +45,49 @@ die() { # Which halves to run. Both by default. RUN_MACHINE=true RUN_OFFICER=true -for arg in "$@"; do - case "$arg" in + +# Kept before the loop below eats them: this script re-executes itself through sudo +# further down, and `shift` would otherwise leave it re-running with no arguments — +# silently dropping --officer-only and turning a platform-only run into a full one. +# +# The `${x[@]+"${x[@]}"}` form is for `set -u`: expanding an empty array unquoted-safe +# is an error on bash before 4.4, and this runs on whatever the machine came with. +ORIGINAL_ARGS=(${@+"$@"}) + +# A `while`/`shift` loop rather than `for arg in "$@"`, because --repo takes a value +# and a for-loop cannot consume the argument after it. +while [[ $# -gt 0 ]]; do + case "$1" in --machine-only) RUN_OFFICER=false ;; --officer-only) RUN_MACHINE=false ;; + --repo) + [[ -n "${2:-}" ]] || die "--repo needs a URL" + OFFICER_REPO="$2" + shift + ;; + --repo=*) OFFICER_REPO="${1#--repo=}" ;; -h | --help) - say "usage: install.sh [--machine-only | --officer-only]" + say "usage: install.sh [--machine-only | --officer-only] [--repo ]" say "" say " no flags both halves, machine first" say " --machine-only stop after the machine is provisioned" say " --officer-only the platform only, on a machine you already trust" + say " --repo clone the platform from here instead of the default" + say "" + say " The default is a private Gitea over SSH, which only authenticates on a" + say " machine whose key it already knows. Pass an https URL on a fresh box." exit 0 ;; - *) die "unknown option: $arg" ;; + *) die "unknown option: $1" ;; esac + shift done +# Exported so `officer-setup.sh` reads it from the environment and this script does +# not have to forward arguments it does not own. `lib/repo.sh` takes it as +# `${OFFICER_REPO:-}`, so unset here still means the default there. +[[ -n "${OFFICER_REPO:-}" ]] && export OFFICER_REPO + KERNEL="$(uname -s)" case "$KERNEL" in Darwin) @@ -104,7 +131,8 @@ if [[ "$KERNEL" != "Darwin" && "$EUID" -ne 0 ]]; then SETUP_USERNAME="${SETUP_USERNAME:-}" \ MACHINE_ROLE="${MACHINE_ROLE:-}" \ REPORT_FILE="${REPORT_FILE:-}" \ - bash "$SELF" "$@" + OFFICER_REPO="${OFFICER_REPO:-}" \ + bash "$SELF" ${ORIGINAL_ARGS[@]+"${ORIGINAL_ARGS[@]}"} fi diff --git a/scripts/setup/officer-setup.sh b/scripts/setup/officer-setup.sh index 69257ab4..0f379357 100755 --- a/scripts/setup/officer-setup.sh +++ b/scripts/setup/officer-setup.sh @@ -14,6 +14,13 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROGRESS_FILE="$SCRIPT_DIR/officer-setup/.setup-progress" ONLY_STEP="" + +# Kept before the loop consumes them. This script re-executes itself through sudo +# further down and was passing `"$@"`, which `shift` had already emptied — so +# `officer-setup.sh --only build` run as a normal user silently became a FULL run +# the moment it escalated. Nothing said so; the flag just stopped existing. +ORIGINAL_ARGS=(${@+"$@"}) + while [[ $# -gt 0 ]]; do case "$1" in --only) @@ -24,17 +31,38 @@ while [[ $# -gt 0 ]]; do ONLY_STEP="${1#*=}" shift ;; + # Set before lib/repo.sh is sourced below, which reads it as + # `${OFFICER_REPO:-}` — so this wins and an absent flag still defaults. + --repo) + [[ -n "${2:-}" ]] || { + echo "--repo needs a URL" >&2 + exit 2 + } + OFFICER_REPO="$2" + shift 2 + ;; + --repo=*) + OFFICER_REPO="${1#*=}" + shift + ;; -l | --list) grep -oP '^step "\K[^"]+' "${BASH_SOURCE[0]}" exit 0 ;; -h | --help) - echo "usage: officer-setup.sh [--only ] [--list]" + echo "usage: officer-setup.sh [--only ] [--list] [--repo ]" + echo "" + echo " --only run one step; --list names them" + echo " --repo clone from here instead of the default, which is a" + echo " private Gitea over SSH and only authenticates on a" + echo " machine whose key it already knows. Same as exporting" + echo " OFFICER_REPO. Ignored once the repo is checked out." exit 0 ;; *) echo "unknown option: $1" >&2 && exit 2 ;; esac done +export OFFICER_REPO="${OFFICER_REPO:-}" # shellcheck source=officer-setup/lib/base.sh source "$SCRIPT_DIR/report.sh" @@ -90,7 +118,8 @@ elif [[ "$EUID" -ne 0 ]]; then SETUP_USERNAME="${SETUP_USERNAME:-}" \ MACHINE_ROLE="${MACHINE_ROLE:-}" \ REPORT_FILE="${REPORT_FILE:-}" \ - bash "$SCRIPT_DIR/officer-setup.sh" "$@" + OFFICER_REPO="${OFFICER_REPO:-}" \ + bash "$SCRIPT_DIR/officer-setup.sh" ${ORIGINAL_ARGS[@]+"${ORIGINAL_ARGS[@]}"} fi trap report_flush EXIT