100 lines
5.1 KiB
YAML
100 lines
5.1 KiB
YAML
name: ci
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
# changelog-monotonic and changelog-assembled compare HEAD against
|
|
# the merge base; a
|
|
# checkout that cannot resolve it is a hard failure in CI, not
|
|
# a skip (a guard that can quietly stop guarding is the failure
|
|
# shape these checks exist to refuse).
|
|
fetch-depth: 0
|
|
- name: shellcheck
|
|
# -x follows the `source=SCRIPTDIR/...` directives into commands/lib/.
|
|
# globstar so a script in a new subdirectory is linted without anyone
|
|
# remembering to edit this list; bin/* covers the extensionless entrypoints.
|
|
# dotglob because globs skip dot-prefixed names: without it `**/` never
|
|
# descends into `.github/`, so `.github/scripts/*.sh` — release-lib.sh
|
|
# among them — was swept up by nothing (#70). It also makes `**`
|
|
# descend into `.git/`, which holds no tracked `.sh` on a checkout.
|
|
# The file list is printed so under-coverage shows up in the log, and
|
|
# the comm below turns under-coverage into a failure rather than a
|
|
# thing someone has to notice: every tracked `.sh` must be in the set.
|
|
run: |
|
|
shopt -s globstar dotglob
|
|
files=(bin/* **/*.sh)
|
|
printf 'shellcheck: %s\n' "${files[@]}"
|
|
uncovered=$(comm -23 <(git ls-files '*.sh' | sort) <(printf '%s\n' "${files[@]}" | sort))
|
|
if [ -n "$uncovered" ]; then
|
|
printf 'tracked .sh files the glob does not lint:\n%s\n' "$uncovered" >&2
|
|
exit 1
|
|
fi
|
|
shellcheck -x "${files[@]}"
|
|
- name: cli tests
|
|
run: bash test/cli.sh
|
|
- name: release tests — rig's own surfaces
|
|
run: bash test/release.sh
|
|
# The drill harness's honesty: refusals, the skip/pass/fail classifier,
|
|
# the idempotence capture-and-diff, the record emitter. Network-free and
|
|
# root-free — the live four-leg run is a release's drill, not CI's.
|
|
- name: drill harness tests — the instrument itself
|
|
run: bash test/drill.sh
|
|
# The release guards, doctrine in heavy-duty/ceremony's README (#13's
|
|
# conversion). Each one's war story — why it exists, what it refuses —
|
|
# lives with its implementation upstream; the six pins below and the
|
|
# two workflow callers must always name the same ceremony tag.
|
|
#
|
|
# changelog-armed: the version-keyed arming rule (rig#66; the
|
|
# unconditional form rig#44 reverted — this is its correct return).
|
|
- uses: heavy-duty/ceremony/actions/changelog-armed@0.3.0
|
|
# changelog-monotonic: no shipped heading deleted or duplicated
|
|
# (#98, box#122). Strict by default: an unresolvable base ref is red,
|
|
# never a quiet skip — hence the fetch-depth: 0 above.
|
|
- uses: heavy-duty/ceremony/actions/changelog-monotonic@0.3.0
|
|
# changelog-assembled: a release's stamped section must exactly match
|
|
# the fragments it consumed. Vacuous on non-release PRs.
|
|
- uses: heavy-duty/ceremony/actions/changelog-assembled@0.3.0
|
|
# drill-recorded: a release version carries drills/<version>.md
|
|
# (rig's drill meaning: drills/README.md). Vacuous on -dev trees.
|
|
- uses: heavy-duty/ceremony/actions/drill-recorded@0.3.0
|
|
# runner-isolated: PR-triggered workflows never execute unreviewed
|
|
# branch code on a self-hosted runner.
|
|
- uses: heavy-duty/ceremony/actions/runner-isolated@0.3.0
|
|
# docs-sync: the .ceremony/ doctrine mirror is byte-identical to the
|
|
# pin read from release.yml (ceremony#19) — a hand edit or a
|
|
# half-done pin bump goes red here.
|
|
- uses: heavy-duty/ceremony/actions/docs-sync@0.3.0
|
|
|
|
# The install LIFECYCLE against a tree install.sh itself produced — the four
|
|
# beats box and cast already run in CI (#106): install from this checkout,
|
|
# assert what landed, a converging re-run proven by an EMPTY DIFF (never an
|
|
# exit code), uninstall --all ending in the absence assert (`! -e` AND
|
|
# `! -L` — only the second sees a dangling symlink). Separate from `check`
|
|
# for the same reason db-integration is: fast feedback first. The runner's
|
|
# real $HOME is the point — no throwaway roots here; the suite refuses to
|
|
# run where a rig is already installed, so it cannot eat a real install.
|
|
install:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: the install lifecycle — four beats against a real tree
|
|
run: bash test/install-lifecycle.sh
|
|
|
|
# Kept SEPARATE from `check` on purpose: this job pulls a Postgres image and
|
|
# stands up throwaway containers, and a slow image pull must never delay the
|
|
# fast shellcheck + cli.sh feedback above. ubuntu-latest ships Docker running
|
|
# and passwordless sudo, so test/db-integration.sh EXECUTES here (it only
|
|
# skips where Docker is absent). It is the automated proof that dump/restore
|
|
# actually round-trips, not just that the args parse.
|
|
db-integration:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: db dump/restore round-trip
|
|
run: bash test/db-integration.sh
|