feat(runner): status, remove, and repoint — the runner lifecycle verbs #11
6 changed files with 423 additions and 7 deletions
42
bin/rig
42
bin/rig
|
|
@ -20,10 +20,22 @@ commands:
|
|||
systemd timer. rig installs the machinery and templates an empty
|
||||
0600 bindings file; you fill in the age recipient and S3 details.
|
||||
Control-plane box only. Run as root.
|
||||
runner install --repo <owner/repo> --version <pin> [options]
|
||||
runner install --repo <owner/repo> [options]
|
||||
GitHub Actions runner as a systemd service under an unprivileged
|
||||
user — outbound-only, no Docker. Prompts for the short-lived
|
||||
registration token (RUNNER_TOKEN env overrides). Run as root.
|
||||
runner status [--user <name>]
|
||||
What this box's runner is registered to: repo, name, labels, unit.
|
||||
Reads the box only — no token, no network call. Run as root.
|
||||
runner remove [--local] [--user <name>]
|
||||
Take the service down and deregister the runner. Prompts for the
|
||||
short-lived removal token (RUNNER_REMOVE_TOKEN env overrides).
|
||||
Run as root.
|
||||
runner repoint --repo <owner/repo> [options]
|
||||
Move an installed runner to another repository — deregister, then
|
||||
re-register, reusing the binary already on the box. Needs a removal
|
||||
token for the old repo and a registration token for the new one.
|
||||
Run as root.
|
||||
|
||||
install/upgrade:
|
||||
curl -fsSL https://raw.githubusercontent.com/heavy-duty/rig/main/install.sh | bash
|
||||
|
|
@ -62,12 +74,28 @@ case "$cmd" in
|
|||
runner)
|
||||
shift
|
||||
sub="${1:-}"
|
||||
if [ "$sub" != "install" ]; then
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
shift
|
||||
exec "$ROOT/commands/runner-install.sh" "$@"
|
||||
case "$sub" in
|
||||
install)
|
||||
shift
|
||||
exec "$ROOT/commands/runner-install.sh" "$@"
|
||||
;;
|
||||
status)
|
||||
shift
|
||||
exec "$ROOT/commands/runner-status.sh" "$@"
|
||||
;;
|
||||
remove)
|
||||
shift
|
||||
exec "$ROOT/commands/runner-remove.sh" "$@"
|
||||
;;
|
||||
repoint)
|
||||
shift
|
||||
exec "$ROOT/commands/runner-repoint.sh" "$@"
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-h|--help|help)
|
||||
usage
|
||||
|
|
|
|||
|
|
@ -162,6 +162,11 @@ else
|
|||
(cd "$RUNNER_DIR" && runuser -u "$RUNNER_USER" -- env HOME="$USER_HOME" \
|
||||
./config.sh --url "https://github.com/${REPO}" --token "$RUNNER_TOKEN" \
|
||||
--name "$RUNNER_NAME" --labels "$LABELS" --unattended --replace)
|
||||
# GitHub owns the labels and the runner does not persist them locally, so
|
||||
# `runner status` and `runner repoint` would have nothing to read. Record
|
||||
# what we registered with — box-local metadata, never a credential.
|
||||
printf '%s\n' "$LABELS" > "$RUNNER_DIR/.rig-labels"
|
||||
chown "$RUNNER_USER:$RUNNER_USER" "$RUNNER_DIR/.rig-labels"
|
||||
fi
|
||||
|
||||
# --- service -------------------------------------------------------------
|
||||
|
|
|
|||
108
commands/runner-remove.sh
Executable file
108
commands/runner-remove.sh
Executable file
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/env bash
|
||||
# rig runner remove — take the service down and deregister the runner.
|
||||
# Convergent: a box with nothing installed exits 0.
|
||||
set -euo pipefail
|
||||
|
||||
log() { printf 'rig-runner: %s\n' "$*"; }
|
||||
warn() { printf 'rig-runner: WARNING: %s\n' "$*" >&2; }
|
||||
die() { printf 'rig-runner: ERROR: %s\n' "$1" >&2; exit "${2:-1}"; }
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
usage: rig runner remove [options]
|
||||
|
||||
--local wipe this box's registration without contacting GitHub
|
||||
(no token needed)
|
||||
--user <name> unprivileged service user (default: github-runner)
|
||||
|
||||
Stops and uninstalls the systemd service, then deregisters the runner from
|
||||
GitHub. The runner binary and its user stay on the box, so a later
|
||||
`rig runner install` re-registers without downloading anything.
|
||||
|
||||
Provide the short-lived REMOVAL token — not a registration token, they are
|
||||
different endpoints — via the RUNNER_REMOVE_TOKEN env var or the interactive
|
||||
prompt:
|
||||
gh api -X POST repos/<owner/repo>/actions/runners/remove-token
|
||||
It is consumed at deregistration and never written to disk by rig.
|
||||
|
||||
--local is the escape hatch for when the registration is already gone
|
||||
server-side, or you cannot mint a token: the box is cleaned, but a stale
|
||||
offline runner is left listed in the repo — delete it by hand from
|
||||
Settings > Actions > Runners.
|
||||
|
||||
Convergent: safe to re-run; a box with no runner installed exits 0.
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- args (validated before the root check, so errors are testable) ---------
|
||||
LOCAL=0
|
||||
RUNNER_USER="github-runner"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--local) LOCAL=1; shift ;;
|
||||
--user)
|
||||
[ $# -ge 2 ] || die "--user needs a value" 2
|
||||
RUNNER_USER="$2"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "unknown flag: $1" 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- validation ------------------------------------------------------------
|
||||
[ "$RUNNER_USER" != "root" ] || die "runner user must not be root" 2
|
||||
|
||||
# --- guards ----------------------------------------------------------------
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root"
|
||||
|
||||
# --- nothing to remove? -----------------------------------------------------
|
||||
if ! id -u "$RUNNER_USER" >/dev/null 2>&1; then
|
||||
log "no ${RUNNER_USER} user on this box; nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
USER_HOME="$(getent passwd "$RUNNER_USER" | cut -d: -f6)"
|
||||
RUNNER_DIR="$USER_HOME/actions-runner"
|
||||
if [ ! -e "$RUNNER_DIR/.runner" ] && [ ! -e "$RUNNER_DIR/.service" ]; then
|
||||
log "no runner registered in ${RUNNER_DIR}; nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- removal token — only when a server-side deregistration is pending -------
|
||||
REMOVE_TOKEN=""
|
||||
if [ -e "$RUNNER_DIR/.runner" ] && [ "$LOCAL" -eq 0 ]; then
|
||||
REMOVE_TOKEN="${RUNNER_REMOVE_TOKEN:-}"
|
||||
if [ -z "$REMOVE_TOKEN" ]; then
|
||||
read -rsp "runner removal token (short-lived): " REMOVE_TOKEN
|
||||
echo
|
||||
fi
|
||||
[ -n "$REMOVE_TOKEN" ] || die "empty removal token"
|
||||
fi
|
||||
|
||||
# --- service ---------------------------------------------------------------
|
||||
# This must come first in BOTH paths. config.sh's removal throws "Uninstall
|
||||
# service first" while the service is configured; and `remove --local` skips
|
||||
# that check entirely, which would otherwise strand a running service pointed
|
||||
# at config that no longer exists.
|
||||
if [ -e "$RUNNER_DIR/.service" ]; then
|
||||
log "stopping and uninstalling the service"
|
||||
(cd "$RUNNER_DIR" && ./svc.sh stop)
|
||||
(cd "$RUNNER_DIR" && ./svc.sh uninstall)
|
||||
else
|
||||
log "no service installed; skipping"
|
||||
fi
|
||||
|
||||
# --- deregister -------------------------------------------------------------
|
||||
if [ -e "$RUNNER_DIR/.runner" ]; then
|
||||
if [ "$LOCAL" -eq 1 ]; then
|
||||
log "wiping the local registration only (--local)"
|
||||
(cd "$RUNNER_DIR" && runuser -u "$RUNNER_USER" -- env HOME="$USER_HOME" \
|
||||
./config.sh remove --local)
|
||||
warn "a stale offline runner is still listed in the repo — delete it from Settings > Actions > Runners"
|
||||
else
|
||||
log "deregistering from GitHub"
|
||||
(cd "$RUNNER_DIR" && runuser -u "$RUNNER_USER" -- env HOME="$USER_HOME" \
|
||||
./config.sh remove --token "$REMOVE_TOKEN")
|
||||
fi
|
||||
rm -f "$RUNNER_DIR/.rig-labels"
|
||||
fi
|
||||
|
||||
log "runner removed; the binary stays at ${RUNNER_DIR} for a future rig runner install"
|
||||
162
commands/runner-repoint.sh
Executable file
162
commands/runner-repoint.sh
Executable file
|
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/env bash
|
||||
# rig runner repoint — move an installed runner from one repository to another.
|
||||
# Deregister, then re-register against the new repo, reusing the binary that is
|
||||
# already on the box.
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
||||
|
||||
log() { printf 'rig-runner: %s\n' "$*"; }
|
||||
warn() { printf 'rig-runner: WARNING: %s\n' "$*" >&2; }
|
||||
die() { printf 'rig-runner: ERROR: %s\n' "$1" >&2; exit "${2:-1}"; }
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
usage: rig runner repoint --repo <owner/repo> [options]
|
||||
|
||||
--repo <owner/repo> the repository to move the runner TO (required)
|
||||
--name <name> runner name (default: keep the name it has now)
|
||||
--labels <csv> runner labels (default: the labels rig recorded at
|
||||
install; else ci-runner)
|
||||
--user <name> unprivileged service user (default: github-runner)
|
||||
--local skip the server-side deregistration of the OLD repo
|
||||
(no removal token needed) — leaves a stale offline
|
||||
runner listed there, to delete by hand
|
||||
|
||||
Deregisters the runner from the repository it is on now and registers it
|
||||
against --repo. The runner binary, its user, and its systemd service are
|
||||
reused, so nothing is downloaded.
|
||||
|
||||
Two short-lived tokens, each minted from its OWN repository:
|
||||
|
||||
RUNNER_REMOVE_TOKEN removal token, from the CURRENT repo (not needed
|
||||
with --local)
|
||||
gh api -X POST repos/<current>/actions/runners/remove-token
|
||||
RUNNER_TOKEN registration token, from the repo in --repo
|
||||
gh api -X POST repos/<new>/actions/runners/registration-token
|
||||
|
||||
Either may be typed at the prompt instead. Both are collected BEFORE the
|
||||
runner is touched — a token you turn out not to have should fail while the
|
||||
runner is still registered, not halfway through the move. Neither is written
|
||||
to disk by rig.
|
||||
|
||||
LABELS ARE NOT RECOVERABLE FROM THE BOX: GitHub holds them and the runner
|
||||
does not persist them. rig records what it registered with, but a runner
|
||||
installed before rig did that has nothing to read — repoint then falls back
|
||||
to the ci-runner default and says so. Check your workflows' runs-on.
|
||||
|
||||
Convergent: repointing to the repo it is already on changes nothing, exits 0,
|
||||
and never asks for a token.
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- args (validated before the root check, so errors are testable) ---------
|
||||
REPO=""
|
||||
RUNNER_NAME=""
|
||||
LABELS=""
|
||||
RUNNER_USER="github-runner"
|
||||
LOCAL=0
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--repo)
|
||||
[ $# -ge 2 ] || die "--repo needs a value" 2
|
||||
REPO="$2"; shift 2 ;;
|
||||
--name)
|
||||
[ $# -ge 2 ] || die "--name needs a value" 2
|
||||
RUNNER_NAME="$2"; shift 2 ;;
|
||||
--labels)
|
||||
[ $# -ge 2 ] || die "--labels needs a value" 2
|
||||
LABELS="$2"; shift 2 ;;
|
||||
--user)
|
||||
[ $# -ge 2 ] || die "--user needs a value" 2
|
||||
RUNNER_USER="$2"; shift 2 ;;
|
||||
--local) LOCAL=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "unknown flag: $1" 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- validation ------------------------------------------------------------
|
||||
[ -n "$REPO" ] || die "--repo <owner/repo> is required" 2
|
||||
if ! printf '%s' "$REPO" | grep -qE '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$'; then
|
||||
die "--repo must be owner/repo" 2
|
||||
fi
|
||||
[ "$RUNNER_USER" != "root" ] || die "runner user must not be root" 2
|
||||
|
||||
# --- guards ----------------------------------------------------------------
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root"
|
||||
|
||||
id -u "$RUNNER_USER" >/dev/null 2>&1 \
|
||||
|| die "no runner installed (no ${RUNNER_USER} user) — use: rig runner install"
|
||||
USER_HOME="$(getent passwd "$RUNNER_USER" | cut -d: -f6)"
|
||||
RUNNER_DIR="$USER_HOME/actions-runner"
|
||||
[ -e "$RUNNER_DIR/.runner" ] \
|
||||
|| die "no runner registered in ${RUNNER_DIR} — use: rig runner install"
|
||||
|
||||
# --- what is it registered to now? ------------------------------------------
|
||||
json_field() {
|
||||
grep -o "\"$2\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$1" \
|
||||
| head -n1 | sed 's/.*:[[:space:]]*"//; s/"$//'
|
||||
}
|
||||
CURRENT_URL="$(json_field "$RUNNER_DIR/.runner" gitHubUrl)"
|
||||
TARGET_URL="https://github.com/${REPO}"
|
||||
|
||||
if [ "$CURRENT_URL" = "$TARGET_URL" ]; then
|
||||
log "already registered to ${REPO}; nothing to do"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Keep the runner's identity across the move unless told otherwise.
|
||||
if [ -z "$RUNNER_NAME" ]; then
|
||||
RUNNER_NAME="$(json_field "$RUNNER_DIR/.runner" agentName)"
|
||||
[ -n "$RUNNER_NAME" ] || die "could not read the current runner name from ${RUNNER_DIR}/.runner"
|
||||
fi
|
||||
if [ -z "$LABELS" ]; then
|
||||
if [ -r "$RUNNER_DIR/.rig-labels" ]; then
|
||||
LABELS="$(cat "$RUNNER_DIR/.rig-labels")"
|
||||
else
|
||||
LABELS="ci-runner"
|
||||
warn "this box has no rig label record (installed before rig kept one)"
|
||||
warn "re-registering with the default labels: ${LABELS}"
|
||||
warn "if your workflows' runs-on expects anything else, ctrl-c and pass --labels"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "moving runner ${RUNNER_NAME} from ${CURRENT_URL} to ${TARGET_URL}"
|
||||
log "labels: ${LABELS}"
|
||||
|
||||
# --- tokens, both up front --------------------------------------------------
|
||||
# Collected before anything is torn down: a missing or expired token must fail
|
||||
# while the runner is still registered and working.
|
||||
if [ "$LOCAL" -eq 0 ]; then
|
||||
RUNNER_REMOVE_TOKEN="${RUNNER_REMOVE_TOKEN:-}"
|
||||
if [ -z "$RUNNER_REMOVE_TOKEN" ]; then
|
||||
read -rsp "removal token for ${CURRENT_URL} (short-lived): " RUNNER_REMOVE_TOKEN
|
||||
echo
|
||||
fi
|
||||
[ -n "$RUNNER_REMOVE_TOKEN" ] || die "empty removal token"
|
||||
export RUNNER_REMOVE_TOKEN
|
||||
fi
|
||||
|
||||
RUNNER_TOKEN="${RUNNER_TOKEN:-}"
|
||||
if [ -z "$RUNNER_TOKEN" ]; then
|
||||
read -rsp "registration token for ${TARGET_URL} (short-lived): " RUNNER_TOKEN
|
||||
echo
|
||||
fi
|
||||
[ -n "$RUNNER_TOKEN" ] || die "empty registration token"
|
||||
export RUNNER_TOKEN
|
||||
|
||||
# --- move -------------------------------------------------------------------
|
||||
REMOVE_ARGS=(--user "$RUNNER_USER")
|
||||
[ "$LOCAL" -eq 1 ] && REMOVE_ARGS+=(--local)
|
||||
"$HERE/runner-remove.sh" "${REMOVE_ARGS[@]}"
|
||||
|
||||
if ! "$HERE/runner-install.sh" \
|
||||
--repo "$REPO" --name "$RUNNER_NAME" --labels "$LABELS" --user "$RUNNER_USER"
|
||||
then
|
||||
warn "the runner is now deregistered from ${CURRENT_URL} and NOT registered anywhere"
|
||||
die "re-registration failed — fix the cause, then run: rig runner install --repo ${REPO} --name ${RUNNER_NAME} --labels ${LABELS} --user ${RUNNER_USER}"
|
||||
fi
|
||||
|
||||
log "repointed to ${TARGET_URL}"
|
||||
log "verify it shows Idle under that repo's Settings > Actions > Runners, and gone from the old one"
|
||||
81
commands/runner-status.sh
Executable file
81
commands/runner-status.sh
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env bash
|
||||
# rig runner status — what is this box's runner registered to?
|
||||
# Read-only: reports what is already on the box. No credential, no network call.
|
||||
set -euo pipefail
|
||||
|
||||
log() { printf 'rig-runner: %s\n' "$*"; }
|
||||
die() { printf 'rig-runner: ERROR: %s\n' "$1" >&2; exit "${2:-1}"; }
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
usage: rig runner status [--user <name>]
|
||||
|
||||
--user <name> unprivileged service user (default: github-runner)
|
||||
|
||||
Prints the repository this box's runner is registered to, its runner name,
|
||||
the labels rig recorded when it registered, the install directory, and the
|
||||
systemd unit and its state.
|
||||
|
||||
Reads only the runner's own on-disk config — no GitHub token, no network
|
||||
call. Exits 1 when no runner is installed.
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- args (validated before the root check, so errors are testable) ---------
|
||||
RUNNER_USER="github-runner"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--user)
|
||||
[ $# -ge 2 ] || die "--user needs a value" 2
|
||||
RUNNER_USER="$2"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "unknown flag: $1" 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- validation ------------------------------------------------------------
|
||||
[ "$RUNNER_USER" != "root" ] || die "runner user must not be root" 2
|
||||
|
||||
# --- guards ----------------------------------------------------------------
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root"
|
||||
|
||||
id -u "$RUNNER_USER" >/dev/null 2>&1 \
|
||||
|| die "no runner installed (no ${RUNNER_USER} user on this box)"
|
||||
USER_HOME="$(getent passwd "$RUNNER_USER" | cut -d: -f6)"
|
||||
RUNNER_DIR="$USER_HOME/actions-runner"
|
||||
[ -e "$RUNNER_DIR/.runner" ] \
|
||||
|| die "no runner registered in ${RUNNER_DIR}"
|
||||
|
||||
# --- read the runner's own config -------------------------------------------
|
||||
# .runner is JSON. Kept dependency-free on purpose: a rig-bootstrapped box has
|
||||
# no jq, and installing one to read five fields would be a poor trade.
|
||||
json_field() {
|
||||
grep -o "\"$2\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$1" \
|
||||
| head -n1 | sed 's/.*:[[:space:]]*"//; s/"$//'
|
||||
}
|
||||
|
||||
REPO_URL="$(json_field "$RUNNER_DIR/.runner" gitHubUrl)"
|
||||
RUNNER_NAME="$(json_field "$RUNNER_DIR/.runner" agentName)"
|
||||
|
||||
# GitHub owns the labels; the runner does not persist them locally. rig records
|
||||
# what it registered with, so a box installed before this existed reports the
|
||||
# honest answer rather than a guess.
|
||||
if [ -r "$RUNNER_DIR/.rig-labels" ]; then
|
||||
LABELS="$(cat "$RUNNER_DIR/.rig-labels")"
|
||||
else
|
||||
LABELS="(not recorded on this box — GitHub holds them; see the repo's Settings > Actions > Runners)"
|
||||
fi
|
||||
|
||||
if [ -r "$RUNNER_DIR/.service" ]; then
|
||||
UNIT="$(cat "$RUNNER_DIR/.service")"
|
||||
STATE="$(systemctl is-active "$UNIT" 2>/dev/null || true)"
|
||||
SERVICE="${UNIT} (${STATE:-unknown})"
|
||||
else
|
||||
SERVICE="(not installed as a service)"
|
||||
fi
|
||||
|
||||
log "repo: ${REPO_URL:-unknown}"
|
||||
log "name: ${RUNNER_NAME:-unknown}"
|
||||
log "labels: ${LABELS}"
|
||||
log "dir: ${RUNNER_DIR}"
|
||||
log "service: ${SERVICE}"
|
||||
32
test/cli.sh
32
test/cli.sh
|
|
@ -80,6 +80,38 @@ else
|
|||
echo "skip: runner non-root refusal (running as root)"
|
||||
fi
|
||||
|
||||
check "runner: bad subcommand exits 2" 2 "usage:" "$ROOT/bin/rig" runner frobnicate
|
||||
|
||||
check "runner status: --help exits 0" 0 "usage:" "$ROOT/commands/runner-status.sh" --help
|
||||
check "runner status: user needs value" 2 "needs a value" "$ROOT/commands/runner-status.sh" --user
|
||||
check "runner status: refuses --user root" 2 "must not be root" "$ROOT/commands/runner-status.sh" --user root
|
||||
check "runner status: unknown flag exits 2" 2 "unknown flag" "$ROOT/commands/runner-status.sh" --nope
|
||||
|
||||
check "runner remove: --help exits 0" 0 "usage:" "$ROOT/commands/runner-remove.sh" --help
|
||||
check "runner remove: user needs value" 2 "needs a value" "$ROOT/commands/runner-remove.sh" --user
|
||||
check "runner remove: refuses --user root" 2 "must not be root" "$ROOT/commands/runner-remove.sh" --user root
|
||||
check "runner remove: unknown flag exits 2" 2 "unknown flag" "$ROOT/commands/runner-remove.sh" --nope
|
||||
|
||||
check "runner repoint: --help exits 0" 0 "usage:" "$ROOT/commands/runner-repoint.sh" --help
|
||||
check "runner repoint: repo required" 2 "--repo" "$ROOT/commands/runner-repoint.sh"
|
||||
check "runner repoint: repo needs value" 2 "needs a value" "$ROOT/commands/runner-repoint.sh" --repo
|
||||
check "runner repoint: rejects bad slug" 2 "owner/repo" "$ROOT/commands/runner-repoint.sh" --repo not-a-slug
|
||||
check "runner repoint: labels need value" 2 "needs a value" "$ROOT/commands/runner-repoint.sh" --repo acme/widgets --labels
|
||||
check "runner repoint: refuses --user root" 2 "must not be root" "$ROOT/commands/runner-repoint.sh" --repo acme/widgets --user root
|
||||
check "runner repoint: unknown flag exits 2" 2 "unknown flag" "$ROOT/commands/runner-repoint.sh" --nope
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
check "runner status: refuses non-root" 1 "must run as root" "$ROOT/commands/runner-status.sh"
|
||||
check "runner remove: refuses non-root" 1 "must run as root" \
|
||||
env RUNNER_REMOVE_TOKEN=x "$ROOT/commands/runner-remove.sh"
|
||||
# --local too: the token-free path must still not be runnable by the runner user.
|
||||
check "runner remove: --local refuses non-root" 1 "must run as root" \
|
||||
"$ROOT/commands/runner-remove.sh" --local
|
||||
check "runner repoint: refuses non-root" 1 "must run as root" \
|
||||
env RUNNER_REMOVE_TOKEN=x RUNNER_TOKEN=y "$ROOT/commands/runner-repoint.sh" --repo acme/widgets
|
||||
else
|
||||
echo "skip: runner status/remove/repoint non-root refusals (running as root)"
|
||||
fi
|
||||
|
||||
# The dump script ships to control-plane boxes as an embedded heredoc. A syntax
|
||||
# error in it would be invisible here and would first surface at 04:00 on a live
|
||||
# control plane. Extract it and syntax-check what actually gets written.
|
||||
|
|
|
|||
Loading…
Reference in a new issue