You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/content/reference/process-workflow-lifecycle-design.md
+12-4Lines changed: 12 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,11 +56,17 @@ The build stage stamps exactly the planned manifest version and prerelease ident
56
56
57
57
One general module release action or reusable workflow consumes enriched Settings after validation. It handles stable release, prerelease, recovery or resume, cleanup-only, and no-op actions according to the planned desired release action and flags. It verifies the artifact when an artifact is required and reconciles only the requested state. It does not recompute versioning, labels, event routing, or cleanup policy.
58
58
59
+
## Candidate stable Plan aggregation
60
+
61
+
Every stable push and recovery target uses the same aggregation rule. Plan finds the last successfully published stable version and its associated target commit, then queries merged pull requests through the requested target commit. It aggregates their release intent and uses that range for the stable version decision and release notes.
62
+
63
+
This aggregation is not limited to manual recovery. GitHub can replace an intermediate pending run when a newer run enters the same concurrency group, so the later stable target must carry forward every merged pull request since the last successful publication.
64
+
59
65
## Candidate manual recovery
60
66
61
-
A manual recovery route accepts only a selected default-branch commit. It first determines whether a stable publication already covers that commit and returns a no-op when one exists.
67
+
A manual recovery route accepts only a selected default-branch commit. It uses the stable Plan aggregation rule and returns a no-op when a stable publication already covers that commit.
62
68
63
-
For a missing publication, the route identifies the last published stable version and its associated default-branch commit. It then queries merged pull requests targeting the default branch between that publication boundary and the selected commit. The release-note reconstruction uses that ordered, de-duplicated result rather than the manual-dispatch event payload, which has no pull-request context.
69
+
For a missing publication, the release-note reconstruction uses the ordered, de-duplicated aggregated pull-request range rather than the manual-dispatch event payload, which has no pull-request context.
64
70
65
71
The recovery route validates the selected commit using the same release gates as a default-branch push. It produces a stable release only after the artifact/version boundary succeeds. This keeps recovery notes traceable even when the normal main-push run was missed or interrupted.
This is a candidate, not an approved caller contract. All pull-request events for one pull request share a group and may cancel an earlier run. Push, manual-dispatch, and scheduled events serialize by ref and never cancel; a manual dispatch or schedule therefore cannot interrupt a main release.
93
+
This is a candidate, not an approved caller contract. All pull-request events for one pull request share a group and may cancel an earlier run. Push, manual-dispatch, and scheduled events serialize by the full `github.ref` and do not cancel a running run. GitHub permits at most one running and one pending run per group, so a newer same-group event can replace an older pending run even when cancellation is disabled. A manual dispatch on `main` shares `refs/heads/main` with a push: it queues behind a running push but can replace an older pending main run.
94
+
95
+
The candidate retains full `github.ref`. `github.ref_name` neither prevents pending-run replacement nor distinguishes branches and tags with the same name.
88
96
89
97
Cancellation can leave only transient partial state. Every pull-request route, including prerelease publication and abandoned-close cleanup, resumes and reconciles on the next `synchronize`, `labeled`, `unlabeled`, or `closed` event:
90
98
@@ -121,7 +129,7 @@ The lifecycle contract is exercised with event payload fixtures and publication
121
129
| Scheduled validation | A published-version fixture that proves no release mutation is requested. |
122
130
| Pull-request convergence | Canceled prerelease-publication and cleanup fixtures followed by synchronize, label, unlabel, and close events that prove the latest pull-request state is reconciled. |
123
131
| Gallery immutability | Deterministic pull-request identity, existing-version detection, supported-unlist, and retained-version fixtures across the cancellation boundary. |
124
-
| Non-pull-request serialization | Overlapping main-push, manual-dispatch, and scheduled fixtures that prove runs queue by ref and do not cancel. |
132
+
| Stable aggregation | Bursts of main-push, manual-dispatch, and scheduled fixtures that replace an intermediate pending run and prove the later stable target aggregates all unreleased merged pull requests. |
Copy file name to clipboardExpand all lines: docs/content/reference/process-workflow-lifecycle-specification.md
+29-6Lines changed: 29 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -120,7 +120,7 @@ Scenario: Abandon a pull request with prereleases
120
120
121
121
### FR6 — Default-branch pushes MUST authorize stable publication after validation {#fr6}
122
122
123
-
A push to the default branch MUST publish a stable version only after all required build, test, quality, and publication gates succeed. When the pushed commit is the merge commit of a pull request, the stable-release decision MUST use that pull request's release intent. A successful stable release for a merged pull request MUST own promotion cleanup.
123
+
A push to the default branch MUST publish a stable version only after all required build, test, quality, and publication gates succeed. A successful stable release MUST own promotion cleanup.
124
124
125
125
#### Behavioral scenarios {#fr6-scenarios}
126
126
@@ -188,6 +188,27 @@ Scenario: Execute a planned cleanup-only action
For every stable push or recovery target, the plan MUST aggregate merged pull requests and their release intent from the last successfully published version through the target commit. The resulting stable action MUST converge correctly when GitHub replaces an intermediate pending run.
194
+
195
+
#### Behavioral scenarios {#fr10-scenarios}
196
+
197
+
```gherkin
198
+
Scenario: Publish after an intermediate pending push is replaced
199
+
Given merged pull requests exist after the last successfully published version
200
+
And an intermediate default-branch push is replaced while pending
201
+
When a later default-branch push is planned
202
+
Then the plan aggregates every merged pull request through the later target commit
203
+
And the stable release uses the aggregated release intent
204
+
205
+
Scenario: Recover a range of unreleased merged pull requests
206
+
Given merged pull requests exist after the last successfully published version
207
+
When a maintainer dispatches recovery for a later default-branch commit
208
+
Then the plan aggregates every merged pull request through that target commit
209
+
And the release notes use that aggregated range
210
+
```
211
+
191
212
## Non-functional requirements
192
213
193
214
### NFR1 — Lifecycle mutations MUST be idempotent {#nfr1}
@@ -206,7 +227,7 @@ Scenario: Retry a publication after an interrupted run
206
227
207
228
### NFR2 — Pull-request cancellation MUST preserve non-pull-request serialization {#nfr2}
208
229
209
-
All pull-request events for one pull request MUST share a cancellation scope, so a newer pull-request event cancels a superseded run. Push, manual dispatch, and scheduled runs MUST share ref-based serialization and MUST NOT cancel an in-progress run.
230
+
All pull-request events for one pull request MUST share a cancellation scope, so a newer pull-request event cancels a superseded run. Push, manual dispatch, and scheduled runs MUST share a full-ref serialization scope and MUST NOT cancel an in-progress run. Because GitHub permits at most one running and one pending run per group, a newer same-group non-pull-request run MAY replace an older pending run; the stable plan MUST therefore converge from the last successfully published version.
210
231
211
232
#### Behavioral scenarios {#nfr2-scenarios}
212
233
@@ -218,9 +239,11 @@ Scenario: Supersede a pull-request run
218
239
219
240
Scenario: Serialize non-pull-request runs
220
241
Given a default-branch release is in progress
221
-
When a manual dispatch or scheduled validation starts for the same ref
222
-
Then the later run waits for the default-branch release
223
-
And neither run cancels the other
242
+
And an earlier default-branch run is pending
243
+
When a manual dispatch or scheduled validation starts for the same full ref
244
+
Then the later run does not cancel the running release
245
+
And it may replace the older pending run
246
+
And the next stable plan aggregates the unreleased merged pull requests
224
247
```
225
248
226
249
### NFR3 — Each lifecycle outcome MUST be auditable {#nfr3}
@@ -308,7 +331,7 @@ Scenario: Recover release notes after a missed main-push publication
0 commit comments