Skip to content

Commit dc5813d

Browse files
authored
docs(upgrading): count every public-entry break among the library sections (#480)
1 parent fa06cbf commit dc5813d

5 files changed

Lines changed: 26 additions & 2 deletions

File tree

‎docs/upgrading/v2-to-v3.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ order: 20
44

55
# Upgrading from v2 to v3
66

7-
Sixty-one breaks. Eleven are for library consumers (sections 9, 23, 24, 27, 34, 35, 54, 56, 58, 60, and 61), and two are for anyone pinning a sha or installing `@next` (sections 21 and 59).
7+
Sixty-one breaks. Twenty-six are for library consumers (sections 9, 22 to 29, 34, 35, 37 to 41, 45, 47, 49, 51, 54 to 56, 58, 60, and 61), ten of those also refusals below, and two are for anyone pinning a sha or installing `@next` (sections 21 and 59).
88

99
Eighteen are parse-time refusals (sections 36 to 52 and 55): a declaration GitHub would reject, or that could never converge, now fails before any request. Sections 53 and 57 are silent: YAML merge keys resolve, and one validation message is respelled.
1010

‎docs/upgrading/v2-to-v3/layering.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ Every list section folds this way, by the key its planner matches on: labels, co
8080

8181
The value `merge` is gone. `labels: {_layering: merge, entries: [...]}` fails with `labels._layering must be one of "replace", "shallow", "deep"; got a string that is none of them`, and the `layering` input refuses it too, naming the same three values.
8282

83+
For `@vivswan/github-settings-as-code` consumers, the `Layering` type is `"replace" | "shallow" | "deep"`, so a `layering: "merge"` in `MergeOptions` stops compiling; write `"deep"`, the fold it meant.
84+
8385
Fix: write `deep` where a layer said `merge`, and `_layering: replace` on any list section a higher layer meant to replace whole. Under `shallow` and `deep` an empty higher list adds nothing; clearing a list takes `replace` with an empty list. The [layering guide](../../operate/layering.md#four-knobs) owns the rules.
8486

8587
## 29. mode: merge is mode: render

‎docs/upgrading/v2-to-v3/refusals-lists.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ v3 branches[0].protection.required_status_checks.enforcement_level: ... is Git
5252
| A scalar where `required_status_checks` or `required_pull_request_reviews` goes | Refused on a wildcard entry, passed through to the PUT on a literal one | Refused: a mapping or `null` on every entry |
5353
| An actor object copied from the GET (`restrictions.users: [{login: octocat}]`) | Sent to the PUT, which 422ed | Refused: write the `login` or `slug` string, `octocat` |
5454

55+
For `@vivswan/github-settings-as-code` consumers, `required_status_checks` and `restrictions` under `SectionInput<"branches">` (and so `SettingsFile`) are typed shapes, once `unknown`; a check list without `strict`, or an actor object, stops compiling.
56+
5557
Fix: declare the PUT's shape (bare booleans, `strict` beside the check list, actors as their login or slug strings) instead of pasting the GET. Also new: a live `restrictions` holder whose `users`, `teams`, and `apps` are all empty is a push restriction that lets nobody through, so a file that omits it now sees the omitted-live drift line and a loud PUT instead of a silent lift.
5658

5759
## 42. Collaborators and teams: permissions and slugs
@@ -121,6 +123,8 @@ v3 webhooks[0].config.url: "hooks.example.com/ci" is not an absolute URL (the
121123
webhooks[0].events[1]: "pushes" is not an event GitHub delivers to repository webhooks ("*" means every event); the accepted names are GitHub's list at https://docs.github.com/webhooks/webhook-events-and-payloads, read from @octokit/openapi-webhooks, so an event GitHub added since arrives in the release that bumps that package
122124
```
123125

126+
For `@vivswan/github-settings-as-code` consumers, under `SectionInput<"webhooks">` (and so `SettingsFile`) `content_type`, `insecure_ssl`, and each `events` item are the unions above, once `string` or `number`; `JSON`, `2`, or `pushes` stops compiling.
127+
124128
Fix: an absolute URL, `json` or `form`, `"0"` or `"1"`, and event names from GitHub's repository list. The list is pinned to `@octokit/openapi-webhooks`, so an event GitHub adds later is refused until the release that bumps that package.
125129

126130
## 48. Secret scanning patterns must compile
@@ -160,6 +164,8 @@ v3 rulesets[0].enforcement: Invalid option: expected one of "active"|"evaluate
160164

161165
Bypass actors are typed from the spec: Integration, RepositoryRole, Team, and User need an `actor_id`; DeployKey takes none and never `pull_request`; `pull_request` applies to branch rulesets only. The 23 known rule types carry their parameters typed from the spec, in GitHub's casing; an unknown rule type still passes through, so a type GitHub ships tomorrow works the day it ships.
162166

167+
For `@vivswan/github-settings-as-code` consumers, `enforcement` and `actor_type` under `SectionInput<"rulesets">` (and so `SettingsFile`) are the enums above, once `string` and `unknown`; `enabled` stops compiling; a rule's parameters still compile.
168+
163169
Fix: spell the enums as GitHub does, give each actor its id, and write `~ALL` or `~DEFAULT_BRANCH`.
164170

165171
## 50. Milestones: due_on is a day
@@ -205,7 +211,7 @@ GitHub answers `protection_rules: []` for an unprotected environment, and the fl
205211
| More than 6 `reviewers` | 422 | Refused: GitHub's cap |
206212
| `deployment_branch_policies[].type: wildcard` | Deleted the live policy, then the create 422ed; every run retried | Refused: `branch` or `tag` |
207213

208-
For library consumers, `DeploymentBranchPolicyConfig.type` narrows from `string` to `"branch" | "tag"`.
214+
For `@vivswan/github-settings-as-code` consumers, a policy's `type` under `SectionInput<"environments">` (and so `SettingsFile`) is `"branch" | "tag"`, where the pre-release v3 builds typed `string`; a `string` there no longer compiles.
209215

210216
## 52. Autolinks: charset, placeholder, and overlapping prefixes
211217

@@ -249,6 +255,8 @@ v3 branches[0].protection.restrictions.users: protection.restrictions must car
249255

250256
GitHub's protection PUT requires `users` and `teams` under `restrictions` and takes `apps` as optional, so each missing list is refused before any request. The two review-side holders are unchanged: `dismissal_restrictions: {}` and `bypass_pull_request_allowances: {}` stay legal, since GitHub documents the empty mapping there as "disabled".
251257

258+
For `@vivswan/github-settings-as-code` consumers, `restrictions` under `SectionInput<"branches">` (and so `SettingsFile`) requires `users` and `teams`, where the pre-release v3 builds typed the block `unknown`; `restrictions: {}` stops compiling.
259+
252260
Fix: declare both lists (`users: []` and `teams: []` when none), or write `restrictions: null` to lift the push restriction.
253261

254262
## 57. A closed section's unrecognized key names the entry by index

‎docs/upgrading/v2-to-v3/refusals-repository.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ v3 repository.has_downloads: has_downloads is reported by GitHub but cannot be
2828
| A topic outside `^[a-z0-9][a-z0-9-]{0,49}$` after lowercasing, or more than 20 | 422 from the topics PUT | Refused naming the topic |
2929
| An empty topic (`topics: [""]`, `topics: ""`, `ci,,tooling`) | Dropped silently, so `[""]` cleared every topic | Refused by index |
3030

31+
For `@vivswan/github-settings-as-code` consumers, the commit-message keys under `SectionInput<"repository">` (and so `SettingsFile`) are enums and `security_and_analysis` is a closed shape, once `unknown`; a `string` or an unknown sub-key stops compiling.
32+
3133
Fix: delete the GET-only key, declare the title beside the message, and spell topics in GitHub's alphabet. A key in neither the GET nor the PATCH still passes through, so a field GitHub adds later works on day one.
3234

3335
## 38. Pages: GET-only fields and the source path
@@ -45,6 +47,8 @@ v3 pages.custom_404: GitHub reports this field on the Pages site and the updat
4547

4648
`url`, `html_url`, `status`, `custom_404`, `protected_domain_state`, `pending_domain_unverified_at`, and `https_certificate` are refused. `public: false` stays declarable: Enterprise Cloud shares the same host, so the check run's note beside the drift says why it cannot converge elsewhere.
4749

50+
For `@vivswan/github-settings-as-code` consumers, `source.path` under `SectionInput<"pages">` (and so `SettingsFile`) is `"/" | "/docs"`, where the pre-release v3 builds typed `string`; another path there stops compiling.
51+
4852
Fix: delete the reported field from the file, and publish from `/` or `/docs`.
4953

5054
## 39. Actions: fields that could never converge
@@ -69,6 +73,8 @@ v3 actions.artifact_and_log_retention.maximum_allowed_days: maximum_allowed_da
6973
| An `approval_policy` outside GitHub's three; a malformed or repeated OIDC claim key; `include_claim_keys` beside `use_default: true` | Refused naming the key |
7074
| A fractional or non-positive retention or cache limit | Refused: positive integers |
7175

76+
For `@vivswan/github-settings-as-code` consumers, in `SectionInput<"actions">` (and so `SettingsFile`) `approval_policy` is an enum, once `string`, and `selected_actions` is closed, once an open mapping; a `string` or an unknown key there stops compiling.
77+
7278
Fix: delete the reported-only field, fix the `selected_actions` spelling, and write booleans and integers unquoted. `fork_pr_workflows_private_repos` now requires only `run_workflows_from_fork_pull_requests`, as the request body does.
7379

7480
## 40. Setup sections: GET-only keys, languages, and the runner pair
@@ -89,6 +95,8 @@ v3 code_scanning_default_setup.schedule: "schedule" is reported by GitHub but
8995
code_quality_setup.runner_label: runner_label "gpu" is declared under runner_type: "standard", where GitHub ignores it; set runner_type: "labeled", or remove runner_label
9096
```
9197

98+
For `@vivswan/github-settings-as-code` consumers, `languages` under `SectionInput<"code_scanning_default_setup" | "code_quality_setup">` (and so `SettingsFile`) is an array whose items are the PATCH's enum, once `string`; `javascript` stops compiling.
99+
92100
Fix: drop `schedule` and `updated_at`, spell languages as the PATCH takes them (`javascript-typescript`; code quality's GET-only `rust` has no declarable name), and pair a string `runner_label` with `runner_type: labeled`. A declared key outside the slice that the GET never echoes now earns the never-converges note in check and apply.
93101

94102
## 44. Check-suite preferences: app_id
@@ -122,4 +130,6 @@ v3 interaction_limits.limit: limit is one of existing_users, contributors_only
122130
interaction_limits: Unrecognized key: "expires_at"; interaction_limits takes limit, expiry, pull_request_creation_cap, and pull_request_creation_bypass (origin and expires_at are what GitHub reports, not what it accepts); remove the key, or fix its spelling
123131
```
124132

133+
For `@vivswan/github-settings-as-code` consumers, `limit` and `expiry` under `SectionInput<"interaction_limits">` (and so `SettingsFile`) are the enums above, where the pre-release v3 builds typed `string`; another value there stops compiling.
134+
125135
Fix: spell the enum values as listed, keep the cap in range, and delete `origin` and `expires_at`, which GitHub reports but never accepts.

‎docs/upgrading/v2-to-v3/run.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ The action and the command line print the same line for the same problem; the re
119119
| `gsac init --settings-file a,b` | `the --settings-file value "a,b" contains a comma or a newline, which check and apply read as a list separator ...` | | `the "settings-file" input is "a,b", which contains a list separator: init writes exactly one settings file ... Name one file` |
120120
| An unreadable `repos-dir` file | `cannot read settings from <path>: ... Fix the file, or delete it to stop managing this repository` | | `cannot read the central settings file <path>: ... Fix the file, or delete it to stop managing this repository` (a YAML syntax error in it reads the same way, where v2 said `cannot parse`) |
121121

122+
For `@vivswan/github-settings-as-code` consumers: `parseConfig` takes a third argument, the face's `RunCapabilities`, and refuses `private-report: artifact` there (`input-artifact-unsupported`); a two-argument call stops compiling.
123+
122124
## 25. Every live read is parsed at the port
123125

124126
Every GET and GraphQL query a section issues now passes through one parser before the section sees the body, so a response off the documented shape fails the section instead of flowing into a comparison.
@@ -136,6 +138,8 @@ Two smaller moves ride along:
136138
- A section that reads anything must declare `snapshot()`; only the write-only `check_suite_preferences` reports `unsupported`, and the `snapshot is not implemented for this section yet` note is gone.
137139
- The organization-only sections (`teams`, `custom_properties`) are probed for the owner kind by the registry, ahead of their own plan and snapshot. The personal-account note is unchanged. A settings-file mistake in those sections (two entries naming one team) is validation's, before any request ([section 34](#34-file-only-checks-run-before-the-first-write)).
138140

141+
For `@vivswan/github-settings-as-code` consumers, a `SectionModule` typed over its literal endpoint dictionaries requires `snapshot()` when an endpoint declares a read; with the erased default, which `sectionModule()` returns, nothing is checked.
142+
139143
## 26. The snapshot file is canonical and undated
140144

141145
The file `mode: snapshot`, `gsac init`, and `snapshotRepository` write carries no timestamp, and its document renders in the one canonical order the rendered file shares, so a snapshot of an unchanged repository is byte for byte the last one and a diff between two snapshots shows only what changed on GitHub.

0 commit comments

Comments
 (0)