Skip to content

chore(deps): update bashunit to 0.45.0, pin CI actions, add --jobs - #64

Merged
Chemaclass merged 3 commits into
mainfrom
chore/update-deps-and-optimize
Aug 9, 2026
Merged

Chemaclass merged 3 commits into
mainfrom
chore/update-deps-and-optimize

Conversation

@Chemaclass

Copy link
Copy Markdown
Owner

🔗 Ticket

🤔 Background

bashunit had drifted 28 minor versions behind (0.17.0), and CI pulled two
actions from floating refs (action-shellcheck@master,
action-editorconfig-checker@main), so runs were not reproducible.

Separately, BASHDEP_JOBS — the only performance knob bashdep exposes —
was reachable only as an environment variable and was missing from
--help, making it effectively undiscoverable.

💡 Goal

Get dependencies current, make CI reproducible, and close the discoverability
gap on concurrency — without regressing runtime behavior.

🔖 Changes

Dependencies

  • bashunit 0.17.0 → 0.45.0. Suite runtime 26.8s → 2.5s (~11x).
  • Actions bumped: checkout@v7, cache@v6, paths-filter@v4,
    configure-pages@v6, upload-pages-artifact@v5, deploy-pages@v5.
  • Floating refs pinned: action-shellcheck@2.0.0,
    action-editorconfig-checker@v2.2.0.
  • .bashunit/ (new run-state dir) git-ignored; example/demo.sh URL refreshed.

Bug the upgrade exposed

bashunit ≥0.40 moved its doubles under bashunit::mock and changed the
multi-argument form to append "$@" to the mock body — so a body that reads
positional arguments (touch "$3") can no longer be expressed. This suite
uses that shape in 62 of its 93 mocks.

The failure was silent and dangerous: mock resolved to command not found,
the mocked tests fell through to real network downloads, and the run
overwrote lib/bashunit itself mid-suite.

tests/bootstrap.sh now owns mock/unmock with the semantics the suite was
written against. Each bashunit test runs in its own subshell, so the helpers
need no mock registry and depend on no bashunit internals.

DX

  • --jobs=N and bashdep::setup jobs=N, listed in --help and offered by the
    bash/zsh completion scripts.
  • Validation deliberately stays in one place: like the env var, a non-integer
    warns and falls back to 4 when install runs, so all three entry points
    behave identically.
  • bashdep::_sha256 caches the shasum/sha256sum probe in
    BASHDEP_SHA_TOOL, mirroring how BASHDEP_DOWNLOADER already pins
    curl/wget for a whole run.

🖼️ Screenshots

N/A — CLI change. --help gains one line:

  --jobs=N              Concurrent downloads (default: 4, 1 = sequential)

⚠️ On "optimize for perf" — two claims measured and withdrawn

1. Lockfile readers rewritten to pure bash, then reverted.
Replacing the awk fork in _lock_get/_lock_names with builtin string
matching removes a fork per dependency — but bash re-scans the whole lockfile
on every lookup, so it goes quadratic:

deps before after
25 0.10s 0.06s
100 0.38s 0.61s
200 0.76s 3.32s

Crossover ~50 entries. Winning ~50ms on small projects in exchange for a silent
cliff on large ones is a bad trade. Reverted, with a comment in
_lock_get so nobody retries it. Final state is at parity (200 deps: 0.83s vs
0.86s).

2. _sha256 "drops an awk fork" — it doesn't.
The inner $(...) just trades one fork for another. Measured identical (150
digests: 1.51s before and after). Kept for the tool-caching consistency, and
labeled in the CHANGELOG as a consistency change rather than a speedup.

Also dropped a BASHDEP_JOBS_OUT global I had added — it saved one fork per
install and was not worth the API surface.

Net: the real perf win here is the 11x faster test suite. bashdep itself
is unchanged in speed; no runtime optimization survived measurement, and
install is network-bound regardless.

✅ Verification

  • 252 tests green, ShellCheck clean, editorconfig clean (make pre_commit/run)
  • Verified on macOS default bash 3.2.57 (the compatibility floor)
  • No network access from the suite; lib/ stays clean across runs

bashunit 0.17.0 -> 0.45.0 cuts the suite from ~27s to ~2.5s.

The upgrade is not drop-in: bashunit moved its doubles under
`bashunit::mock` and changed the multi-argument form to append "$@" to
the mock body, so a body that reads positional arguments (`touch "$3"`)
can no longer be expressed. This suite uses that shape in 62 of its 93
mocks. When `mock` silently resolved to "command not found", the mocked
tests fell through to real downloads, hit the network and overwrote
lib/bashunit itself.

tests/bootstrap.sh now owns `mock`/`unmock` with the semantics the suite
was written against. Each bashunit test runs in its own subshell, so the
helpers need no mock registry and depend on no bashunit internals.

Also pins the two floating action refs (action-shellcheck@master,
action-editorconfig-checker@main) so CI runs are reproducible, bumps the
remaining actions, and ignores bashunit's new .bashunit/ state dir.
BASHDEP_JOBS was reachable only as an environment variable and was absent
from --help, so the one performance knob bashdep has was effectively
undiscoverable.

Adds `--jobs=N` and `bashdep::setup jobs=N`, lists the flag in --help,
and offers it in the bash/zsh completion scripts. Validation is
deliberately left where it already lived: like the environment variable,
a non-integer warns and falls back to 4 when install runs, so all three
entry points behave identically.

Also caches the shasum/sha256sum probe in BASHDEP_SHA_TOOL, mirroring how
BASHDEP_DOWNLOADER already pins curl/wget for a whole run so every
checksum is computed by the same tool. Measured performance-neutral (150
digests: 1.51s before and after) — a consistency change, not a speedup.
@Chemaclass Chemaclass added enhancement New feature or request performance Runtime or CI performance developer-experience Contributor or consumer DX labels Aug 9, 2026
@Chemaclass Chemaclass self-assigned this Aug 9, 2026
@Chemaclass
Chemaclass merged commit 26cdb7a into main Aug 9, 2026
6 checks passed
@Chemaclass
Chemaclass deleted the chore/update-deps-and-optimize branch August 9, 2026 17:14
Chemaclass added a commit that referenced this pull request Aug 9, 2026
CONTRIBUTING listed bashunit 0.17.0 in the toolchain table; the repo has been
on 0.45.0 since #64, so anyone matching that table locally would install a
version whose doubles API the suite no longer targets.

The landing page advertised concurrency as BASHDEP_JOBS only, predating the
--jobs=N flag added in #64.

Prose across README and docs/ is no longer hard-wrapped at 80 columns.
.editorconfig sets max_line_length for **.sh (120) and never for **.md, so
long lines lint clean and reworded sentences stop reflowing whole paragraphs
in diffs. Code blocks, tables and lists are untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

developer-experience Contributor or consumer DX enhancement New feature or request performance Runtime or CI performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant