Repository navigation
fix(environments): name a key GitHub only reports or does not echo on an entry or a nested entry - #604
Conversation
… an entry or a nested entry An environment entry, and each entry of its nested lists, is an open shape: a key the shape does not declare passes the parse and rides the request. Two classes of such a key had no line naming them. A key GitHub only reports (the GET returns it, the write does not take it) is now named by a note in every run, from the declaration alone: id, node_id, url, html_url, created_at, updated_at and protection_rules on an entry, id and node_id on a deployment branch-policy pattern, created_at and updated_at on a variable. The three lists are pinned both ways to @octokit/openapi-types. The variable note lives in the shared variables engine, so actions_variables and agents_variables print it too. An undeclared key on a branch-policy pattern that the live pattern does not echo (a typo such as typ for type) is now named by a note in every run where the pattern exists. The planner sends such a key on the create call alone and compares it in no run, so it adds no drift; phantomNote takes an optional tail for a write the comparison does not gate, and every existing caller prints the sentence it printed before. No file that parsed before is refused. Each open shape that still accepts a reported key carries a COMPAT(v4) marker naming the parse refusal that replaces the note.
File size check0 over a hard cap (fails), 6 warning(s).
Split the file, wrap the line, shorten or exempt the comment, or list the path in 5 managed file(s) skipped; repo-platform owns them. |
Member shape check18 finding(s).
Add the blank lines, make the comment one line directly above the item, comment every field or none, or list the path in 4 generated file(s) skipped. |
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are identified for the diagnostic-note changes.
No open issues 🎉
What changed in this PR
Adds diagnostic notes to GitHub Settings as Code for environment, branch-policy, and variable keys that GitHub only reports or does not echo back. Existing parsing and reconciliation behavior stays unchanged; rejection of reported-only keys remains deferred to v4.
Changes:
- Adds reported-only key lists checked against OpenAPI types and notes that avoid naming the same key twice.
- Reports unechoed branch-policy keys and extends the shared note formatter with an optional ending.
- Adds unit tests, an end-to-end scenario, and documentation for the diagnostics.
| File | Description |
|---|---|
test/sections/environments/scenarios/environment-branch-policies-unknown-key-noted.yml |
Verifies a misspelled pattern key produces a note without drift or writes. |
test/sections/environments/environments.test.ts |
Tests reported-only and unechoed keys across environment and nested entries. |
test/sections/actions_variables/actions_variables.test.ts |
Tests reported timestamp notes for repository variables. |
src/sections/shared/secrets-and-variables/variables-engine.ts |
Adds shared variable timestamp diagnostics and suppresses duplicate notes. |
src/sections/shared/schema-helpers.ts |
Adds a compatibility comment deferring timestamp rejection to v4. |
src/sections/environments/schema.ts |
Adds compatibility comments for future reported-only key rejection. |
src/sections/environments/reported-keys.ts |
Defines OpenAPI-checked key lists and a reported-key note formatter. |
src/sections/environments/index.ts |
Adds environment reported-key notes, including for missing environments. |
src/sections/environments/branch-policies.ts |
Adds reported-only and unechoed pattern-key diagnostics. |
src/engine/diff.ts |
Allows callers to customize the ending of phantom-key notes. |
docs/sections/environments.docs.yml |
Documents when the new diagnostics appear. |
docs/reference/coverage.md |
Updates generated coverage documentation to match. |
Review effort: Balanced
… writes, and pin the unattempted report The note for a key GitHub only reports was written twice, in the environments section and in the shared variables engine. It is now one function in src/sections/shared/reported-key-note.ts, called by the entry, the branch-policy pattern, and the variable. A variable that does not exist yet is written by a POST, so the variable note now says neither the POST nor the PATCH takes the key. The environmentDrift comment is two short paragraphs, and each COMPAT(v4) marker sits in its declaration's doc comment. A reported key declared null still draws its note, and a test row pins it: such a declaration drifts against the live value and rides the write. A new scenario pins what a refused entry leaves unattempted: the first environment's PUT answers 422, and the run names the second environment's variable and secret as not attempted, on stdout and in the summary.
Before
After
No file that ran before stops running: nothing new is refused.
A reported key's parse refusal waits for version 4 behind
COMPAT(v4). Taking it earlier is the owner's decision.How
@octokit/openapi-types.reportedKeyNote, reads the declaration alone, whatever value the key holds.phantomKeysonce the pattern is live.phantomNotetakes an optional tail: a pattern's extra key gates no write.actions_variablesandagents_variables.phantomKeysandphantomNote, covering the unechoed key.Proof
phantomNotecallers: 583 tests pass, no expectation changed.Technical details
parseScenarioandrunScenario, as a check, an apply, and a check right after the apply.origin/main, After the same command against this branch.origin/maindoes not hold it. The After is the same command on this branch.::notice::environments[prod]: ....additionalProperties: false), andtest/e2e/mock/request-body.test.tspins the mock's 422 for a closed body.can_admins_bypasssits in the repository's own live fixture (test/sections/environments/snapshot-row.ts), is absent from the descriptor, and completes a run when it equals the live value.id,node_id,url,html_url,created_at,updated_at,protection_rules.id,node_id.created_at,updated_at.html_urlfrom the entry list is TS2344, addingnameto the pattern list is TS2322 (bun run typecheck).id: nullagainst a live id 99 drifts and rides the PUT body, so it is not inert, and a test row pins the note.deployment_branch_policies: [{name: "v*", typ: tag}]on a pattern that does not exist yet prints no note in the creating apply, and one in every later run.deployment_branch_policies: [{name: "v*", typ: ""}]against a live pattern prints no note, because the diff reads both values as not declared.reviewers: [{type: User, id: 1, typ: Team}, {type: User, id: 2}]against live User reviewers 1 and 2 prints no note and two drift lines, onorigin/maintoo: the extra key stops the entry matching.deployment_branch_policyonce the environment exists, and a key insidereviewers[]while its entry still matches a live reviewer.test/schema-corpus.test.tsneeds no known-divergence entry.origin/mainthe 17 new cases give 16 fail and 1 pass, the named control (bun test test/sections/environments/environments.test.ts test/sections/actions_variables/actions_variables.test.ts -t "outside the entry shapes|only reports").environments-apply-refused-entry-reports-unattemptedpins the warning and the twonot attemptedlines on stdout and in the summary.bun test test/sections/environments test/sections/actions_variables test/sections/agents_variables, andbun test/e2e/run.ts --sections environments,actions_variables,agents_variables.phantomNote: ten call expressions in nine files, their arguments unchanged.bun run build:schema:bun test test/engine/diff.test.ts test/sections/actions/ test/sections/autolinks/ test/sections/branches/ test/sections/deploy_keys/ test/sections/interaction_limits/ test/sections/labels/ test/sections/pages/ test/sections/repository/ test/sections/rulesets/ test/sections/shared/setup-section.test.ts.bun test/e2e/run.ts --sections actions,branches,code_quality_setup,code_scanning_default_setup,pages.pages-enable-needs-build-type-or-source, fails onorigin/mainalone too: it expects the section key twice, and this change touches neither the scenario nor that line.src/sections/environments/schema.ts, one onvariableConfiginsrc/sections/shared/schema-helpers.ts, each inside its declaration's doc comment and naming the actions section's reported-only refusal as its successor.typecheck,lint,lint:arch,knip,check:compat,build:check.src/sections/shared/reported-key-note.ts,src/sections/environments/{reported-keys.ts,index.ts,branch-policies.ts,schema.ts},src/sections/shared/secrets-and-variables/variables-engine.ts,src/sections/shared/schema-helpers.ts,src/engine/diff.ts.test/sections/environments/{environments.test.ts,scenarios/environment-branch-policies-unknown-key-noted.yml,scenarios/environments-apply-refused-entry-reports-unattempted.yml},test/sections/actions_variables/actions_variables.test.ts,docs/sections/environments.docs.yml, and the generateddocs/reference/coverage.md.The table script, probe.mts
Save it outside the checkout, then run
TMPDIR="$(mktemp -d)" bun probe.mts /path/to/checkout.