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;
|
- checks out the module with `persist-credentials: false` and pinned actions;
|
||||||
- runs the module's own unit tests, typecheck, and lint;
|
- 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
|
- sweeps stale CI stacks from the runner, then runs the harness, once per pinned platform version,
|
||||||
**by digest**. The module directory is mounted read-only, and the runner's Docker is used exactly
|
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.
|
as the platform's smoke uses it.
|
||||||
|
|
||||||
It references no secret, needs no registry credential (the harness image is public within the
|
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
|
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.
|
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
|
### 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
|
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