feat: Forgejo-native CI — a ci-box tenant and a forgejo-runner command family #110
7 changed files with 207 additions and 72 deletions
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
|
|
@ -11,7 +11,9 @@
|
|||
"scope:runner":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
["commands/runner-*.sh", "commands/lib/runner-config.sh"]
|
||||
["commands/runner-*.sh", "commands/lib/runner-config.sh",
|
||||
"commands/forgejo-runner-*.sh", "commands/lib/forgejo-runner-config.sh",
|
||||
"docs/templates/ci-box/**"]
|
||||
"scope:coolify":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ["commands/coolify-*.sh"]
|
||||
|
|
|
|||
2
.github/labels.conf
vendored
2
.github/labels.conf
vendored
|
|
@ -2,7 +2,7 @@ panel=claude-bot-andresmgsl codex-bot-andresmgsl grok-bot-andresmgsl kimi-bot-an
|
|||
triage-actors=dan-claude-bot
|
||||
scope:bootstrap|C5DEF5|bootstrap — hardening a pristine server into a node
|
||||
scope:users|C5DEF5|users-* — class model, apply/status, close-root
|
||||
scope:runner|C5DEF5|runner-* — GitHub runner lifecycle
|
||||
scope:runner|C5DEF5|runner-* / forgejo-runner-* — CI runner lifecycle, either forge
|
||||
scope:coolify|C5DEF5|coolify-* — Coolify and backup install
|
||||
scope:db|C5DEF5|db.sh — dump/restore
|
||||
scope:installer|C5DEF5|install.sh — how rig lands on a machine
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -1174,6 +1174,28 @@ FORGEJO__actions__ENABLED=true
|
|||
FORGEJO__actions__DEFAULT_ACTIONS_URL=https://code.forgejo.org
|
||||
```
|
||||
|
||||
> **`DEFAULT_ACTIONS_URL` is a single fallback, and rig's own workflows need
|
||||
> two origins.** It decides where a *bare* `uses: owner/repo@ref` resolves.
|
||||
> Measured:
|
||||
>
|
||||
> | reference | count in `.github/workflows/` | `code.forgejo.org` |
|
||||
> |---|---|---|
|
||||
> | `actions/checkout@v4` | 3 | **200** — mirrored |
|
||||
> | `heavy-duty/ceremony/...@0.3.0` | 8 | **404** — lives on this Forgejo instead |
|
||||
>
|
||||
> So with the value above, every ceremony guard (`changelog-armed`,
|
||||
> `changelog-monotonic`, `changelog-assembled`, `drill-recorded`,
|
||||
> `runner-isolated`, `docs-sync`, and the release/labels callers) fails to
|
||||
> resolve the moment rig's CI actually runs on the forge.
|
||||
>
|
||||
> Forgejo accepts an absolute URL per step, so one side has to be explicit —
|
||||
> which one is a **decision this PR does not make**. Either set the default to
|
||||
> this instance and make the three `actions/*` references absolute
|
||||
> (`uses: https://code.forgejo.org/actions/checkout@v4`), or keep the value
|
||||
> above and make the eight ceremony references absolute. Until that lands,
|
||||
> **rig's CI is not expected to run on Forgejo** — `rig forgejo-runner` is for
|
||||
> running *your* repositories' workflows, and does not depend on this.
|
||||
|
||||
> **A registry served from Forgejo needs one more.** `RIG_TEMPLATES_HOST`
|
||||
> (below) lets the template registry live on any forge, but the mint-time fetch
|
||||
> is **unauthenticated by contract** — box auto-runs `rig bootstrap <role>-box`
|
||||
|
|
|
|||
|
|
@ -33,6 +33,55 @@ die() { printf 'rig-forgejo-runner: ERROR: %s\n' "$1" >&2; exit "${2:-1}"; }
|
|||
# from a shared CI server, and inside a box that boundary is already paid for.
|
||||
DEFAULT_LABELS='ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-22.04,docker:docker://node:22-bookworm'
|
||||
|
||||
# fetch_and_verify_sha256 <asset-url> <file> <sumfile> <label>
|
||||
#
|
||||
# The whole checksum POLICY, in one place: fetch the published .sha256 beside
|
||||
# an asset and prove the download matches it. Prints the reason on stderr and
|
||||
# returns 1 on any failure; the caller supplies the refusal in its own voice.
|
||||
#
|
||||
# BYTE-IDENTICAL to the copy in docs/templates/ci-box/install.sh, diffed by
|
||||
# test/cli.sh — the valid_version / templates_archive_urls precedent. The two
|
||||
# downloaders cannot share a lib: this one sources commands/lib/, and that one
|
||||
# is a REGISTRY DEFINITION that runs standalone inside a mint from a fetched
|
||||
# tarball, with rig's tree nowhere in reach. So the pin is the only mechanism
|
||||
# that keeps one policy from becoming two.
|
||||
#
|
||||
# Review !110 is the evidence for why that matters: a fail-open branch lived in
|
||||
# BOTH copies while a grep for "checksum mismatch" passed against both, because
|
||||
# the string it looked for sat right beside the branch it could not see. The
|
||||
# next checksum-policy change must not be able to land in one file only.
|
||||
#
|
||||
# AN UNFETCHABLE CHECKSUM REFUSES — it is a gate, not a courtesy. The earlier
|
||||
# reasoning ("do not let an upstream layout change break installs") reasons
|
||||
# about the wrong failure: a layout change moves the BINARY url too, so the
|
||||
# download would already have died. "Binary yes, checksum no" is not what a
|
||||
# layout change looks like — it is what an interfered fetch looks like, which
|
||||
# is precisely what a checksum exists to catch. Failing open would hand an
|
||||
# unverified root install to anyone able to block a single URL. There is
|
||||
# deliberately no bypass flag: if upstream really does move its assets, that is
|
||||
# a rig PR editing the URL, not an operator improvising past a security gate.
|
||||
fetch_and_verify_sha256() {
|
||||
local url="$1" file="$2" sumfile="$3" label="$4" want got
|
||||
if ! curl -fsSL "${url}.sha256" -o "$sumfile" 2>/dev/null; then
|
||||
printf 'no published .sha256 for %s at %s.sha256 — the binary itself downloaded, so this is not an upstream layout change; check what is intercepting the fetch\n' "$label" "$url" >&2
|
||||
return 1
|
||||
fi
|
||||
# The published .sha256 names the asset, not our temp path. Compare the
|
||||
# digest itself rather than rewriting the file into sha256sum -c's format:
|
||||
# one comparison, no parsing of a file we did not write.
|
||||
want="$(tr -d '\r' < "$sumfile" 2>/dev/null | awk '{print $1}' | head -n1)"
|
||||
got="$(sha256sum "$file" | awk '{print $1}')"
|
||||
if [ -z "$want" ]; then
|
||||
printf 'the published checksum for %s is unreadable — a fetch that succeeds but returns nothing usable is not a verified download\n' "$label" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$want" != "$got" ]; then
|
||||
printf 'checksum mismatch for %s: published %s, downloaded %s\n' "$label" "$want" "$got" >&2
|
||||
return 1
|
||||
fi
|
||||
printf 'checksum verified (%s)\n' "$got"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
usage: rig forgejo-runner install --instance <url> [options]
|
||||
|
|
@ -286,35 +335,8 @@ if [ "$NEED_DOWNLOAD" -eq 1 ]; then
|
|||
log "downloading forgejo-runner ${VERSION} (${ARCH})"
|
||||
curl -fsSL "$URL" -o "$WORKDIR/forgejo-runner" \
|
||||
|| die "could not download ${URL}"
|
||||
# THE CHECKSUM IS A GATE, NOT A COURTESY — an unfetchable one refuses.
|
||||
#
|
||||
# This previously warned and installed anyway, reasoning that rig should not
|
||||
# become unable to install if upstream changed its asset layout. That reasons
|
||||
# about the wrong failure. The binary lands as root and is executed by a
|
||||
# systemd unit, and the two ways the checksum can go missing are:
|
||||
#
|
||||
# - upstream moved the assets — in which case the BINARY url moved too, and
|
||||
# the download above would already have died. A layout change does not
|
||||
# present as "binary yes, checksum no".
|
||||
# - something is interfering with the fetch — which is precisely the case
|
||||
# the checksum exists to catch.
|
||||
#
|
||||
# So the asymmetry is itself the signal: same origin, same release tag, one
|
||||
# answers and one does not. Failing open there hands an unverified root
|
||||
# install to anyone who can block a single URL. There is deliberately no
|
||||
# bypass flag: if upstream really does change layout, that is a rig PR
|
||||
# editing the URL above, not an operator improvising past a security gate.
|
||||
curl -fsSL "${URL}.sha256" -o "$WORKDIR/forgejo-runner.sha256" 2>/dev/null \
|
||||
|| die "no published .sha256 for ${ASSET} at ${URL}.sha256 — refusing to install an unverified binary that runs as root. The binary itself downloaded, so this is not an upstream layout change; check what is intercepting the fetch."
|
||||
# The published .sha256 names the asset, not our temp path. Compare the
|
||||
# digest itself rather than rewriting the file into sha256sum -c's format:
|
||||
# one comparison, no parsing of a file we did not write.
|
||||
WANT="$(tr -d '\r' < "$WORKDIR/forgejo-runner.sha256" | awk '{print $1}' | head -n1)"
|
||||
GOT="$(sha256sum "$WORKDIR/forgejo-runner" | awk '{print $1}')"
|
||||
[ -n "$WANT" ] || die "the published checksum for ${ASSET} is unreadable — refusing to install an unverified binary"
|
||||
[ "$WANT" = "$GOT" ] \
|
||||
|| die "checksum mismatch for ${ASSET}: published ${WANT}, downloaded ${GOT} — refusing to install"
|
||||
log "checksum verified (${GOT})"
|
||||
fetch_and_verify_sha256 "$URL" "$WORKDIR/forgejo-runner" "$WORKDIR/forgejo-runner.sha256" "$ASSET" \
|
||||
|| die "refusing to install an unverified ${ASSET} — it lands as root and runs under a systemd unit. See the checksum failure above."
|
||||
|
||||
# Staged beside the target and RENAMED into place, never written over.
|
||||
# Replacing a running executable in place fails with ETXTBSY, and this path
|
||||
|
|
|
|||
|
|
@ -67,19 +67,36 @@ fi
|
|||
UNIT=/etc/systemd/system/forgejo-runner.service
|
||||
|
||||
# --- nothing to remove? -----------------------------------------------------
|
||||
if ! id -u "$RUNNER_USER" >/dev/null 2>&1; then
|
||||
log "no ${RUNNER_USER} user on this box; nothing to remove"
|
||||
# The unit is checked INDEPENDENTLY of the user, and that ordering is the whole
|
||||
# point. A missing user used to exit 0 here before the unit was ever looked at,
|
||||
# so a deleted account with a leftover forgejo-runner.service reported "nothing
|
||||
# to remove" and left the unit behind — while the absence-assert at the end,
|
||||
# which never ran, implied removal had been complete. `bootstrap --undo`'s own
|
||||
# unit check would still have caught it, but a verb that claims to have removed
|
||||
# everything must not be the thing that lies about it.
|
||||
RUNNER_DIR=""
|
||||
if id -u "$RUNNER_USER" >/dev/null 2>&1; then
|
||||
USER_HOME="$(getent passwd "$RUNNER_USER" | cut -d: -f6)"
|
||||
RUNNER_DIR="$USER_HOME/forgejo-runner"
|
||||
else
|
||||
log "no ${RUNNER_USER} user on this box"
|
||||
fi
|
||||
if [ -z "$RUNNER_DIR" ] && [ ! -e "$UNIT" ]; then
|
||||
log "no runner user and no unit on this box; nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
USER_HOME="$(getent passwd "$RUNNER_USER" | cut -d: -f6)"
|
||||
RUNNER_DIR="$USER_HOME/forgejo-runner"
|
||||
if [ ! -e "$RUNNER_DIR/.runner" ] && [ ! -e "$UNIT" ]; then
|
||||
if [ -n "$RUNNER_DIR" ] && [ ! -e "$RUNNER_DIR/.runner" ] && [ ! -e "$UNIT" ]; then
|
||||
log "no runner registered in ${RUNNER_DIR}; nothing to remove"
|
||||
exit 0
|
||||
fi
|
||||
[ -n "$RUNNER_DIR" ] || warn "the ${RUNNER_USER} user is gone but ${UNIT} is still here — removing the orphaned unit"
|
||||
|
||||
INSTANCE="$(forgejo_runner_instance "$RUNNER_DIR")"
|
||||
RUNNER_NAME="$(forgejo_runner_name "$RUNNER_DIR")"
|
||||
INSTANCE=""
|
||||
RUNNER_NAME=""
|
||||
if [ -n "$RUNNER_DIR" ]; then
|
||||
INSTANCE="$(forgejo_runner_instance "$RUNNER_DIR")"
|
||||
RUNNER_NAME="$(forgejo_runner_name "$RUNNER_DIR")"
|
||||
fi
|
||||
|
||||
# --- service ---------------------------------------------------------------
|
||||
# First, in both paths: stopping after the registration is wiped would strand a
|
||||
|
|
@ -95,16 +112,23 @@ else
|
|||
fi
|
||||
|
||||
# --- registration -----------------------------------------------------------
|
||||
if [ -e "$RUNNER_DIR/.runner" ]; then
|
||||
rm -f "$RUNNER_DIR/.runner"
|
||||
log "wiped the local registration"
|
||||
# Every path below is gated on RUNNER_DIR being non-empty. With the user gone
|
||||
# it is "", and an unguarded "$RUNNER_DIR/.rig-labels" would expand to
|
||||
# "/.rig-labels" — an rm at the filesystem root, as root. The repo already
|
||||
# treats this class of expansion as a hazard worth spelling out (`rm -rf
|
||||
# "${ir:?}/versions/$ver"` in bin/rig); same discipline here.
|
||||
if [ -n "$RUNNER_DIR" ]; then
|
||||
if [ -e "$RUNNER_DIR/.runner" ]; then
|
||||
rm -f "$RUNNER_DIR/.runner"
|
||||
log "wiped the local registration"
|
||||
fi
|
||||
rm -f "$RUNNER_DIR/.rig-labels"
|
||||
fi
|
||||
rm -f "$RUNNER_DIR/.rig-labels"
|
||||
|
||||
# END WITH THE ABSENCE ASSERT: "removed" is a claim, and claims get verified
|
||||
# (the `rig uninstall` precedent).
|
||||
leftover=""
|
||||
[ -e "$RUNNER_DIR/.runner" ] && leftover="$leftover $RUNNER_DIR/.runner"
|
||||
[ -n "$RUNNER_DIR" ] && [ -e "$RUNNER_DIR/.runner" ] && leftover="$leftover $RUNNER_DIR/.runner"
|
||||
[ -e "$UNIT" ] && leftover="$leftover $UNIT"
|
||||
if [ -n "$leftover" ]; then
|
||||
printf 'rig-forgejo-runner: remove INCOMPLETE — still present:%s\n' "$leftover" >&2
|
||||
|
|
|
|||
74
docs/templates/ci-box/install.sh
vendored
74
docs/templates/ci-box/install.sh
vendored
|
|
@ -18,6 +18,55 @@
|
|||
# inside the box.
|
||||
set -euo pipefail
|
||||
|
||||
# fetch_and_verify_sha256 <asset-url> <file> <sumfile> <label>
|
||||
#
|
||||
# The whole checksum POLICY, in one place: fetch the published .sha256 beside
|
||||
# an asset and prove the download matches it. Prints the reason on stderr and
|
||||
# returns 1 on any failure; the caller supplies the refusal in its own voice.
|
||||
#
|
||||
# BYTE-IDENTICAL to the copy in commands/forgejo-runner-install.sh, diffed by
|
||||
# test/cli.sh — the valid_version / templates_archive_urls precedent. The two
|
||||
# downloaders cannot share a lib: that one sources commands/lib/, and this one
|
||||
# is a REGISTRY DEFINITION that runs standalone inside a mint from a fetched
|
||||
# tarball, with rig's tree nowhere in reach. So the pin is the only mechanism
|
||||
# that keeps one policy from becoming two.
|
||||
#
|
||||
# Review !110 is the evidence for why that matters: a fail-open branch lived in
|
||||
# BOTH copies while a grep for "checksum mismatch" passed against both, because
|
||||
# the string it looked for sat right beside the branch it could not see. The
|
||||
# next checksum-policy change must not be able to land in one file only.
|
||||
#
|
||||
# AN UNFETCHABLE CHECKSUM REFUSES — it is a gate, not a courtesy. The earlier
|
||||
# reasoning ("do not let an upstream layout change break installs") reasons
|
||||
# about the wrong failure: a layout change moves the BINARY url too, so the
|
||||
# download would already have died. "Binary yes, checksum no" is not what a
|
||||
# layout change looks like — it is what an interfered fetch looks like, which
|
||||
# is precisely what a checksum exists to catch. Failing open would hand an
|
||||
# unverified root install to anyone able to block a single URL. There is
|
||||
# deliberately no bypass flag: if upstream really does move its assets, that is
|
||||
# a rig PR editing the URL, not an operator improvising past a security gate.
|
||||
fetch_and_verify_sha256() {
|
||||
local url="$1" file="$2" sumfile="$3" label="$4" want got
|
||||
if ! curl -fsSL "${url}.sha256" -o "$sumfile" 2>/dev/null; then
|
||||
printf 'no published .sha256 for %s at %s.sha256 — the binary itself downloaded, so this is not an upstream layout change; check what is intercepting the fetch\n' "$label" "$url" >&2
|
||||
return 1
|
||||
fi
|
||||
# The published .sha256 names the asset, not our temp path. Compare the
|
||||
# digest itself rather than rewriting the file into sha256sum -c's format:
|
||||
# one comparison, no parsing of a file we did not write.
|
||||
want="$(tr -d '\r' < "$sumfile" 2>/dev/null | awk '{print $1}' | head -n1)"
|
||||
got="$(sha256sum "$file" | awk '{print $1}')"
|
||||
if [ -z "$want" ]; then
|
||||
printf 'the published checksum for %s is unreadable — a fetch that succeeds but returns nothing usable is not a verified download\n' "$label" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$want" != "$got" ]; then
|
||||
printf 'checksum mismatch for %s: published %s, downloaded %s\n' "$label" "$want" "$got" >&2
|
||||
return 1
|
||||
fi
|
||||
printf 'checksum verified (%s)\n' "$got"
|
||||
}
|
||||
|
||||
BIN=/usr/local/bin/forgejo-runner
|
||||
|
||||
if [ -x "$BIN" ]; then
|
||||
|
|
@ -58,29 +107,8 @@ curl -fsSL "$URL" -o "$WORKDIR/forgejo-runner" \
|
|||
# Forgejo publishes a .sha256 beside each binary. Verifying it costs one
|
||||
# request and makes the install auditable; this file executes as root inside
|
||||
# every future mint, so an unverified download is the last thing it should do.
|
||||
# An unfetchable checksum REFUSES — it does not warn and continue. The comment
|
||||
# above says an unverified root download is the last thing this file should do,
|
||||
# and an earlier draft then did exactly that whenever the .sha256 404'd. The
|
||||
# binary downloading while its checksum does not is not an upstream layout
|
||||
# change (that would break both URLs); it is the shape of an interfered fetch,
|
||||
# which is the case the checksum exists to catch. Failing open here would hand
|
||||
# an unverified root install, inside every future mint, to anyone who can block
|
||||
# one URL.
|
||||
if ! curl -fsSL "${URL}.sha256" -o "$WORKDIR/forgejo-runner.sha256" 2>/dev/null; then
|
||||
echo "ci-box install: no published .sha256 for ${ASSET} — refusing to install an unverified binary that runs as root. The binary itself downloaded, so this is not an upstream layout change; check what is intercepting the fetch." >&2
|
||||
exit 1
|
||||
fi
|
||||
WANT="$(tr -d '\r' < "$WORKDIR/forgejo-runner.sha256" | awk '{print $1}' | head -n1)"
|
||||
GOT="$(sha256sum "$WORKDIR/forgejo-runner" | awk '{print $1}')"
|
||||
if [ -z "$WANT" ]; then
|
||||
echo "ci-box install: the published checksum for ${ASSET} is unreadable — refusing to install an unverified binary" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$WANT" != "$GOT" ]; then
|
||||
echo "ci-box install: checksum mismatch for ${ASSET}: published ${WANT}, downloaded ${GOT} — refusing to install" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "ci-box install: checksum verified (${GOT})"
|
||||
fetch_and_verify_sha256 "$URL" "$WORKDIR/forgejo-runner" "$WORKDIR/forgejo-runner.sha256" "$ASSET" \
|
||||
|| { echo "ci-box install: refusing to install an unverified ${ASSET} — it lands as root inside every mint. See the checksum failure above." >&2; exit 1; }
|
||||
|
||||
install -m 0755 -o root -g root "$WORKDIR/forgejo-runner" "$BIN"
|
||||
echo "ci-box install: installed ${BIN}"
|
||||
|
|
|
|||
49
test/cli.sh
49
test/cli.sh
|
|
@ -3207,6 +3207,26 @@ check "forgejo-runner: remove --local explains why it is not a flag" 2 "always l
|
|||
"$ROOT/commands/forgejo-runner-remove.sh" --local
|
||||
check "forgejo-runner: repoint explains why it cannot exist" 2 "no deregistration endpoint" \
|
||||
"$ROOT/bin/rig" forgejo-runner repoint --instance https://f.example.com
|
||||
# remove used to exit 0 on a missing user BEFORE looking at the unit, so a
|
||||
# deleted account with a leftover forgejo-runner.service reported "nothing to
|
||||
# remove" and stranded it — while the absence-assert that never ran implied the
|
||||
# opposite (review !110). The unit check must not sit behind the user check.
|
||||
remove_checks_unit_independently() {
|
||||
# The early-exit must require BOTH the user to be absent AND the unit to be
|
||||
# missing; a user-only guard is the regression.
|
||||
# shellcheck disable=SC2016 # the '$RUNNER_DIR'/'$UNIT' are LITERAL text being grepped for
|
||||
grep -q 'if \[ -z "\$RUNNER_DIR" \] && \[ ! -e "\$UNIT" \]' "$ROOT/commands/forgejo-runner-remove.sh"
|
||||
}
|
||||
check "forgejo-runner: remove checks the unit even when the user is gone" 0 "" \
|
||||
remove_checks_unit_independently
|
||||
check "forgejo-runner: remove warns about an orphaned unit" 0 "orphaned unit" \
|
||||
grep -o "orphaned unit" "$ROOT/commands/forgejo-runner-remove.sh"
|
||||
# With the user gone RUNNER_DIR is "", and an unguarded "$RUNNER_DIR/.rig-labels"
|
||||
# would expand to "/.rig-labels" — an rm at the filesystem root, as root.
|
||||
# shellcheck disable=SC2016 # the '$RUNNER_DIR' is LITERAL text being grepped for
|
||||
check "forgejo-runner: remove never rm's an unguarded \$RUNNER_DIR path" 1 "" \
|
||||
grep -qE '^rm -f "\$RUNNER_DIR' "$ROOT/commands/forgejo-runner-remove.sh"
|
||||
|
||||
check "forgejo-runner: status --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-status.sh" --help
|
||||
check "forgejo-runner: remove --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-remove.sh" --help
|
||||
|
||||
|
|
@ -3327,7 +3347,9 @@ check "ci-box: a matching checksum installs" 0 "checksum verified" \
|
|||
cibox_run CB_SUM="$CB_GOOD"
|
||||
check "ci-box: ...and the binary really landed" 0 "" cibox_installed
|
||||
# The regression this replaces: a 404 on .sha256 used to warn and install.
|
||||
check "ci-box: a MISSING checksum refuses (exit 1)" 1 "refusing to install an unverified binary" \
|
||||
check "ci-box: a MISSING checksum refuses (exit 1)" 1 "refusing to install an unverified" \
|
||||
cibox_run
|
||||
check "ci-box: ...naming the fetch, not blaming an upstream layout change" 1 "check what is intercepting the fetch" \
|
||||
cibox_run
|
||||
check "ci-box: ...and installed NOTHING" 1 "" cibox_installed
|
||||
check "ci-box: a MISMATCHED checksum refuses" 1 "checksum mismatch" \
|
||||
|
|
@ -3337,15 +3359,30 @@ check "ci-box: an EMPTY checksum file refuses" 1 "unreadable" cibox_run CB_SUM=E
|
|||
check "ci-box: ...and installed nothing there either" 1 "" cibox_installed
|
||||
rm -rf "$CBW"
|
||||
|
||||
# The rig command's copy of the gate must not drift back to failing open.
|
||||
# Grep-pinned only for the branch SHAPE (driving it needs root and systemd);
|
||||
# the behaviour itself is proven above on the byte-equivalent template path.
|
||||
check "forgejo-runner: install refuses an unfetchable checksum" 0 "refusing to install an unverified binary" \
|
||||
grep -o "refusing to install an unverified binary" "$FR"
|
||||
# ONE checksum policy, two files that cannot share a lib — the rig command
|
||||
# sources commands/lib/, the template is a registry definition that runs
|
||||
# standalone inside a mint with rig's tree nowhere in reach. So the copies are
|
||||
# byte-identical and diffed, the valid_version precedent (review !110).
|
||||
#
|
||||
# This pin is what the driven tests above cannot give on their own: they
|
||||
# exercise the TEMPLATE's copy, and without the diff a fix could land there
|
||||
# while the rig command kept a stale policy. That is exactly how fail-open
|
||||
# survived in both while a grep for "checksum mismatch" passed against both.
|
||||
FVLIB="$(mktemp)"; FVTPL="$(mktemp)"
|
||||
awk '/^fetch_and_verify_sha256\(\) \{/,/^\}/' "$FR" > "$FVLIB"
|
||||
awk '/^fetch_and_verify_sha256\(\) \{/,/^\}/' "$CIBOX" > "$FVTPL"
|
||||
check "checksum policy: extracted from the command (guards the awk)" 0 "sha256sum" cat "$FVLIB"
|
||||
check "checksum policy: extracted from the template (guards the awk)" 0 "sha256sum" cat "$FVTPL"
|
||||
check "checksum policy: the two copies are byte-identical" 0 "" diff "$FVLIB" "$FVTPL"
|
||||
rm -f "$FVLIB" "$FVTPL"
|
||||
|
||||
# ...and neither may drift back to warn-and-continue.
|
||||
check "forgejo-runner: install has no warn-and-continue checksum branch" 1 "" \
|
||||
grep -q "WITHOUT checksum verification" "$FR"
|
||||
check "ci-box: no warn-and-continue checksum branch either" 1 "" \
|
||||
grep -q "WITHOUT checksum verification" "$CIBOX"
|
||||
check "forgejo-runner: install routes through the shared checksum policy" 0 "fetch_and_verify_sha256" \
|
||||
grep -o "fetch_and_verify_sha256 \"\$URL\"" "$FR"
|
||||
|
||||
# --- --version must converge, not be swallowed (review !110) ----------------
|
||||
# forgejo-runner does NOT self-update, and a ci-box's template preinstalls the
|
||||
|
|
|
|||
Loading…
Reference in a new issue