Skip to content

feat(declare-bashscript): one trap handler, set with Set-Traps; bash 5.3; tests run by make check - #288

Merged
David-Noble-at-work merged 6 commits into
developfrom
chore/268-declare-bashscript-traps
Oct 9, 2026
Merged

David-Noble-at-work merged 6 commits into
developfrom
chore/268-declare-bashscript-traps

Conversation

@David-Noble-at-work

@David-Noble-at-work David-Noble-at-work commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • One handler in the helper. Declare-BashScript defines on_error_or_interrupt and Set-Traps. A script
    calls Set-Traps cleanup once, after its cleanup function and before its arguments are parsed. A failure that ends
    the script is reported once, in error's form, with its line and command; a failure the script tolerates is not;
    HUP, INT and TERM end it with 129, 130 and 143; and the cleanup runs on every way out. The man page gains a TRAPS
    section.
  • The copied handler's defects are gone. The handler five personal scripts copy let a signal run on, kept a
    failure inside a function silent, and under errtrace reported exits that never happened.
  • bash 5.3 or later. The helper refuses an older bash with 78 before anything else runs, and turns on errtrace
    and inherit_errexit.
  • Tests and a Makefile. tests/Test-DeclareBashScript runs 14 cases against the helper. A root Makefile gives
    each gate a target, with its reasons beside it, and make check runs them all and then the tests. CI calls
    make check on ubuntu-26.04, whose bash meets the floor.
  • The base's own script. scripts/setup-ground-zero.sh sources the helper and cleans up through Set-Traps.

Test plan

  • make check on Danoble-MBP-A: frontmatter, spelling, shell lint, PowerShell, Starlark, and the 14 tests
  • The deployed test: the branch checked out in the base layer's clone and deployed; the tests passed against the
    deployed helper, and the 18 consumers deployed there whose code before their option loop runs nothing exited 0
    from --help
  • No command substitution in the 72 scripts that source the helper relies on running past a failure, which
    inherit_errexit would stop
  • scripts/setup-ground-zero.sh: --help, its usage errors, and its dry run to the prerequisite check; its live
    path, which provisions Azure, was not run
  • CI on ubuntu-26.04

Plan: docs/plans/chore/268-declare-bashscript-traps.md. Lane 60 of NobleFactor/devlore-cli#916. Personal's scripts
that trap follow in David-Noble-at-work/personal#266 (lane 61), and devlore-cli's in NobleFactor/devlore-cli#1037
(lane 62).

Resolves #268

Written with AI assistance.

Signed-off-by: David Noble [email protected]
Assisted-by: Claude Code

Time

Marker UTC Elapsed
opened (first commit) 2026-10-09T00:14:30Z —
submitted (PR opened) 2026-10-09T05:08:36Z 4.9 h after opened
merged 2026-10-09T05:09:34Z 0 h after submitted; 4.9 h in all

Computed by the algorithm of noblefactor-ops#188 at merge.

