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 origin story
Section titled “The origin story”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]].
Schema
Section titled “Schema”[[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 |
Wiring a guard into a copy
Section titled “Wiring a guard into a copy”The guard runs only when a [[bootstrap.copy]] step references it by name:
[[bootstrap.copy]]from = ".env"to = ".env"required = falseguards = ["no-aws-rds"] # ← referenced hereA 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.
on_match semantics
Section titled “on_match semantics”abort (default)
Section titled “abort (default)”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 backThe user sees the offending pattern, the line, and the fact that nothing was left behind. Re-run is safe.
seed-from-example
Section titled “seed-from-example”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.exampleUseful 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.
Regex syntax
Section titled “Regex syntax”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\.']Doctor coverage
Section titled “Doctor coverage”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.
Related
Section titled “Related”- Bootstrap pipeline: where guards sit in the execution order
.gwm.tomlschema: full type reference