docs: define doors-unchanged drill records
This commit is contained in:
parent
ba55d1d552
commit
75d85df20c
3 changed files with 61 additions and 6 deletions
5
changelog.d/237.md
Normal file
5
changelog.d/237.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
### Changed
|
||||
|
||||
- Define the doors-unchanged drill record and an executable release-path list,
|
||||
so a release may reuse live evidence only when its door bytes are unchanged
|
||||
since the last rehearsed tag. (#237)
|
||||
|
|
@ -66,6 +66,46 @@ record is the only thing that survives the drill, and 0.2.0's record shipped
|
|||
its first draft asserting a cleanup that had not happened (#135) — false
|
||||
evidence in the one file whose job is to be evidence.
|
||||
|
||||
A record has one of three shapes. A **rehearsal** records the disposable-repo
|
||||
run above. **Doors unchanged** records the mechanically checked claim below
|
||||
when a new rehearsal would execute the same bytes as the last one. **WAIVED**
|
||||
records a maintainer's judgement under the standing paragraph below. If the
|
||||
doors-unchanged conditions do not all hold, the release owes a rehearsal or a
|
||||
waiver; the narrower shape is never a substitute for either.
|
||||
|
||||
## Doors unchanged
|
||||
|
||||
The builder may assert that no disposable-repo rehearsal is owed only when
|
||||
all three conditions below hold at the candidate head. The release PR's panel
|
||||
verifies the claim like any other evidence, and if any reviewer rules a full
|
||||
drill owed, that verdict wins.
|
||||
|
||||
1. `git diff <last-rehearsed-tag>..HEAD -- <release-path>` contains no change
|
||||
except the `CEREMONY_SELF_REF` pin line in
|
||||
`.github/workflows/release.yml`.
|
||||
2. The release path is exactly the output of
|
||||
`.github/scripts/release-path.sh`: `.github/workflows/release.yml`, `bin/`,
|
||||
`lib/version.sh`, `lib/decide.sh`, `lib/facts.sh`, and
|
||||
`lib/changelog.sh`. The script is the record author's copy-paste source;
|
||||
its contract test keeps this inline list and the workflow's direct and
|
||||
transitive dependencies in agreement.
|
||||
3. The last rehearsed tag's own record is a full rehearsal, its release is
|
||||
published, and `main` was re-armed to `-dev` after it.
|
||||
|
||||
The baseline is the last **rehearsed** tag, never merely the previous tag. A
|
||||
previous-tag baseline could chain one doors-unchanged assertion from another
|
||||
while the doors drift a small diff at a time; the last-rehearsed anchor makes
|
||||
any accumulated release-path change force a new rehearsal.
|
||||
|
||||
The record carries all three measurements as observed at its candidate head,
|
||||
never copied from an earlier record. `drills/0.4.1.md` and
|
||||
`drills/0.5.0.md` are the worked examples; the latter's amendment from a
|
||||
predicted empty `lib/` diff to the observed `lib/ruling.sh` delta is why each
|
||||
candidate is measured afresh (#233). Re-running its stricter baseline now is
|
||||
also the path-enumeration proof: `git diff 0.4.0 0.5.0 -- <release-path>` is
|
||||
only the `CEREMONY_SELF_REF` pin, while adding `lib/ruling.sh` makes the diff
|
||||
non-empty even though neither release door reads that file (#217, #237).
|
||||
|
||||
`actions/drill-recorded` refuses any bare-version tree whose record is
|
||||
missing or blank. A waived drill is still a record: the file says WAIVED and
|
||||
why — a maintainer's call, visible and reviewable in the release PR's diff,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ trap 'rm -rf "$TMP"' EXIT
|
|||
# derive_path <tree> — print the workflow, bin/ when a bin command sources a
|
||||
# door library, and the workflow's direct + transitive lib dependencies.
|
||||
derive_path() {
|
||||
local tree="$1" workflow="$tree/.github/workflows/release.yml"
|
||||
local tree="$1" workflow
|
||||
local pending seen=" " lib file refs ref bin_uses_lib=no
|
||||
workflow="$tree/.github/workflows/release.yml"
|
||||
|
||||
printf '%s\n' .github/workflows/release.yml
|
||||
pending="$(sed -n 's|.*\(lib/[[:alnum:]_.-]*\.sh\).*|\1|p' "$workflow" | sort -u)"
|
||||
|
|
@ -75,10 +76,12 @@ fixture() {
|
|||
tree="$TMP/$name"
|
||||
mkdir -p "$tree/.github/scripts" "$tree/.github/workflows" "$tree/lib" "$tree/bin"
|
||||
cp "$PATH_SCRIPT" "$tree/.github/scripts/release-path.sh"
|
||||
printf '#!/usr/bin/env bash\n. "$ROOT/lib/changelog.sh"\n' >"$tree/bin/assemble"
|
||||
printf '#!/usr/bin/env bash\n. "%s"\n' \
|
||||
"\$ROOT/lib/changelog.sh" >"$tree/bin/assemble"
|
||||
printf '#!/usr/bin/env bash\n' >"$tree/lib/changelog.sh"
|
||||
printf '#!/usr/bin/env bash\n' >"$tree/lib/decide.sh"
|
||||
printf '#!/usr/bin/env bash\n. "$ROOT/lib/version.sh"\n' >"$tree/lib/facts.sh"
|
||||
printf '#!/usr/bin/env bash\n. "%s"\n' \
|
||||
"\$ROOT/lib/version.sh" >"$tree/lib/facts.sh"
|
||||
printf '#!/usr/bin/env bash\n' >"$tree/lib/version.sh"
|
||||
printf '%s\n' "$tree"
|
||||
}
|
||||
|
|
@ -92,7 +95,10 @@ check "real workflow and transitive dependencies match the manifest" 0 "" \
|
|||
|
||||
# A door growing a dependency must name the missing path (#237 D7).
|
||||
tree="$(fixture missing)"
|
||||
printf 'run: bash "$CEREMONY_DIR/lib/facts.sh"\nrun: bash "$CEREMONY_DIR/lib/decide.sh"\nrun: . "$CEREMONY_DIR/lib/changelog.sh"\nrun: . "$CEREMONY_DIR/lib/version.sh"\nrun: . "$CEREMONY_DIR/lib/ruling.sh"\n' \
|
||||
printf 'run: bash "%s"\nrun: bash "%s"\nrun: . "%s"\nrun: . "%s"\nrun: . "%s"\n' \
|
||||
"\$CEREMONY_DIR/lib/facts.sh" "\$CEREMONY_DIR/lib/decide.sh" \
|
||||
"\$CEREMONY_DIR/lib/changelog.sh" "\$CEREMONY_DIR/lib/version.sh" \
|
||||
"\$CEREMONY_DIR/lib/ruling.sh" \
|
||||
>"$tree/.github/workflows/release.yml"
|
||||
printf '#!/usr/bin/env bash\n' >"$tree/lib/ruling.sh"
|
||||
check "a new workflow library fails with its missing path" 1 \
|
||||
|
|
@ -100,7 +106,9 @@ check "a new workflow library fails with its missing path" 1 \
|
|||
|
||||
# A manifest may not rot into a safe-looking superset.
|
||||
tree="$(fixture extra)"
|
||||
printf 'run: bash "$CEREMONY_DIR/lib/facts.sh"\nrun: bash "$CEREMONY_DIR/lib/decide.sh"\nrun: . "$CEREMONY_DIR/lib/changelog.sh"\n' \
|
||||
printf 'run: bash "%s"\nrun: bash "%s"\nrun: . "%s"\n' \
|
||||
"\$CEREMONY_DIR/lib/facts.sh" "\$CEREMONY_DIR/lib/decide.sh" \
|
||||
"\$CEREMONY_DIR/lib/changelog.sh" \
|
||||
>"$tree/.github/workflows/release.yml"
|
||||
sed -i 's| lib/changelog.sh$| lib/changelog.sh \\|' \
|
||||
"$tree/.github/scripts/release-path.sh"
|
||||
|
|
@ -111,7 +119,9 @@ check "a path no door reads fails as stale" 1 "stale path: lib/ruling.sh" \
|
|||
|
||||
# Transitive sourcing is part of the derivation, not decoration.
|
||||
tree="$(fixture transitive)"
|
||||
printf 'run: bash "$CEREMONY_DIR/lib/facts.sh"\nrun: bash "$CEREMONY_DIR/lib/decide.sh"\nrun: . "$CEREMONY_DIR/lib/changelog.sh"\n' \
|
||||
printf 'run: bash "%s"\nrun: bash "%s"\nrun: . "%s"\n' \
|
||||
"\$CEREMONY_DIR/lib/facts.sh" "\$CEREMONY_DIR/lib/decide.sh" \
|
||||
"\$CEREMONY_DIR/lib/changelog.sh" \
|
||||
>"$tree/.github/workflows/release.yml"
|
||||
: >"$tree/lib/facts.sh"
|
||||
check "removing facts' version source fails as a stale path" 1 \
|
||||
|
|
|
|||
Loading…
Reference in a new issue