Repository navigation
refactor(sections)!: environments plan through the secrets and variables engines; the sealing key is read at apply - #207
Conversation
710c209 to
bb6fd9d
Compare
a83fecd to
3b57545
Compare
File size check0 over a hard cap (fails), 8 warning(s).
Split the file, wrap the line, shorten or exempt the comment, or list the path in 4 managed file(s) skipped; repo-platform owns them. |
3b57545 to
3ebc7ec
Compare
3ebc7ec to
b8e4a1a
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The refactor is internally consistent and has targeted coverage for its changed behavior.
Pull request overview
Refactors environment secrets and variables to use shared engines while deferring sealing-key reads until apply time.
Changes:
- Reuses shared engines for environment resources.
- Makes sealing-key reads execution-only and memoized per scope.
- Updates validation, tests, and v3 migration documentation.
File summaries
| File | Description |
|---|---|
test/sections/secrets-engine.test.ts |
Tests deferred, shared key reads. |
test/sections/registry.test.ts |
Pins execution-phase endpoints. |
src/sections/shared/variables-engine.ts |
Adds scoped prose, descriptions, and payload validation. |
src/sections/shared/secrets-engine.ts |
Defers and memoizes sealing-key reads. |
src/sections/shared/repo-variables.ts |
Adopts shared validation and descriptions. |
src/sections/shared/repo-secrets.ts |
Marks key endpoints execution-only. |
src/sections/environments/protection-rules.ts |
Uses shared duplicate validation. |
src/sections/environments/nested.ts |
Replaces bespoke nested planners with shared engines. |
src/sections/environments/index.ts |
Passes section metadata into validation. |
src/sections/environments/environments.test.ts |
Updates nested behavior coverage. |
src/sections/environments/branch-policies.ts |
Uses shared duplicate validation. |
src/sections/contract/endpoints.ts |
Allows execution-phase gated reads. |
src/sections/actions_variables/actions_variables.test.ts |
Covers descriptions and plain payload validation. |
src/sections/actions_secrets/actions_secrets.test.ts |
Covers apply-time sealing-key behavior. |
docs/upgrading/v2-to-v3.md |
Documents the two breaking changes. |
Review details
- Files reviewed: 15/15 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…les engines; the sealing key is read at apply The secrets engine reads the scope's sealing key from the first sealed PUT's thunk (once per scope), so the four repo families declare the key endpoint execution-phase and environments' nested secrets share the engine; the variables engine serves environments' nested variables too. Both engines take the scope's home noun and change-line suffix and render through the shared prose helpers; the variables engine proves every payload plain. The per-list duplicate rejecters in environments give way to rejectDuplicates with a resource noun. BREAKING CHANGE: check mode no longer reads the sealing key (a malformed key fails the first PUT at apply); the environment secret and variable lines use the engines' wording. docs/upgrading/v2-to-v3.md sections 10-11.
…ot as a second verb
…key is read at apply
b8e4a1a to
2e71b66
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The shared-engine refactor is consistent with existing contracts and has focused coverage for deferred reads, payload validation, and environment behavior.
Review details
- Files reviewed: 23/23 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Before / after
What changed
Environments plan their nested secrets and variables through the shared secrets and variables engines, whose sealing key is read late (at apply, by the first sealed PUT) so one engine serves the repo families and the nested scopes alike.
Behavior changes
Each has a numbered entry in docs/upgrading/v2-to-v3.md (sections 19-20, after #206's 16-18):
not on environment "prod"on a missing one,in environment "prod"on deletes; a kept undeclared variable still names its environment); the nested duplicate-entry error is the shared one.Proof
bun run checkclean),bun run test:e2e260/260 afterbun .github/scripts/trim-openapi.ts; the harness below classifies every main-vs-this-head difference (0 unclassified).where/suffix,describe,plainData; errors.ts +3 for the denial wording).Technical details
Base: main at 05e6d41 (#206); #202 landed as 2cb5c8a, the squash of 79a0851.
How
SecretsPlanScope.publicKey(exec, describe)is called from the first sealed PUT's payload thunk, once per scope (a memoized promise): an environment's key exists only after the PUT that creates the environment. The four repo families declare the key endpointphase: "execution"(the port is gated; check mode cannot issue it), which neededGatedReadDecl.phase?: "execution"for the Codespaces write-gated read.where(the home: "the environment", orenvironment "prod"for variables so a kept note names it) andsuffix(in environment "prod") and render through the shared helpers (valueDrift,cannotVerifyNote); the variables engine's ops carrydescribeand prove every payload plain (plainData).rejectDuplicateswith a resource noun (variable of the "prod" environment).Harness (main at 05e6d41 vs this head, same inputs, same matrix as #202): 9233 leaves compared, 211 differing, 0 unclassified.
not on environment "prod")Against main before #202 (cumulative): 9869 leaves, 773 differing, 0 unclassified. Baseline for the table above: a
git archiveof main at 05e6d41 (#206 changed teams, so the earlier #202-head baseline no longer matches main).Line accounting (production src = src/** minus *.test.ts, mock.ts, scenarios, docs.yml; against main at 05e6d41):
src/sections/environments/nested.tssrc/sections/environments/branch-policies.ts,protection-rules.tssrc/sections/shared/repo-variables.tssrc/sections/environments/index.tssrc/sections/contract/endpoints.ts,errors.tssrc/sections/shared/repo-secrets.tssrc/sections/shared/secrets-engine.tswhere/suffix)src/sections/shared/variables-engine.tswhere/suffix,describe,plainData,rejectDuplicateVariableNames)Tests +45 (the late-bound key, the plainData regression, the engine wording pins).
Codex rubber-duck review, 4 rounds: round 1: 1 blocking (the variables engine lost nested.ts's
plainDataguard, soextra: NaNreached the wire as null), fixed in the engine for both consumers with a regression test in src/sections/actions_variables/actions_variables.test.ts; round 2: 0/0; round 3 (the rebase resolution below): 0/0; round 4 (the three gate-fold commits): 0/0.Rebases: four
git rebase --ontoreplays. The first (onto #202's trim commit) differed in one place outside docs/upgrading/v2-to-v3.md: #202 trimmedmissingDrift, so the two engines render the missing-drift line inline (... but not on ${scope.where ?? "the repo"}; apply will create it); the rendered text is unchanged, and #202'ssecretValuesOfconversion oflistSecretValuesno longer appears here because it landed there. The second (onto #202 over main at d92b738, #205) replayed without conflict: the interdiff of added and removed lines outside the doc is empty, the doc's sections sit at 16-17 after #202's 11-15, andgit grepfor the #205 renames over src and test is empty. The third (onto main at 69fc7c4 after #202 landed as the squash 2cb5c8a) replayed without conflict, the range-diff shows the one commit=, and the added and removed lines are identical to the previous head's including the doc. The fourth (onto main at 05e6d41, #206) conflicted only in the doc, whose sections now sit at 19-20 after #206's 16-18; outside the doc the replay is identical.Recorded, not built: a test proving several payload thunks share one rejected sealing-key read; the engines do not call the duplicate guard themselves (a fourth scope must remember
rejectDuplicate*Namesas a separate call), routed to the contract-tightening task.Lead gate review (b8e4a1a), folded as three commits: blocking 1 (two environments holding the same undeclared variable emitted one byte-identical kept note;
nestedProsenames the environment again, the secrets noun already did); non-blocking (the four secret check-drift descriptions said check reads the sealing key; a denied request read "denied ... failed" with two verbs and now names its operation in parentheses,the token was denied GET /repos/o/r/actions/secrets/public-key (reading the actions_secrets sealing key): 403 ..., seven pins moved; this body). Confirmed clean by the review: one planner each, no key read in check mode, one key read per environment at apply, a denied key fails with zero PUTs, placeholders through the one helper.Out-of-territory edits: none.
BEGIN_COMMIT_OVERRIDE
refactor(sections)!: environments plan through the secrets and variables engines; the sealing key is read at apply
BREAKING CHANGE: check mode no longer reads a secret family's sealing key (a malformed key fails the first PUT at apply); the environment secret and variable lines use the engines' wording (docs/upgrading/v2-to-v3.md sections 19-20).
END_COMMIT_OVERRIDE