CI's shellcheck sweep never lints .github/scripts/*.sh — including release-lib.sh, which decides what gets published #70

Closed
opened 2026-07-19 23:13:25 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-19 23:13:25 +00:00 (Migrated from github.com)

rig-side record of heavy-duty/box#116. Same defect, same cause — and here it is the changelog extraction that escapes linting.

The gap

.github/workflows/ci.yml's shellcheck step uses:

shopt -s globstar
files=(bin/* **/*.sh)
shellcheck -x "${files[@]}"

globstar makes ** descend into subdirectories, but globs do not match dot-prefixed names without dotglob. .github is dot-prefixed, so **/ never descends into it.

Measured on main, the tracked .sh files CI never lints:

.github/scripts/labels-reconcile.sh
.github/scripts/release-lib.sh

Why release-lib.sh makes this worth fixing here

release-lib.sh holds changelog_section — the extraction release.yml sources to build the published release body, and the same function test/release.sh's changelog_armed guard (#66/#67) calls to decide whether main is armed.

So the script that decides both what gets published and whether the changelog is safe is the one shellcheck never sees. It is also the file most likely to be edited next, since #66's fix landed in it.

Current state: latent, not broken

The gap is that nothing would catch a regression, not that anything is broken today. Worth confirming both files pass before fixing, so the change is a no-op on current code rather than a bug-fix in disguise.

Suggested fix

shopt -s globstar dotglob, then verify what else dotglob pulls into bin/* and **/*.sh rather than assuming it is only .github.

Better paired with an assertion that the globbed set covers git ls-files '*.sh', so the gap cannot reopen silently — the class-check shape heavy-duty/box#112 used for its EOF-guard sweep.

Note rig's CI line differs slightly from box's in which files it enumerates; fix rig's on its own terms rather than copying box's patch verbatim.

Siblings

  • heavy-duty/box#116 — misses changelog-armed.sh, release-notes.sh, labels-reconcile.sh
  • heavy-duty/cast — misses release-notes.sh, labels-reconcile.sh (filed separately)

Refs

Found during the release: 0.2.0 drill (#69), while replicating CI's exact sweep on a real host.

rig-side record of `heavy-duty/box#116`. Same defect, same cause — and here it is the changelog extraction that escapes linting. ## The gap `.github/workflows/ci.yml`'s shellcheck step uses: ```bash shopt -s globstar files=(bin/* **/*.sh) shellcheck -x "${files[@]}" ``` `globstar` makes `**` descend into subdirectories, but **globs do not match dot-prefixed names** without `dotglob`. `.github` is dot-prefixed, so `**/` never descends into it. Measured on `main`, the tracked `.sh` files CI never lints: ``` .github/scripts/labels-reconcile.sh .github/scripts/release-lib.sh ``` ## Why `release-lib.sh` makes this worth fixing here `release-lib.sh` holds **`changelog_section`** — the extraction `release.yml` sources to build the published release body, and the same function `test/release.sh`'s `changelog_armed` guard (#66/#67) calls to decide whether `main` is armed. So the script that decides both *what gets published* and *whether the changelog is safe* is the one shellcheck never sees. It is also the file most likely to be edited next, since #66's fix landed in it. ## Current state: latent, not broken The gap is that nothing would catch a regression, not that anything is broken today. Worth confirming both files pass before fixing, so the change is a no-op on current code rather than a bug-fix in disguise. ## Suggested fix `shopt -s globstar dotglob`, then verify what else `dotglob` pulls into `bin/*` and `**/*.sh` rather than assuming it is only `.github`. Better paired with an assertion that the globbed set covers `git ls-files '*.sh'`, so the gap cannot reopen silently — the class-check shape `heavy-duty/box#112` used for its EOF-guard sweep. Note rig's CI line differs slightly from box's in which files it enumerates; fix rig's on its own terms rather than copying box's patch verbatim. ## Siblings - `heavy-duty/box#116` — misses `changelog-armed.sh`, `release-notes.sh`, `labels-reconcile.sh` - `heavy-duty/cast` — misses `release-notes.sh`, `labels-reconcile.sh` (filed separately) ## Refs Found during the `release: 0.2.0` drill (#69), while replicating CI's exact sweep on a real host.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/rig#70
No description provided.