docs: ADR 0047, nothing the harness starts outlives its job
CI / verify (pull_request) Successful in 58s
CI / infrastructure-smoke (pull_request) Successful in 21s
CI / migration-smoke (pull_request) Successful in 1m51s
CI / image-build (pull_request) Successful in 19s
CI / deploy-smoke (same-origin) (pull_request) Successful in 43s
CI / deploy-smoke (split) (pull_request) Successful in 57s
CI / verify (pull_request) Successful in 58s
CI / infrastructure-smoke (pull_request) Successful in 21s
CI / migration-smoke (pull_request) Successful in 1m51s
CI / image-build (pull_request) Successful in 19s
CI / deploy-smoke (same-origin) (pull_request) Successful in 43s
CI / deploy-smoke (split) (pull_request) Successful in 57s
A job the runner kills never runs its own cleanup trap, and the platform's CI leaked a whole migration stack that way. The harness follows the platform's three-layer rule: - everything it starts is named and labeled as a CI stack; - it cleans up in a trap; - the template workflow sweeps stale CI stacks before running it, and removes its own in a final if: always() step. The sweep ships in the harness image. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3827841205
commit
3a2f5d68f6
@@ -154,8 +154,9 @@ it.
|
||||
|
||||
- checks out the module with `persist-credentials: false` and pinned actions;
|
||||
- runs the module's own unit tests, typecheck, and lint;
|
||||
- runs the harness, once per pinned platform version, with one `docker run` of the harness image
|
||||
**by digest**. The module directory is mounted read-only, and the runner's Docker is used exactly
|
||||
- sweeps stale CI stacks from the runner, then runs the harness, once per pinned platform version,
|
||||
with one `docker run` of the harness image **by digest**, and finally, always, removes this job's
|
||||
own stacks. The module directory is mounted read-only, and the runner's Docker is used exactly
|
||||
as the platform's smoke uses it.
|
||||
|
||||
It references no secret, needs no registry credential (the harness image is public within the
|
||||
@@ -176,6 +177,22 @@ An image digest is the one reference that is equally immutable, equally reviewab
|
||||
unchanged on Gitea 1.24, Gitea 1.26, and GitHub Actions. A composite action can be added later as a
|
||||
convenience over the same image, without changing what a module pins.
|
||||
|
||||
### Nothing the harness starts outlives the job that started it
|
||||
|
||||
The harness starts Docker stacks on a shared runner, and a runner can kill a job outright: a
|
||||
cancelled job, or the runner's own time limit, since Gitea 1.24 ignores `timeout-minutes`. A script's
|
||||
own cleanup trap does not run then. The platform's CI leaked a whole migration stack that way, and it
|
||||
ran until someone removed it by hand. So the harness follows the platform's rule
|
||||
(`scripts/ci-sweep.sh`, `docs/development/security.md`):
|
||||
|
||||
- everything it starts is named and labeled as a CI stack of its run, attempt, and job key;
|
||||
- it removes its own stacks in a trap;
|
||||
- the template workflow runs the harness's **stale sweep** before the harness starts, and its
|
||||
**job sweep** in a final `if: always()` step, so a killed run's stacks are removed by that run's
|
||||
last step, or failing that by the next job on the runner.
|
||||
|
||||
The sweep ships inside the harness image, so a module never copies it.
|
||||
|
||||
### Publishing follows the instance's release pattern
|
||||
|
||||
The harness image is pushed only by a `publish` job that runs on `v*` tags, after the platform's CI
|
||||
|
||||
Reference in New Issue
Block a user