chore: 🔧 allow git push/tag without prompting - #5
Merged
Conversation
lib/common.sh's log/ok/warn/die and its ERR trap duplicated ANSI-color logging logic that now has a canonical home in zz_colors/zz_log at https://github.com/tomgrv/scripts (already shared with tomgrv/devcontainer-features' common-utils feature). Bootstrap zz_use from there on first source and delegate to it instead, keeping every existing call site (log/ok/warn/die) and die's exit-1 behavior unchanged. Everything else in lib/common.sh (apt helpers, net_port/net_access, dispatch_action, Helm/k3s helpers) stays local: it's vps-specific domain logic, not duplicated anywhere. dispatch.sh's own standalone log/ok/warn/die are intentionally left untouched too - it must stay a zero-dependency POSIX sh entrypoint (curl | sudo sh) that works before the repo is even cloned, so it can't assume network access to a second external repo.
Every feature (system, security, tailscale, cockpit, k3s, rancher, dockermanager, argocd, epinio) moves from features/<name>/ to a top-level <name>/, alongside two new folders for what used to be lib/common.sh and lib/summary.sh: common/ and summary/ - both excluded from dispatch.sh's feature discovery, but laid out the same way (package.json + run.sh) so they're zz_use-able too. This matches https://github.com/tomgrv/scripts' own one-folder-per-script layout, which is what makes zz_use itself usable directly against this repo: `zz_use perspikapps/vps/rancher` now fetches and installs any one feature standalone, without cloning this repo or running dispatch.sh - zz_use's [org/repo/]<tool>[@ref] syntax resolves perspikapps/vps as the origin. Every feature's run.sh now bootstraps zz_use (if not already on PATH) and does `zz_use perspikapps/vps/common; . common` instead of a relative `source ../../lib/common.sh`, so it works the same way whether invoked by dispatch.sh, standalone from a checkout, or zz_use-installed from anywhere. dispatch.sh, package.json (workspaces), and README.md updated throughout for the new paths; package-lock.json regenerated. Added tests/ (bats): syntax checks on every run.sh/dispatch.sh, a check that every feature's run.sh has the new zz_use/common wiring, and coverage of common/run.sh's pure logic (net_port/net_access/all_network_ports/feature_package_json/ dispatch_action) against a fixture tree - this repo had no test suite before.
Every folder's package.json now has "bin": {"<name>": "run.sh"}, matching
the convention tomgrv/scripts uses for its own scripts and what
zz_use perspikapps/vps/<name> relies on - except tailscale/, which uses
"vps-tailscale" instead: tailscale/run.sh calls the real tailscale CLI
internally, so the bare name would let a zz_use-installed copy shadow the
actual binary it depends on.
Every feature's "dependencies" now also declares "@vps/common": "*" (a
real workspace dependency - every feature sources common/run.sh), on top
of any existing @vps/<feature> deps. Since common/ (and summary/) aren't
installable steps, dispatch.sh's feature_deps() now excludes them from
the dependencies it reads for auto-enable/--down-<step> refusal, so they
never get treated as toggleable steps despite being real dependencies.
common/package.json's own two dependencies (zz_colors, zz_log) live in
the separate tomgrv/scripts repo, not as workspace members here - listing
them as plain "dependencies" entries would make `npm install` try (and
fail) to resolve them from the registry. Documented instead under a new,
npm-ignored "zzUse" field.
Extended tests/test-syntax.bats to cover all of the above; README.md's
"One folder per feature" section and common/README.md updated to match.
The previous commit's "bin": {"vps-tailscale": "run.sh"} in
tailscale/package.json didn't actually prevent the collision it was meant
to: zz_use has no awareness of package.json's "bin" field at all - it
always installs <name>/run.sh under the literal folder name <name> it
was asked for. zz_use perspikapps/vps/tailscale would still have
installed this feature's own script as "tailscale", shadowing the real
Tailscale CLI it calls internally.
Renamed the folder itself instead - the only thing zz_use actually keys
off. package.json's own "name" field stays "@vps/tailscale" (that's what
dispatch.sh reads for feature identity/CLI flags - --only-tailscale etc.
are unchanged), so only the folder differs from every other feature's own
name. Verified end-to-end against the real pushed branch: zz_use
perspikapps/vps/vps-tailscale now installs cleanly under that name, with
no "tailscale" binary ever created by it.
Simplified tests/test-syntax.bats accordingly (folder/bin names are
uniform again - no more special-casing) and added a guard test that no
package.json's bin ever uses the bare "tailscale" name.
1/ Every package.json's "name" and "dependencies" keys move from
@vps/<name> to @tomgrv/vps-<name>, matching the org scope used
elsewhere (tomgrv/scripts, tomgrv/devcontainer-features). Updated
dispatch.sh's feature_name()/pkg_deps() and common/run.sh's
feature_package_json() to match the new prefix; package-lock.json
regenerated; README and test fixtures updated throughout.
2/ Added a root setup.sh (mirroring tomgrv/scripts' own): a thin,
zero-prerequisite wrapper that installs zz_use by delegating to
tomgrv/scripts' setup.sh - the same "don't reimplement what you can
delegate to" reasoning that script itself uses for zz_use's bin-dir
logic. Every run.sh's bootstrap shrinks from a 3-line block embedding
the tomgrv/scripts URL directly to one line delegating to this repo's
own setup.sh instead:
command -v zz_use >/dev/null 2>&1 || curl -fsSL "${VPS_SETUP_URL:-...}" | sh
so the tomgrv/scripts URL/env-var default now lives in exactly one
place. Documented the whole pattern in a new README section,
"Replicating this pattern in another repo", generic enough to copy into
a different codebase (this repo, tomgrv/devcontainer-features'
common-utils, and tomgrv/scripts itself already share this shape).
Extended tests/ to cover both: the new @tomgrv/vps-* dependency
declarations, and that every run.sh uses the centralized setup.sh
bootstrap rather than a duplicated tomgrv/scripts URL.
…patch.sh Every feature's run.sh previously embedded its own "command -v zz_use || curl ... setup.sh | sh" - one curl call per script. Removed: dispatch.sh now runs setup.sh exactly once, up front (right after the root check, before any feature runs), so zz_use is on PATH for every feature's subprocess. Individual run.sh scripts no longer curl anything themselves - they just fail fast with a one-line message pointing at setup.sh if zz_use somehow still isn't there (e.g. run standalone, outside dispatch.sh). common/run.sh drops the bootstrap entirely: it's only ever reached by sourcing from a caller that already passed this same check, so by the time its own body runs, zz_use is guaranteed present. Found and fixed a real bug this exposed under end-to-end testing: common/run.sh's VPS_SETUP_ROOT was computed from its own BASH_SOURCE[0] (wherever zz_use last installed it, e.g. /usr/local/bin/common) instead of the calling script's location - since zz_use perspikapps/vps/common always (re)installs rather than reusing a local checkout's sibling common/run.sh (explicit org/repo requests never skip as "already available"), this broke feature_package_json/net_port/all_network_ports even inside a normal dispatch.sh run from a full checkout. Fixed to use BASH_SOURCE[1] (the caller's location), matching the pattern net_port/ net_access already used. Updated README.md's "Layout", standalone-run, and "Replicating this pattern in another repo" sections to match; extended tests/ with two new checks (no run.sh curls setup.sh itself; dispatch.sh bootstraps zz_use exactly once).
Removed comments that only restated what the following line already does, historical/rationale narration (why a decision was made, links to external docs), and header "Env vars:" blocks duplicating README's env var tables - keeping just a one-line pointer to README instead. Every run.sh's header comment shrinks to a single line. Kept: every runtime log/warn/die message an operator actually sees while running the script (these are the usability payload, not noise) - including the detailed failure diagnostics in argocd/epinio's helm timeout handling and dispatch.sh's TAILSCALE_AUTHKEY guard. Kept the handful of comments that explain a genuinely non-obvious gotcha (random_password's SIGPIPE/pipefail interaction, the ERR trap, the BASH_SOURCE[1] indirection in VPS_SETUP_ROOT) but compressed them to one line each. Also fixed a real doc gap this exposed: setup.sh's own trimmed comment was the only place documenting its ZZ_SCRIPTS_REF/ZZ_SCRIPTS_SETUP_URL override env vars - moved that one line to README's Layout section instead of just dropping it. ~230 lines removed across dispatch.sh, setup.sh, common/run.sh, and every feature's run.sh; behavior unchanged (bats/shellcheck/sh -n all still pass).
Missed in the previous rationalization pass - the test name already says what it checks.
Removes the log()/warn()/die() wrapper functions from common/run.sh (ok() is kept - it's not a thin proxy the same way) and updates every call site across the feature scripts to call zz_log i/w/e directly, adding an explicit exit 1 where die() previously did. dispatch.sh's own independent log/warn/die are untouched since it must stay a zero-dependency POSIX sh entrypoint that runs before zz_use exists.
…ch.sh setup.sh now execs package.json's "main" (dispatch.sh) after installing zz_use, forwarding args through - so `curl setup.sh | sh -s -- --only-rancher` behaves the same as calling dispatch.sh directly. dispatch.sh's own zz_use bootstrap now forwards "$@" the same way when it falls back to setup.sh, and the check moved earlier (right after the OS check) so a fresh install doesn't re-run the interactive menu twice. Matches the shared setup.sh pattern now used across tomgrv/scripts and tomgrv/devcontainer-features.
Avoids colliding with other repos' own SETUP_DIR-shaped env vars by keeping this script's local var under the zz_ namespace convention.
A curl | sh pipeline's exit status is sh's, not curl's, so a failed download would go unnoticed under set -e. Download to a temp file and run that instead - same fix applied to the scripting devcontainer feature's copy of this template (tomgrv/devcontainer-features#139).
Same hardening as tomgrv/scripts's copy of this template: reject absolute paths and ".." segments in "main" before using it to build a file path, and invoke sh with "--" for defense in depth.
- common/run.sh: feature_package_json()/all_network_ports() now only scan directories that have a run.sh alongside package.json, so a checked-out node_modules/ (thousands of unrelated package.json files) is no longer traversed/jq-parsed on every call. - README: fix a leftover "tailscale/" reference (folder is vps-tailscale/), clarify that curl | sh only bootstraps zz_use without a local checkout to find package.json/dispatch.sh in, and note the jq prerequisite in the standalone zz_use example. - tests: fixture dirs get a run.sh to match the new filter, plus a regression test asserting node_modules/* ports are skipped.
Contributor
Author
|
Generated by Claude Code |
tomgrv
marked this pull request as ready for review
August 27, 2026 19:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
permissions.allow: ["Bash(git push:*)", "Bash(git tag:*)"]to.claude/settings.jsonso Claude Code sessions in this repo no longer prompt forgit push/git tag.🤖 Generated with Claude Code
Generated by Claude Code