…efects, and eight rulings (#268)

The plan for lane 60 of NobleFactor/devlore-cli#916, ahead of lane 49's startup hook. The owner, 2026-10-08: "We will
commit your outstanding work and then take the time to update Declare-BashScript with trap logic. We will accept the
trap logic when all bash scripts in base, team, and main that have trap logic using the Declarre-BashScript trap
logic."

It records the handler five personal scripts copy, in four variants, and its three defects, measured with bash 5.3.15:
a signal does not stop the script, a failure inside a function is silent, and with errtrace it reports exits that
never happen. The owner ruled, one question at a time: a script calls Set-Traps, naming its cleanup; a signal ends it
with 128 plus its number, so the cleanup runs; HUP, INT and TERM are trapped; inherit_errexit is on; the helper
refuses bash older than 5.3, which all three machines meet; the tests are committed and run from a new root Makefile,
whose make check CI calls; and Set-Traps follows the cleanup it names, before the arguments are parsed. Approved: "The
plan is approved. Let's go".
….3, errtrace and inherit_errexit (#268)

Phase 2 of the plan. The helper refuses bash older than 5.3 with EX_CONFIG before anything else runs, turns on
errtrace and inherit_errexit, and defines on_error_or_interrupt and Set-Traps. A script calls Set-Traps once, naming
its cleanup. A failure that ends it is reported once, in error's form, with its line and command, and exits with its
status; a failure it tolerates is not reported; HUP, INT and TERM end it with 129, 130 and 143; and the cleanup runs on
every way out. The man page gains a TRAPS section and states the bash requirement.

Probed on Danoble-MBP-A with bash 5.3.15 against this helper, every case in the plan's table, and macOS's /bin/bash
3.2.57 is refused with 78. Two behaviors of bash itself are written into the man page: a failing pipeline is reported
with its last command's text, and a function called as an if test runs past its own failure. The helper's getopt call,
131 columns, is wrapped at 120. No script calls Set-Traps yet: phase 4 here, then lanes 61 and 62.
… on ubuntu-26.04 (#268)

Phase 3 of the plan. tests/Test-DeclareBashScript runs 14 programs under the helper in a child bash and checks how each
ends: a failure at top level, inside a function, inside a command substitution, before the last command of one, inside
a subshell and in a pipeline is reported once with its status; a failure under set +o errexit, in an if test and
before || is not; SIGHUP, SIGINT and SIGTERM end the script with 129, 130 and 143 and run its cleanup; an error call
and a normal end run the cleanup too; and a bash older than 5.3, where one is at /bin/bash, is refused with 78. No copy
of the old handler is kept, as ruled.

A root Makefile, modeled on devlore-cli's, gives each gate CI runs a target, with the gate's reasons moved beside it
from the workflow, and make check runs them all and then the tests. CI moves to ubuntu-26.04, whose bash meets the
helper's floor where ubuntu-24.04's 5.2.21 does not, installs the same pinned tools, codespell among them, and calls
make check. make check passes on Danoble-MBP-A in 7.8 seconds; CI's own run comes with the pull request.
…d cleans up through Set-Traps (#268)

Phase 4 of the plan. scripts/setup-ground-zero.sh, the one bash file in this repository that traps, sources the
helper under the guard and the directive, parses its options with the helper's loop, and narrates with note, success,
error 0 for its warnings and error with a sysexits status for its failures. Its own colors, info, warn, error and
phase are gone, and its help text is the synopsis usage prints. The file it captures the Azure setup's output in is
removed by a cleanup that Set-Traps runs on every way out, where a trap set mid-script did before. Its Azure and GitHub
commands are unchanged.

Run on Danoble-MBP-A: --help exits 0; an unknown option, a missing --name and a stray argument exit 64; the dry run
read Azure and GitHub and stopped at the prerequisites with 69. The live path, which provisions Azure and configures
GitHub, was not run. Two old defects are fixed: a missing CLI's error exited before the line meant to record it, and
the secret count printed two lines when gh failed.
… needed, all passed (#268)

The deployed test ran as ruled for these tests, the branch checked out in the base layer's clone: writ deploy
--allow-dirty deployed 270 links (personal's clone held the inventory lists Upgrade-Mac writes), the deployed helper
carried Set-Traps, the 14 tests passed against it, and the 18 consumers deployed on Danoble-MBP-A whose code before
their option loop runs nothing exited 0 from --help. The clone went back to develop and was deployed again.

Every command substitution holding more than one command in the 72 scripts that source the helper was read for one
that relies on running past a failure, which inherit_errexit would stop: none. No launchd job or cron entry runs these
scripts here, where launchd's default PATH would hand them /bin/bash 3.2. The man page's lint, from phase 2, is ticked.
CI's own run comes with the pull request.
…itself (#268)

The plan stays active until they do, as agent-rules rule 12 asks a plan to say of a box that cannot close inside its
own pull request.
@David-Noble-at-work David-Noble-at-work self-assigned this Oct 9, 2026
@David-Noble-at-work
David-Noble-at-work merged commit 5f793ed into develop Oct 9, 2026
1 check passed
@David-Noble-at-work
David-Noble-at-work deleted the chore/268-declare-bashscript-traps branch October 9, 2026 05:09
David-Noble-at-work added a commit that referenced this pull request Oct 9, 2026
…th test machines (#289)

Phase 5 of lanes 63 and 65 of NobleFactor/devlore-cli#916. Plan 268's CI box and closure box are ticked from #288's
record: quality-gate passed in 35 s, it merged as 5f793ed, and git close-branch removed its worktree. Its last box
records lane 61, merged as David-Noble-at-work/personal#267, and stays open for lane 62, so plan 268 stays active.

And phase 6's first box: getopt --test exits 4 on both test machines, so the new check stops neither.
danoble-ud24-1.local, Ubuntu 26.04.1 with bash 5.3.9, has util-linux 2.41.3; danoble-wd11-3, Git for Windows' bash
5.3.15, has util-linux 2.40.2.
David-Noble-at-work added a commit that referenced this pull request Oct 10, 2026
…mand, and every function documented (#293)

## Summary

- **GNU getopt, in or out (#290).** The helper parses every consumer's options with GNU `getopt --long`. macOS's own `/usr/bin/getopt` misparses that call and exits 0, so a script ran with its options dropped and the rest taken as arguments. Beside the bash 5.3 check, the helper now requires `getopt --test` to exit 4, as only GNU's does; otherwise it stops with 78 (`EX_CONFIG`) and says where to get it. It searches for no other copy.
- **`require_command` (#290).** `require_command <name>...` looks each name up with `hash` and stops with 69 (`EX_UNAVAILABLE`), naming every tool that is missing. Which scripts call it is for the scripting standards (#266).
- **Shellcheck's notes (#289).** `Set-Traps`'s cleanup is optional, and a directive at its definition says so, so shellcheck at every severity no longer flags personal's five scripts that call it bare. The helper's test marks the two programs it hands a child bash in single quotes.
- **Every function documented.** All 12 of the helper's functions and the test's `run_case` take the Go guide's § 4 form: a one-line summary that begins with the function's name, paragraphs, then Parameters and Returns, as ruled 2026-10-09 on #267.
- **The man page** names the GNU getopt requirement and documents `require_command`. **Plan 268's** CI and closure boxes are ticked from #288's record.

## Test plan

- [x] `make check` on Danoble-MBP-A: frontmatter, spelling, shell lint, PowerShell, Starlark, and the test's 17 cases, three of them new
- [x] Shellcheck at every severity against this branch's helper: clean on the helper, its test, and personal's five scripts that call `Set-Traps` bare
- [x] `getopt --test` exits 4 on danoble-ud24-1 (util-linux 2.41.3) and in Git for Windows' bash on danoble-wd11-3 (util-linux 2.40.2), so the check stops neither
- [x] The deployed check: the branch checked out in the base layer's clone and deployed; the 17 cases passed against the deployed helper; with macOS's `/usr/bin/getopt` first on PATH it stopped with 78; and the 18 consumers deployed there whose code before their option loop runs nothing exited 0 from `--help`
- [ ] CI on `ubuntu-26.04`

Plan: `docs/plans/chore/289-set-traps-optional-cleanup.md`. Lanes 63 and 65 of NobleFactor/devlore-cli#916. Next on the schedule: `install.sh` and devlore-cli's two tools, NobleFactor/devlore-cli#1037 and #1038 (lanes 62 and 64), and `Set-Environment`'s defects, #291 (lane 66).

Resolves #289
Resolves #290

Written with AI assistance.

Signed-off-by: David Noble <[email protected]>
Assisted-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

on_error_or_interrupt moves into Declare-BashScript: one handler, its defects fixed, each script stating its traps and cleanup

1 participant