build(verify): make the local Linux relay a skippable fallback gate
The pre-push gate ran the self-hosted claw relay (ssh + Lima Debian) as a hard stage, so any time the host was unreachable the whole hook failed and the only way past it was a blanket --no-verify, which also discarded the local macOS Swift gate. The authoritative Linux gate is the GitHub-hosted workflow (ubuntu-latest + swift:6.2); the relay is a convenience fallback. check-linux.sh now separates connectivity and provisioning (Stage A, exit 77 to signal skip when the relay is unavailable) from the relayed build and test (Stage B, exit 1 on a genuine Linux failure). check-all.sh treats 77 as a non-fatal skip and still aborts on any other non-zero, so a runner outage no longer blocks a green push and never masks a real failure.
This commit is contained in:
parent
942a7ff2bc
commit
5a3bf6518c
@ -6,11 +6,24 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Exit code 77 from a gate means "skipped: runner/infrastructure unavailable"
|
||||
# (see scripts/check-linux.sh). A skip is non-fatal and must not block the
|
||||
# push; a real failure (any other non-zero) still aborts the whole gate.
|
||||
SKIP=77
|
||||
|
||||
run_gate() {
|
||||
name="$1"
|
||||
shift
|
||||
printf '\n==> %s\n' "$name"
|
||||
set +e
|
||||
"$@"
|
||||
status=$?
|
||||
set -e
|
||||
if [ "$status" -eq "$SKIP" ]; then
|
||||
printf ' SKIPPED (runner unavailable; authoritative gate runs on CI)\n'
|
||||
return 0
|
||||
fi
|
||||
return "$status"
|
||||
}
|
||||
|
||||
run_gate "style" bash scripts/check-style.sh
|
||||
|
||||
@ -1,7 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# The remote commands below are deliberately composed on the client: local
|
||||
# config ($REMOTE_DIR, $LIMA_INSTANCE, $REMOTE_BUILD) is expanded here and sent
|
||||
# to the host as a literal string. That client-side expansion is intended, so
|
||||
# the SC2029 notes it raises are silenced file-wide rather than per line.
|
||||
# shellcheck disable=SC2029
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Exit-code contract (consumed by check-all.sh run_gate):
|
||||
#
|
||||
# 0 - Linux gate ran and PASSED. Either this machine is Linux (the gate runs
|
||||
# natively), or the self-hosted relay was reachable and the relayed
|
||||
# Swift build/test succeeded.
|
||||
# 77 - Linux gate SKIPPED because the self-hosted relay is unavailable from
|
||||
# this machine: ssh/rsync missing locally, the host is unreachable, it
|
||||
# lacks limactl, the working dir cannot be created, the sync fails, or
|
||||
# the VM will not start. This is a runner-availability limitation, NOT a
|
||||
# code defect. The authoritative Linux gate is the GitHub-hosted
|
||||
# workflow (.github/workflows/linux.yml: ubuntu-latest + swift:6.2),
|
||||
# which runs on every push regardless of this relay.
|
||||
# 1 - Linux gate RAN on the relay but the Swift build/test FAILED. A real
|
||||
# Linux failure. It must be fixed, never skipped.
|
||||
#
|
||||
# The 77-vs-1 split is the whole point. An unreachable runner must not block a
|
||||
# green local push (skip), and it must never mask a real Linux failure (which
|
||||
# stays a hard 1). When in doubt during the build stage we fail hard, because
|
||||
# masking a real failure is the worse error.
|
||||
|
||||
SKIP=77
|
||||
|
||||
skip() {
|
||||
echo "linux: SKIP ($1)." >&2
|
||||
echo "linux: authoritative Linux gate is GitHub-hosted .github/workflows/linux.yml." >&2
|
||||
exit "$SKIP"
|
||||
}
|
||||
|
||||
run_linux_gate() {
|
||||
if [ -n "${SWIFTLY_HOME_DIR:-}" ] && [ -f "$SWIFTLY_HOME_DIR/env.sh" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
@ -14,6 +48,7 @@ run_linux_gate() {
|
||||
swift test -c release
|
||||
}
|
||||
|
||||
# Native Linux: this machine IS the runner. Hard gate, no relay, no skip path.
|
||||
if [ "$(uname -s)" = "Linux" ]; then
|
||||
run_linux_gate
|
||||
exit 0
|
||||
@ -25,21 +60,41 @@ REMOTE_PARENT="${PUREYAML_LINUX_REMOTE_PARENT:-/Volumes/ClawSSD/tmp}"
|
||||
REMOTE_DIR="$REMOTE_PARENT/pureyaml-linux-check"
|
||||
REMOTE_SWIFTLY_HOME="${PUREYAML_LINUX_SWIFTLY_HOME:-/Volumes/ClawSSD/swiftly-linux/home}"
|
||||
REMOTE_SWIFTLY_BIN="${PUREYAML_LINUX_SWIFTLY_BIN:-/Volumes/ClawSSD/swiftly-linux/bin}"
|
||||
SSH_CONNECT_TIMEOUT="${PUREYAML_LINUX_SSH_TIMEOUT:-10}"
|
||||
|
||||
if ! command -v ssh >/dev/null 2>&1; then
|
||||
echo "linux: ssh is required outside Linux" >&2
|
||||
exit 2
|
||||
# --- Stage A: connectivity and provisioning (soft; any failure => skip) ------
|
||||
# Everything here is relay infrastructure. If it is not available, the local
|
||||
# Linux check cannot run, but that is not a code failure: skip with 77.
|
||||
|
||||
command -v ssh >/dev/null 2>&1 || skip "ssh not available on this machine"
|
||||
command -v rsync >/dev/null 2>&1 || skip "rsync not available on this machine"
|
||||
|
||||
if ! ssh -o BatchMode=yes -o ConnectTimeout="$SSH_CONNECT_TIMEOUT" "$HOST" true >/dev/null 2>&1; then
|
||||
skip "host '$HOST' is unreachable over ssh"
|
||||
fi
|
||||
|
||||
if ! command -v rsync >/dev/null 2>&1; then
|
||||
echo "linux: rsync is required outside Linux" >&2
|
||||
exit 2
|
||||
if ! ssh "$HOST" "command -v limactl >/dev/null && mkdir -p '$REMOTE_DIR'" >/dev/null 2>&1; then
|
||||
skip "host '$HOST' lacks limactl or cannot create '$REMOTE_DIR'"
|
||||
fi
|
||||
|
||||
ssh "$HOST" "command -v limactl >/dev/null && mkdir -p '$REMOTE_DIR'"
|
||||
rsync -a --delete \
|
||||
--exclude '.build' \
|
||||
--exclude '.git' \
|
||||
./ "$HOST:$REMOTE_DIR/"
|
||||
if ! rsync -a --delete --exclude '.build' --exclude '.git' ./ "$HOST:$REMOTE_DIR/" >/dev/null 2>&1; then
|
||||
skip "rsync to '$HOST:$REMOTE_DIR' failed"
|
||||
fi
|
||||
|
||||
ssh "$HOST" "limactl start '$LIMA_INSTANCE' >/tmp/pureyaml-lima-start.log 2>&1 || true; limactl shell '$LIMA_INSTANCE' -- bash -lc 'export SWIFTLY_HOME_DIR=\"$REMOTE_SWIFTLY_HOME\" SWIFTLY_BIN_DIR=\"$REMOTE_SWIFTLY_BIN\"; [ -f \"\$SWIFTLY_HOME_DIR/env.sh\" ] && . \"\$SWIFTLY_HOME_DIR/env.sh\"; cd \"$REMOTE_DIR\" && swift --version && swift build && swift test && swift build -c release && swift test -c release'"
|
||||
if ! ssh "$HOST" "limactl start '$LIMA_INSTANCE' >/tmp/pureyaml-lima-start.log 2>&1"; then
|
||||
skip "lima instance '$LIMA_INSTANCE' would not start on '$HOST'"
|
||||
fi
|
||||
|
||||
# --- Stage B: the real Linux build/test (hard; failure => exit 1) ------------
|
||||
# The relay is up and the tree is synced. From here a non-zero exit is a real
|
||||
# Linux build/test failure and must propagate. (A connection drop mid-build
|
||||
# also lands here; failing hard is the conservative, correct choice.)
|
||||
|
||||
REMOTE_BUILD="export SWIFTLY_HOME_DIR=\"$REMOTE_SWIFTLY_HOME\" SWIFTLY_BIN_DIR=\"$REMOTE_SWIFTLY_BIN\"; [ -f \"\$SWIFTLY_HOME_DIR/env.sh\" ] && . \"\$SWIFTLY_HOME_DIR/env.sh\"; cd \"$REMOTE_DIR\" && swift --version && swift build && swift test && swift build -c release && swift test -c release"
|
||||
|
||||
if ssh "$HOST" "limactl shell '$LIMA_INSTANCE' -- bash -lc '$REMOTE_BUILD'"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "linux: relayed Swift build/test FAILED on '$HOST'. Real failure, not skipped." >&2
|
||||
exit 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user