Skip to content
gwmgwmgwmv1.10.0

Regex guards

[[bootstrap.guard]] rules vet each file produced by stage 1 of the bootstrap pipeline against a list of regex deny-patterns. A match triggers either an abort or a substitution from a known-good fallback.

The original incident: someone created a worktree from a repo with .env pointing at the production AWS RDS host, then ran php artisan migrate:fresh --seed in the worktree thinking it was the local DB. The migration ran against prod.

The fix was institutional: never copy a .env blindly across worktrees. The mechanism is [[bootstrap.guard]].

[[bootstrap.guard]]
name = "no-aws-rds"
deny_patterns = ["amazonaws\\.com", "\\.rds\\."]
on_match = "seed-from-example" # or "abort"
example_file = ".env.example" # required when on_match=seed-from-example
Field Type Default Meaning
name string (required) referenced by [[bootstrap.copy]].guards = [...]
deny_patterns list of strings [] Rust regex patterns (regex crate syntax). Matches anywhere in the file are flagged.
on_match string "abort" "abort" or "seed-from-example"
example_file string none path (relative to main checkout) of the file to substitute when on_match=seed-from-example

The guard runs only when a [[bootstrap.copy]] step references it by name:

[[bootstrap.copy]]
from = ".env"
to = ".env"
required = false
guards = ["no-aws-rds"] # ← referenced here

A guard with no copy references it is dead config, and gwm doctor (check #2) does not flag this (yet), so audit by hand or run grep guards .gwm.toml to spot orphans.

A match halts the entire bootstrap with ✗. The worktree itself was already created (stage 1 succeeded), so gwm rolls it back: removes the worktree directory and the branch.

bootstrap report:
✗ guard no-aws-rds on .env
pattern 'amazonaws\.com' matched on line 12
→ bootstrap aborted, worktree rolled back

The user sees the offending pattern, the line, and the fact that nothing was left behind. Re-run is safe.

A match triggers a substitution: gwm overwrites the offending file with the contents of example_file (still relative to the main checkout, since the worktree is fresh and unlikely to have its own example). Reported as ! (warning), pipeline continues.

bootstrap report:
! guard no-aws-rds on .env
pattern 'amazonaws\.com' matched on line 12
→ substituted from .env.example

Useful when .env is genuinely sensitive but you want the worktree to have some working config (e.g. local sqlite): the substitution lands you in a known-safe baseline you can iterate from.

Patterns use the regex crate: Perl-ish, no look-around. Anchors:

  • No anchor → matches anywhere in the file.
  • ^…$ with the multi-line flag (?m) → matches per-line.

Common patterns:

deny_patterns = [
"amazonaws\\.com", # AWS endpoints
"(?m)^DB_PASSWORD=(?!$|\"\"$)", # any non-empty DB_PASSWORD line
"BEGIN .* PRIVATE KEY", # accidental SSH keys
"sk_live_[A-Za-z0-9]{20,}", # Stripe live secret keys
]

Backslashes must be doubled inside TOML strings. Use TOML’s literal strings ('...') for raw regex if you have many backslashes:

deny_patterns = ['amazonaws\.com', '\.rds\.']

gwm doctor check #2 (guard references resolve) validates that every [[bootstrap.copy]].guards = [...] name points at an existing [[bootstrap.guard]]. Catches typos at config-time instead of waiting for the next gwm create to fail. See Integrations → gwm doctor.