push.sh requires bash 4+ (declare -A) with no version guard — fails on macOS's default bash 3.2
0
Anchors
—
Blast radius
—
Churn 30d
0
Proposals
Summary
push.sh uses declare -A (associative arrays), which requires bash 4+, with no version guard. macOS ships bash 3.2 by default, so push.sh fails outright for anyone running it under the system bash on macOS rather than a Homebrew-installed bash 4/5.
Fix
Small — either:
- Add a version check at the top of
push.shthat fails with a clear message pointing atbrew install bash(or equivalent) if running under bash < 4, or - Rewrite the associative-array usage to avoid requiring bash 4 (e.g. parallel indexed arrays, or a
casedispatch) if broad compatibility is preferred over a version gate.
Source
Reported by aaronrene, 2026-09-10 (relayed via message to gabriel, processed 2026-09-11) — one of four friction notes; the other three (per-env SSO profiles, secrets.sh writing DATABASE_URL, and the deploy.sh registry bug) are already fixed or tracked (see #194).
Activity1
closed this issue
34 days ago
Fixed.
Root cause:
push.shuseddeclare -A(associative arrays) for its per-environmentINSTANCE/ECR_REGISTRY/AWS_PROFILElookup tables, with no version guard. Associative arrays require bash 4+; macOS ships bash 3.2 as/bin/bashwith no upgrade path short of Homebrew, so anyone runningpush.shunder the system bash hit 'unbound variable' at the very first array reference, before the script did anything useful.Fix: replaced all three associative arrays with
case-dispatch helper functions (instance_id_for/ecr_registry_for/aws_profile_for) — went with the ticket's second suggested option (rewrite to avoid bash 4 entirely) rather than a version-gate, since it means there's nothing for a user to install at all.Tests: new
TestPushShBash32Compatintests/test_deployment.py. Reproduced the reported crash for real against the actual macOS system bash (confirmed 3.2.57 on the dev machine) before the fix, confirmed the usage message now prints cleanly after it, and confirmed the replacement helper functions resolve the exact same values the old arrays held. Fulltests/test_deployment.pysweep: 37 passed.This is a local operator script (never runs inside the deployed container), so no server deploy was needed — pushed to local/staging/production
dev.