Conversation
…cture ops/ and docs/ move under a new gate that resolves every script path on an executed .tf/.tm.hcl line: 87 today, 30 of them to scripts this PR moves. Every expected count was measured by simulating the move.
87 references on executed lines, 30 of them to scripts this PR moves. They run at apply and destroy time and no CI job executes them; neither test-script-paths.sh nor verify-doc-paths.sh reads a .tf or .tm.hcl.
aws/, gcp/, k8s/, demo/. The cloud prefix drops where it repeats the directory. eks-prepare-destroy.sh's call to reclaim-csi-volumes.sh crosses directories now and is corrected by hand: no gate sees a path passed to exec.
teardown.sh is the supported teardown entry point; the other three are what terramate destroy calls (22 of the 34 references). The terramate reference gate went from 22 failed to 0.
Spec criterion 2: every entry point has a one-line description. Only teardown.sh is indexed in ops/teardown/; terramate calls the rest.
Check 1 flagged any dirname+.. idiom that didn't resolve to the repo root, which made every correct Task 4/5 fix false-positive: climbing to a sibling directory (lib/, k8s/) isn't a root climb. Classify by what follows the climb -- a named path segment means "sibling", checked for existence; anything else (the climb ends the path, or a variable follows it) means "root", checked against the two markers as before. This also means eks-prepare-destroy.sh's exec of ../k8s/reclaim-csi-volumes.sh is now gated -- 169b2493 said no gate saw it; it does now, via the new "relative paths" count. 11 roots, 4 relative paths, 21 sources, 16 subjects checked; 0 failed.
The ops/{aws,gcp,k8s} row said "also called from terramate destroy
scripts", but eks-recycle-bootstrap-nodes.sh and adopt-workforce-pool.sh
run on every deploy, not just destroy. Named both, and corrected the
closing note: those two already moved to ops/, ahead of the rest of
the apply-time scripts still waiting on provision/.
Round 1's sibling branch trusted plain existence, but AGENTS.md and README.md both nest at several depths: a climb that stops one level short of the root can land on a decoy of the same name and pass by accident, exactly like the wrong-depth case it's meant to catch. Before the existence check, look at the climb's first path segment. If it also exists at the repo root and the climb itself didn't land there, fail loudly instead of trusting the coincidence. 11 roots, 4 relative paths, 21 sources, 16 subjects checked; 0 failed.
…an't resolve
The gate only ever extracted what its inner regex matched, so an
unbraced variable, a single-quoted path, a bare "../.." climb, or a
$(git rev-parse ...) prefix silently checked 0 refs and passed. Count
the outer "scripts/..." mentions per line against what the inner
regex extracted; fewer extracted fails as an unresolvable shape.
Also close the trust gap on the other side: a ${...}/$${...} prefix
now resolves only as ${path.module}, ${terramate.root.path.fs.absolute}
or $${ROOT} -- the three this codebase actually uses. Anything else
(${path.root}, ${terramate.stack.path.absolute}) failed silently
resolved against $ROOT/scripts/ before; it now fails as an
unrecognised prefix instead of guessing.
--exclude-dir=.terraform on the outer grep: vendored modules there are
gitignored and inflated the count locally (94 vs 88 in CI).
88 checked; 0 failed on the tree, unchanged.
It is a destroy-time helper, not a day-2 entry point: gke destroy and eks-prepare-destroy.sh call it directly, with no prompt, and it deletes every PVC and CNPG cluster in the current kube context. The file's own rule already excludes destroy-time helpers -- this one was missed. task --list now shows 15 ops/docs tasks, not 16.
"Compute it from a REPO_ROOT/SCRIPTS variable" was itself wrong: a SCRIPTS=.../../.. variable climbs the same ambiguous way and fails the root check it's supposed to satisfy. The only fix that actually resolves is climbing to REPO_ROOT and naming the path from there.
…ables M5: the closing paragraph repeated the ops row and reversed the causality (named the two deploy-time scripts as if they were the exception rather than the rule). Replaced with the plain fact: apply-time provisioning scripts still sit at the root of scripts/, moving to provision/ later. M6: the terramate-refs row described the gate's pre-I1 behavior (exists or is silently skipped). After I1 every mention on an executed line is resolved or fails loudly, and .tfvars is one of the three extensions it reads.
- ops:gcp:adopt-workforce-pool needs an initialised stack directory as cwd for its tofu-import half; without dir:, that half always skipped. Set dir: to the workforce-identity stack. - adopt-workforce-pool.sh's usage said "from the stack directory" but gave a repo-root path; gave both the from-stack-dir and from-anywhere forms instead. - commands.md named the renamed scripts by bare name, which verify-doc-paths.sh cannot check and which means nothing on their own (load.sh, reclaim-csi-volumes.sh, ...). Full scripts/ops/... and scripts/docs/... paths. Also: export-diagrams.sh writes SVG, not PNG. - docs/architecture/AGENTS.md's "after any diagram change" block lost its column alignment when export-diagrams.sh moved into scripts/docs/.
Contributor
🔍 Rendered manifest diff — this PR vs
|
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.
PR 2 of 3 in the
scripts/restructure. It moves the day-2 operations scripts intoscripts/ops/<area>/and the docs generators intoscripts/docs/. A new gate goes in first: it fails CI when any script path that opentofu or terramate executes doesn't exist. PR 1 (#2061) is merged; PR 3 (provision/) is still to come.flowchart LR subgraph before["after PR 1"] R["scripts/ root<br/>32 files"] end subgraph after["after PR 2"] O["ops/aws · gcp · k8s · demo · teardown<br/>17 scripts"] D["docs/<br/>3 generators"] C["ci/check-rebased.sh"] P["root: 8 files<br/>provision-bound (PR 3)"] end R ==> O & D & C & P G["test-terramate-script-refs.sh<br/>88 executed refs, 0 unresolved"] -.->|gates| O classDef new fill:#d4edda,stroke:#28a745 classDef pending fill:#f8f9fa,stroke:#adb5bd,stroke-dasharray:4 class O,D,C,G new class P pending📋 Design
2026-09-17-scripts-restructure-design.md2026-09-21-scripts-restructure-pr2-plan.md. PR 1's plan is2026-09-17-scripts-restructure-pr1-plan.md.What changed
scripts/ci/tests/test-terramate-script-refs.shopentofu/**/*.{tf,tm.hcl,tfvars}: 88 refs, floor 80,.yamlincluded,.terraform/excluded. A shape it can't resolve, or a${…}prefix outside its allowlist, fails loudly instead of being skipped. These paths run at apply and destroy time, and no CI job executes them.scripts/ops/{aws,gcp,k8s,demo}/aws-sweep-orphaned-volumes.shbecomesops/aws/sweep-orphaned-volumes.sh.scripts/ops/teardown/teardown.sh, the supported teardown, plus the 3 helpers terramate destroy callsscripts/docs/export-diagrams.sh,diagram-icons.py,build-og-card.htmlscripts/ci/check-rebased.sh.pre-commit-config.yamlupdatedtask --listops:*/docs:*entries that work from any directory. Destroy-time helpers are deliberately not indexed.scripts/ci/tests/test-script-paths.sh../../lib/…) from a root climb, and fails an under-climb that lands on a name the repo root also has (nestedAGENTS.md,scripts/README.md).The design's Deletions table was overruled for
teardown.shandaws-sweep-controller-orphans.sh. Both have "no caller" only because a human is the caller:teardown.shis the supported teardown (#1970, #1976), and the sweep is its recovery step. Owner decision, 2026-09-21. Nothing is deleted in this PR.The plan makes
terramate script run previewon both clouds a merge gate (owner decision, 2026-09-21). The whole-branch review then found thatpreviewruns none of the moved scripts. Countingterramate script infolines that name a moved script:previewdrift detectdeploydestroyThe design's preview evidence fits PR 3, where
helm-release-present.shruns at plan time. For this PR, the reviewer recommends different evidence:task ops:teardownafter merge, whose logs should be watched forNo such file.I left the gate as you set it. Please choose:
Evidence
Run on this branch, rebased on
main@1c987b17. CI runs the render.The refs gate was proved against fixtures:
terramate-destroy-confirm.shwithout rewriting gives 15 failed;helm-release-present.shgives 2 failed;${path.root}/…fails as an unrecognised prefix.All 13 symlinks are intact, no workflow changed, and job names are unchanged.
Rulings made during implementation
All are recorded in the SDD ledger.
.yamltoo (88, not 87)./..as a root climb.# shellcheck source=lines stay root-relative, because CI runs shellcheck from the root.ops:k8s:reclaim-csi-volumes. It deletes every PVC on the current context without a prompt.Follow-ups (not in this PR)
teardown.sh's${ROOT}/scripts/ops/aws/…sweep calls are not gated. The paths gate's check 3 covers onlyHERE/SCRIPT_DIR./..climb on a line.scripts/ci/validate-manifests.sh:20andflux-schema/gen-catalog.sh:37have# shellcheck source=paths that don't resolve from the root (SC1091, hidden at-S warning)./* */block would be read as code, which fails loud, and there are 0 today;bundle.tm.ymlis not scanned, and there are no bundles today.