pr-report-core 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/checks.d.mts +61 -62
  2. package/dist/checks.d.mts.map +1 -1
  3. package/dist/checks.mjs +8 -9
  4. package/dist/checks.mjs.map +1 -1
  5. package/dist/claim.d.mts +13 -14
  6. package/dist/claim.d.mts.map +1 -1
  7. package/dist/claim.mjs +0 -1
  8. package/dist/claim.mjs.map +1 -1
  9. package/dist/closing-issues.d.mts +18 -19
  10. package/dist/closing-issues.d.mts.map +1 -1
  11. package/dist/closing-issues.mjs +0 -1
  12. package/dist/closing-issues.mjs.map +1 -1
  13. package/dist/code-owners.d.mts +48 -49
  14. package/dist/code-owners.d.mts.map +1 -1
  15. package/dist/code-owners.mjs +41 -43
  16. package/dist/code-owners.mjs.map +1 -1
  17. package/dist/labels.d.mts +38 -40
  18. package/dist/labels.d.mts.map +1 -1
  19. package/dist/labels.mjs +0 -2
  20. package/dist/labels.mjs.map +1 -1
  21. package/dist/merge-after.d.mts +22 -16
  22. package/dist/merge-after.d.mts.map +1 -1
  23. package/dist/merge-after.mjs +97 -34
  24. package/dist/merge-after.mjs.map +1 -1
  25. package/dist/queue-comments.d.mts +2 -2
  26. package/dist/queue-order.d.mts +43 -30
  27. package/dist/queue-order.d.mts.map +1 -1
  28. package/dist/queue-order.mjs +33 -18
  29. package/dist/queue-order.mjs.map +1 -1
  30. package/dist/queue-owner.d.mts +30 -30
  31. package/dist/queue-owner.d.mts.map +1 -1
  32. package/dist/queue-owner.mjs +51 -51
  33. package/dist/queue-owner.mjs.map +1 -1
  34. package/dist/report.d.mts +9 -9
  35. package/dist/report.d.mts.map +1 -1
  36. package/dist/report.mjs +23 -23
  37. package/dist/report.mjs.map +1 -1
  38. package/dist/review-hold.d.mts +14 -14
  39. package/dist/ruleset.d.mts +10 -11
  40. package/dist/ruleset.d.mts.map +1 -1
  41. package/dist/ruleset.mjs +0 -1
  42. package/dist/ruleset.mjs.map +1 -1
  43. package/dist/set-aside.d.mts +28 -28
  44. package/dist/stack.d.mts +14 -15
  45. package/dist/stack.d.mts.map +1 -1
  46. package/dist/stack.mjs +0 -1
  47. package/dist/stack.mjs.map +1 -1
  48. package/dist/start-after.d.mts +20 -21
  49. package/dist/start-after.d.mts.map +1 -1
  50. package/dist/start-after.mjs +0 -1
  51. package/dist/start-after.mjs.map +1 -1
  52. package/dist/summarize.d.mts +2 -2
  53. package/dist/timestamp.d.mts +10 -10
  54. package/dist/tree.d.mts +5 -5
  55. package/dist/types.d.mts +32 -33
  56. package/dist/types.d.mts.map +1 -1
  57. package/package.json +8 -8
  58. package/src/checks.mts +74 -75
  59. package/src/checks.test.mts +30 -31
  60. package/src/claim.mts +13 -14
  61. package/src/closing-issues.mts +18 -19
  62. package/src/closing-issues.test.mts +2 -2
  63. package/src/code-owners.mts +107 -109
  64. package/src/labels.mts +38 -40
  65. package/src/merge-after.mts +164 -71
  66. package/src/merge-after.test.mts +80 -3
  67. package/src/queue-comments.mts +2 -2
  68. package/src/queue-order.mts +103 -83
  69. package/src/queue-order.test.mts +41 -4
  70. package/src/queue-owner.mts +103 -103
  71. package/src/queue-owner.test.mts +2 -2
  72. package/src/report.mts +49 -49
  73. package/src/review-hold.mts +14 -14
  74. package/src/review-hold.test.mts +3 -3
  75. package/src/ruleset.mts +10 -11
  76. package/src/set-aside.mts +28 -28
  77. package/src/stack.mts +14 -15
  78. package/src/stack.test.mts +4 -4
  79. package/src/start-after.mts +20 -21
  80. package/src/summarize.mts +2 -2
  81. package/src/timestamp.mts +14 -14
  82. package/src/tree.mts +5 -5
  83. package/src/types.mts +32 -33
package/dist/types.d.mts CHANGED
@@ -12,22 +12,21 @@ export type RepoRef = Readonly<{
12
12
  * What one context has reported on a head commit.
13
13
  *
14
14
  * `skipped` is its own state rather than a kind of `passed`. GitHub counts a
15
- * skip as met, and so does the verdict — but once the two are one word a
16
- * reader cannot tell them apart, and the aggregate that skipped may be from a
17
- * round that was superseded by one about to fail.
15
+ * skip as met, and so does the verdict — but once the two are one word a reader
16
+ * cannot tell them apart, and the aggregate that skipped may be from a round
17
+ * that was superseded by one about to fail.
18
18
  */
19
19
  export type ContextState = 'failed' | 'passed' | 'pending' | 'skipped';
20
20
  export type ChecksSummary = Readonly<{
21
21
  /**
22
- * `paused` is `skip-ci`: the gated jobs boot no runner and
23
- * `no-skip-ci-label` sits `pending` by design, so neither "pending" nor
24
- * "failing" describes it.
22
+ * `paused` is `skip-ci`: the gated jobs boot no runner and `no-skip-ci-label`
23
+ * sits `pending` by design, so neither "pending" nor "failing" describes it.
25
24
  */
26
25
  verdict: 'failing' | 'passed' | 'paused' | 'pending';
27
26
  /**
28
27
  * Every required context by what it reported. These four,
29
- * {@link ChecksSummary.missing} and {@link ChecksSummary.notRun} are
30
- * disjoint and cover the required list.
28
+ * {@link ChecksSummary.missing} and {@link ChecksSummary.notRun} are disjoint
29
+ * and cover the required list.
31
30
  */
32
31
  passed: readonly string[];
33
32
  failed: readonly string[];
@@ -41,9 +40,9 @@ export type ChecksSummary = Readonly<{
41
40
  missing: readonly string[];
42
41
  /**
43
42
  * Required contexts with nothing reported, on a pull request whose base the
44
- * ruleset does not cover — a stacked one. A workflow may run on pull
45
- * requests into `main` only, and then its contexts never come here; nothing
46
- * waits for them, since GitHub requires nothing of this base either.
43
+ * ruleset does not cover — a stacked one. A workflow may run on pull requests
44
+ * into `main` only, and then its contexts never come here; nothing waits for
45
+ * them, since GitHub requires nothing of this base either.
47
46
  */
48
47
  notRun: readonly string[];
49
48
  /** How many contexts the verdict was reached over. */
@@ -82,28 +81,28 @@ export type PullRequestFacts = Readonly<{
82
81
  labels: readonly Label[];
83
82
  /**
84
83
  * Whether auto-merge is armed. Separate from `merge-queued`, which is the
85
- * author saying a pull request is to be landed: the label is the request
86
- * and this is the mechanism, which `unblock-prs` arms when it picks the
87
- * pull request.
84
+ * author saying a pull request is to be landed: the label is the request and
85
+ * this is the mechanism, which `unblock-prs` arms when it picks the pull
86
+ * request.
88
87
  */
89
88
  autoMerge: boolean;
90
89
  headRef: string;
91
90
  headSha: string;
92
91
  baseRef: string;
93
92
  /**
94
- * Whether the head branch lives in a fork, which keeps it from being read
95
- * as the parent of a stacked pull request. See `stack.mts`.
93
+ * Whether the head branch lives in a fork, which keeps it from being read as
94
+ * the parent of a stacked pull request. See `stack.mts`.
96
95
  */
97
96
  fromFork: boolean;
98
97
  url: string;
99
98
  /**
100
- * When anything about the pull request last changed — a label, a comment,
101
- * an edit — which is why it is not {@link PullRequestFacts.headCommittedAt}.
99
+ * When anything about the pull request last changed — a label, a comment, an
100
+ * edit — which is why it is not {@link PullRequestFacts.headCommittedAt}.
102
101
  */
103
102
  updatedAt: string;
104
103
  /**
105
- * When the head commit was made, which is when the branch was last pushed
106
- * to as nearly as GitHub records it. Undefined when it could not be read.
104
+ * When the head commit was made, which is when the branch was last pushed to
105
+ * as nearly as GitHub records it. Undefined when it could not be read.
107
106
  */
108
107
  headCommittedAt: string | undefined;
109
108
  /** Undefined when the comparison could not be read. */
@@ -111,8 +110,8 @@ export type PullRequestFacts = Readonly<{
111
110
  /** What every context reported on the head commit, required or not. */
112
111
  reported: ReadonlyMap<string, ContextState>;
113
112
  /**
114
- * Whether any check run on the head commit has not finished, required or
115
- * not. See `anyRunInProgress` for why the required ones are not enough.
113
+ * Whether any check run on the head commit has not finished, required or not.
114
+ * See `anyRunInProgress` for why the required ones are not enough.
116
115
  */
117
116
  checksRunning: boolean;
118
117
  linkedIssues: readonly LinkedIssue[];
@@ -126,8 +125,8 @@ export type ReportEntry = PullRequestFacts & Readonly<{
126
125
  */
127
126
  stackedOn: number | undefined;
128
127
  /**
129
- * The open pull requests it merges after because an issue it closes
130
- * starts after them (`start-after.mts`'s `inheritStartAfter`), less what
128
+ * The open pull requests it merges after because an issue it closes starts
129
+ * after them (`start-after.mts`'s `inheritStartAfter`), less what
131
130
  * `mergeAfter` and `stackedOn` already say.
132
131
  */
133
132
  inheritedMergeAfter: readonly number[];
@@ -146,9 +145,9 @@ export type ReportEntry = PullRequestFacts & Readonly<{
146
145
  }>;
147
146
  /**
148
147
  * One pull request in the merge order. `repeated` marks the second and later
149
- * appearances of a pull request with more than one predecessor — declared,
150
- * or the one it is stacked on: it is drawn under each of them, but expanded
151
- * under the first only.
148
+ * appearances of a pull request with more than one predecessor — declared, or
149
+ * the one it is stacked on: it is drawn under each of them, but expanded under
150
+ * the first only.
152
151
  */
153
152
  export type TreeNode = Readonly<{
154
153
  number: number;
@@ -158,8 +157,8 @@ export type TreeNode = Readonly<{
158
157
  /**
159
158
  * One pull request that has already landed, for the section that says what
160
159
  * shipped. Nothing that is true of an open pull request — a merge order, a
161
- * check verdict, a distance from its base — is true of one that has merged,
162
- * so it is its own shape rather than an entry with the fields blanked.
160
+ * check verdict, a distance from its base — is true of one that has merged, so
161
+ * it is its own shape rather than an entry with the fields blanked.
163
162
  */
164
163
  export type MergedPullRequest = Readonly<{
165
164
  number: number;
@@ -193,8 +192,8 @@ export type OpenIssue = Readonly<{
193
192
  */
194
193
  startAfter: readonly number[];
195
194
  /**
196
- * What a `Merge-After:` in its body names. That line is not read on an
197
- * issue, and is shown as a slip to fix: `Start-After:` is the issue's.
195
+ * What a `Merge-After:` in its body names. That line is not read on an issue,
196
+ * and is shown as a slip to fix: `Start-After:` is the issue's.
198
197
  */
199
198
  misplacedMergeAfter: readonly number[];
200
199
  }>;
@@ -215,8 +214,8 @@ export type IssueDeclarations = Readonly<{
215
214
  /** Each issue's `Start-After:`; an issue not in it declares nothing. */
216
215
  startAfter: ReadonlyMap<number, readonly number[]>;
217
216
  /**
218
- * The numbers known to be open issues, beyond the ones an open pull
219
- * request links as open. Decides only what is said not to be started.
217
+ * The numbers known to be open issues, beyond the ones an open pull request
218
+ * links as open. Decides only what is said not to be started.
220
219
  */
221
220
  open: ReadonlySet<number>;
222
221
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.mts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE1E;;;GAGG;AAEH,wCAAwC;AACxC,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEhE;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvE,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC;IACnC;;;;OAIG;IACH,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrD;;;;OAIG;IACH,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;;OAKG;IACH,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEzE,oEAAoE;AACpE,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,uDAAuD;IACvD,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,uEAAuE;IACvE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC5C;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;CACtC,CAAC,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,gBAAgB,GACxC,QAAQ,CAAC;IACP,uEAAuE;IACvE,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;;;OAIG;IACH,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;OAIG;IACH,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC,CAAC;AAEL;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC/B,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,0EAA0E;IAC1E,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;CACtC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,SAAS,GACjC,QAAQ,CAAC;IACP,KAAK,EAAE,eAAe,CAAC;IACvB,0EAA0E;IAC1E,KAAK,EAAE,SAAS,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,CAAC,EAAE,CAAC;CACzE,CAAC,CAAC;AAEL;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,wEAAwE;IACxE,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IACnD;;;OAGG;IACH,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC3B,CAAC,CAAC;AAEH,sCAAsC;AACtC,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,oDAAoD;IACpD,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC;;;OAGG;IACH,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACvC,qEAAqE;IACrE,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrC,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-report-core",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "What a GitHub merge queue driven by labels and `Merge-After:` trailers decides about the open pull requests — verdicts, merge order, stacks, owners — with no I/O, shared by the GitHub Pull Requests Manager page and the unblock-prs worker",
6
6
  "keywords": [
@@ -39,8 +39,8 @@
39
39
  "LICENSE"
40
40
  ],
41
41
  "dependencies": {
42
- "ts-data-forge": "^14.10.0",
43
- "ts-fortress": "^12.4.1"
42
+ "ts-data-forge": "^14.11.0",
43
+ "ts-fortress": "^12.4.3"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@octokit/openapi-types": "^29.0.1",
@@ -49,16 +49,16 @@
49
49
  "cspell": "10.4.0",
50
50
  "dedent": "1.7.2",
51
51
  "eslint": "10.13.0",
52
- "eslint-config-typed": "7.1.0",
53
- "eslint-plugin-ts-data-forge": "0.10.5",
54
- "eslint-plugin-ts-fortress": "1.3.10",
55
- "eslint-plugin-ts-type-forge": "0.8.15",
52
+ "eslint-config-typed": "7.4.0",
53
+ "eslint-plugin-ts-data-forge": "0.10.9",
54
+ "eslint-plugin-ts-fortress": "1.3.13",
55
+ "eslint-plugin-ts-type-forge": "0.8.18",
56
56
  "jiti": "2.7.0",
57
57
  "npm-run-all2": "9.0.4",
58
58
  "prettier": "3.9.10",
59
59
  "prettier-plugin-organize-imports": "4.3.0",
60
60
  "prettier-plugin-packagejson": "3.0.2",
61
- "ts-repo-utils": "10.7.1",
61
+ "ts-repo-utils": "10.7.2",
62
62
  "tsx": "4.23.15",
63
63
  "typescript": "6.0.3",
64
64
  "typescript-native": "npm:typescript@7.0.2",
package/src/checks.mts CHANGED
@@ -6,36 +6,36 @@ import type { ChecksSummary, ContextState } from './types.mjs';
6
6
  /**
7
7
  * What every context reported, from a head commit's check runs.
8
8
  *
9
- * A name appears more than once whenever two check suites reported it, and on
10
- * a queued pull request that is the normal case rather than the odd one: the
11
- * run the `opened` event starts is cancelled by the `labeled` event's, and
12
- * both stay on the commit — the cancelled one leaving its `*-result`
13
- * aggregate concluded `failure`, because an `if: always()` job that asserts
14
- * on cancelled `needs` fails.
9
+ * A name appears more than once whenever two check suites reported it, and on a
10
+ * queued pull request that is the normal case rather than the odd one: the run
11
+ * the `opened` event starts is cancelled by the `labeled` event's, and both
12
+ * stay on the commit — the cancelled one leaving its `*-result` aggregate
13
+ * concluded `failure`, because an `if: always()` job that asserts on cancelled
14
+ * `needs` fails.
15
15
  *
16
- * **The newest check suite wins, and that is not the same as the newest
17
- * run.** GitHub resolves a required context to the run in the suite with the
18
- * greatest id, so where the cancelled suite happens to have been created
19
- * after the one that superseded it, the stale red is what holds the merge —
20
- * however much later the green one finished. Every suite of one push is
21
- * created in the same second, so which of them got the higher id is not
22
- * something the repository decides.
16
+ * **The newest check suite wins, and that is not the same as the newest run.**
17
+ * GitHub resolves a required context to the run in the suite with the greatest
18
+ * id, so where the cancelled suite happens to have been created after the one
19
+ * that superseded it, the stale red is what holds the merge — however much
20
+ * later the green one finished. Every suite of one push is created in the same
21
+ * second, so which of them got the higher id is not something the repository
22
+ * decides.
23
23
  *
24
24
  * This is why the rule is not "the newest `started_at`", which reads more
25
25
  * natural and would call such a pull request green while GitHub blocks it.
26
- * A report that says a blocked pull request will merge is worse than one
27
- * that says a green one will not: `CLAUDE.md`'s "Commits and pull requests"
28
- * says to ignore the red the cancelled run leaves, and this is the case where
26
+ * A report that says a blocked pull request will merge is worse than one that
27
+ * says a green one will not: `CLAUDE.md`'s "Commits and pull requests" says to
28
+ * ignore the red the cancelled run leaves, and this is the case where
29
29
  * GitHub does not.
30
30
  *
31
31
  * **A run whose workflow has a newer round still going is pending.** An
32
- * aggregate has no run in a round until the jobs it waits on are done, so
33
- * until then the only run of its name is the previous round's — on a pull
34
- * request whose label events started two rounds, the red the second left on
35
- * the first (#2191). That run is what GitHub shows, but not what it will
36
- * answer with: the newer round is in the suite with the greater id, and its
37
- * aggregate will be the newest run of the name. Where the newer round has
38
- * finished without one, the older run stands, as it does on GitHub.
32
+ * aggregate has no run in a round until the jobs it waits on are done, so until
33
+ * then the only run of its name is the previous round's — on a pull request
34
+ * whose label events started two rounds, the red the second left on the first
35
+ * (#2191). That run is what GitHub shows, but not what it will answer with: the
36
+ * newer round is in the suite with the greater id, and its aggregate will be
37
+ * the newest run of the name. Where the newer round has finished without one,
38
+ * the older run stands, as it does on GitHub.
39
39
  */
40
40
  export const statesFromCheckRuns = (
41
41
  runs: readonly CheckRunReport[],
@@ -101,9 +101,9 @@ export type CheckRunReport = Readonly<{
101
101
  /**
102
102
  * The workflow run its suite is, where it is one: the workflow, so that a
103
103
  * newer round of it can be told from an unrelated suite, and whether the
104
- * round has finished, which its runs alone do not say — an aggregate's run
105
- * is created only once every job before it has completed. `undefined` for
106
- * a run no workflow made, or where the workflow runs could not be read.
104
+ * round has finished, which its runs alone do not say — an aggregate's run is
105
+ * created only once every job before it has completed. `undefined` for a run
106
+ * no workflow made, or where the workflow runs could not be read.
107
107
  */
108
108
  round: Readonly<{ workflowId: number; completed: boolean }> | undefined;
109
109
  }>;
@@ -114,12 +114,12 @@ export type CheckRunReport = Readonly<{
114
114
  * A run that has not completed is pending whatever it concluded last — the
115
115
  * conclusion of a re-run is the previous verdict until the new one finishes.
116
116
  * A `skipped` conclusion is reported as `skipped` and counted as met by
117
- * {@link summarizeChecks}, because GitHub counts it as met: the gated jobs
118
- * skip on `skip-ci` and on a diff the workflow does not read, and reading
119
- * that as a failure would call every gated pull request red.
117
+ * {@link summarizeChecks}, because GitHub counts it as met: the gated jobs skip
118
+ * on `skip-ci` and on a diff the workflow does not read, and reading that as a
119
+ * failure would call every gated pull request red.
120
120
  * Everything else that finished — `cancelled`, `stale`, `timed_out`,
121
- * `action_required` — is something a reader has to act on, so it is a
122
- * failure here even where GitHub is vaguer about it.
121
+ * `action_required` — is something a reader has to act on, so it is a failure
122
+ * here even where GitHub is vaguer about it.
123
123
  */
124
124
  export const classifyCheckRun = (
125
125
  status: string,
@@ -141,12 +141,12 @@ const PASSING_CONCLUSIONS: ReadonlySet<string> = new Set<string>([
141
141
  /**
142
142
  * Whether any run on the head commit has not finished, or any round has not.
143
143
  *
144
- * Every run, not only the required ones: the aggregates are `if: always()`
145
- * and have no run in the newest round until the jobs they wait on are done,
146
- * so "every required context has reported" is true of a commit halfway
147
- * through a round — with the reports coming from the round before. And the
148
- * round, not only its runs: between the last job finishing and the aggregate
149
- * being created, every run there is has completed.
144
+ * Every run, not only the required ones: the aggregates are `if: always()` and
145
+ * have no run in the newest round until the jobs they wait on are done, so
146
+ * "every required context has reported" is true of a commit halfway through a
147
+ * round — with the reports coming from the round before. And the round, not
148
+ * only its runs: between the last job finishing and the aggregate being
149
+ * created, every run there is has completed.
150
150
  */
151
151
  export const anyRunInProgress = (runs: readonly CheckRunReport[]): boolean =>
152
152
  runs.some(
@@ -154,20 +154,10 @@ export const anyRunInProgress = (runs: readonly CheckRunReport[]): boolean =>
154
154
  );
155
155
 
156
156
  /**
157
- * Which of two runs of one name GitHub would answer with: the one in the
158
- * later-created suite, and within one suite the later run of it — a re-run
159
- * keeps the suite and takes a new run id.
160
- */
161
- const outranks = (run: CheckRunReport, previous: CheckRunReport): boolean =>
162
- run.checkSuiteId === previous.checkSuiteId
163
- ? run.id > previous.id
164
- : run.checkSuiteId > previous.checkSuiteId;
165
-
166
- /**
167
- * What every context has reported on one commit, from both places GitHub
168
- * keeps them. The aggregate jobs are check runs; `no-skip-ci-label` is a
169
- * commit status, so reading only the first would report the context that
170
- * holds every labelled pull request as missing.
157
+ * What every context has reported on one commit, from both places GitHub keeps
158
+ * them. The aggregate jobs are check runs; `no-skip-ci-label` is a commit
159
+ * status, so reading only the first would report the context that holds every
160
+ * labelled pull request as missing.
171
161
  *
172
162
  * `state` is a commit status's as the REST API spells it, in lower case.
173
163
  */
@@ -175,9 +165,9 @@ export const reportedContexts = (
175
165
  runs: readonly CheckRunReport[],
176
166
  statuses: readonly Readonly<{ context: string; state: string }>[],
177
167
  ): ReadonlyMap<string, ContextState> => {
178
- // A commit status and a check run of the same name are two requirements,
179
- // not one reported twice: GitHub asks both to pass. So the stricter of
180
- // the two is kept rather than whichever was read second.
168
+ // A commit status and a check run of the same name are two requirements, not
169
+ // one reported twice: GitHub asks both to pass. So the stricter of the two is
170
+ // kept rather than whichever was read second.
181
171
  const mut_states = new Map<string, ContextState>(statesFromCheckRuns(runs));
182
172
 
183
173
  for (const { context, state } of statuses) {
@@ -199,12 +189,11 @@ export const reportedContexts = (
199
189
  /**
200
190
  * What a context reported that is both a check run and a commit status.
201
191
  *
202
- * Not "the status wins", which is what this used to assume. GitHub's own
203
- * answer is that neither does: "If a check and a commit status have the same
204
- * name, both must pass when that name is required." So the stricter of the
205
- * two is the verdict, and a green status cannot cover a red check run of the
206
- * same name. A skip beside a pass is a skip: both are met, but only one of
207
- * them ran.
192
+ * Not "the status wins", which is what this used to assume. GitHub's own answer
193
+ * is that neither does: "If a check and a commit status have the same name,
194
+ * both must pass when that name is required." So the stricter of the two is the
195
+ * verdict, and a green status cannot cover a red check run of the same name. A
196
+ * skip beside a pass is a skip: both are met, but only one of them ran.
208
197
  */
209
198
  export const combineContextStates = (
210
199
  a: ContextState,
@@ -220,8 +209,8 @@ export const combineContextStates = (
220
209
 
221
210
  /**
222
211
  * What one commit status has reported. `no-skip-ci-label` is one of these
223
- * rather than a check run, so a report that read only check runs would call
224
- * the context that holds every labelled pull request "missing".
212
+ * rather than a check run, so a report that read only check runs would call the
213
+ * context that holds every labelled pull request "missing".
225
214
  */
226
215
  export const classifyCommitStatus = (state: string): ContextState => {
227
216
  switch (state) {
@@ -241,24 +230,24 @@ export const classifyCommitStatus = (state: string): ContextState => {
241
230
  * requires and no others: a failing job nothing requires does not block a
242
231
  * merge, and listing it would bury the one that does.
243
232
  *
244
- * `paused` outranks the rest. While `skip-ci` is on, the checks a reader
245
- * sees are whatever survived from before the label went on — typically the
246
- * red left by the `opened` run that the `labeled` run cancelled. Calling
247
- * that "failing" would make every queued pull request look broken; the
248
- * failures are still listed, because they are what a reader asks about.
233
+ * `paused` outranks the rest. While `skip-ci` is on, the checks a reader sees
234
+ * are whatever survived from before the label went on — typically the red left
235
+ * by the `opened` run that the `labeled` run cancelled. Calling that "failing"
236
+ * would make every queued pull request look broken; the failures are still
237
+ * listed, because they are what a reader asks about.
249
238
  *
250
239
  * `running` is the third thing that makes a verdict provisional, beside a
251
- * required context that is pending and one that has not reported. Without it
252
- * a commit mid-round reads as settled out of the round before — which is how
253
- * a failing pull request (#2031) came to show a tick.
240
+ * required context that is pending and one that has not reported. Without it a
241
+ * commit mid-round reads as settled out of the round before — which is how a
242
+ * failing pull request (#2031) came to show a tick.
254
243
  *
255
244
  * **Off the covered base, a context that never reported is not awaited.**
256
245
  * The contexts are the ones the ruleset asks of `main`, and a workflow that
257
- * runs only on pull requests into `main` never reports on a stacked one —
258
- * which kept #2103, every check of it green, "running" until it was moved
259
- * onto `main`. Such a context is {@link ChecksSummary.notRun} instead, but
260
- * only once some required context has reported: before the first check
261
- * suite, nothing having come is not a pass over zero contexts.
246
+ * runs only on pull requests into `main` never reports on a stacked one — which
247
+ * kept #2103, every check of it green, "running" until it was moved onto
248
+ * `main`. Such a context is {@link ChecksSummary.notRun} instead, but only once
249
+ * some required context has reported: before the first check suite, nothing
250
+ * having come is not a pass over zero contexts.
262
251
  */
263
252
  export const summarizeChecks = ({
264
253
  required,
@@ -308,3 +297,13 @@ export const summarizeChecks = ({
308
297
  required: required.length,
309
298
  };
310
299
  };
300
+
301
+ /**
302
+ * Which of two runs of one name GitHub would answer with: the one in the
303
+ * later-created suite, and within one suite the later run of it — a re-run
304
+ * keeps the suite and takes a new run id.
305
+ */
306
+ const outranks = (run: CheckRunReport, previous: CheckRunReport): boolean =>
307
+ run.checkSuiteId === previous.checkSuiteId
308
+ ? run.id > previous.id
309
+ : run.checkSuiteId > previous.checkSuiteId;
@@ -17,11 +17,11 @@ describe(classifyCheckRun, () => {
17
17
  assert.strictEqual(classifyCheckRun('in_progress', 'failure'), 'pending');
18
18
  });
19
19
 
20
- // The gated jobs skip on `skip-ci` and on a diff the workflow does not
21
- // read; GitHub counts that as met, so reading it as a failure would call
22
- // every gated pull request red. `summarizeChecks` still counts it as met —
23
- // but it is reported as what it was, because folding it into `passed` is
24
- // what let a failing pull request show a tick.
20
+ // The gated jobs skip on `skip-ci` and on a diff the workflow does not read;
21
+ // GitHub counts that as met, so reading it as a failure would call every
22
+ // gated pull request red. `summarizeChecks` still counts it as met — but it
23
+ // is reported as what it was, because folding it into `passed` is what let a
24
+ // failing pull request show a tick.
25
25
  test('a skipped job is reported as skipped, not as passed', () => {
26
26
  assert.strictEqual(classifyCheckRun('completed', 'skipped'), 'skipped');
27
27
 
@@ -114,10 +114,9 @@ describe(summarizeChecks, () => {
114
114
 
115
115
  test('`skip-ci` is a pause, and the detail is still reported', () => {
116
116
  // While the label is on, the gated jobs boot no runner and
117
- // `no-skip-ci-label` sits `pending` by design. Calling that "failing"
118
- // would make every queued pull request look broken; the red left by the
119
- // cancelled `opened` run is still listed, because it is what a reader
120
- // asks about.
117
+ // `no-skip-ci-label` sits `pending` by design. Calling that "failing" would
118
+ // make every queued pull request look broken; the red left by the cancelled
119
+ // `opened` run is still listed, because it is what a reader asks about.
121
120
  const summary = summarizeChecks({
122
121
  required,
123
122
  reported: new Map<string, ContextState>([
@@ -207,9 +206,9 @@ describe(summarizeChecks, () => {
207
206
  });
208
207
 
209
208
  // #2103, stacked on `chore/pnpm-update`: `lint-pull-request.yml` runs on
210
- // pull requests into `main` only, so its three contexts never came, and
211
- // the page kept calling a pull request whose checks had all passed
212
- // "checks running".
209
+ // pull requests into `main` only, so its three contexts never came, and the
210
+ // page kept calling a pull request whose checks had all passed "checks
211
+ // running".
213
212
  describe('on a base the ruleset does not cover', () => {
214
213
  const withLint = Arr.toPushed(required, 'Validate PR title');
215
214
 
@@ -235,8 +234,8 @@ describe(summarizeChecks, () => {
235
234
  });
236
235
 
237
236
  test('while nothing required has reported, everything is still coming', () => {
238
- // Between a push and the first check suite, a head commit has nothing
239
- // on it at all; that is not a pass over zero contexts.
237
+ // Between a push and the first check suite, a head commit has nothing on
238
+ // it at all; that is not a pass over zero contexts.
240
239
  const summary = summarizeChecks({
241
240
  required: withLint,
242
241
  reported: new Map<string, ContextState>(),
@@ -331,8 +330,8 @@ describe(statesFromCheckRuns, () => {
331
330
  // `test-node-versions-result`, the one context of the five that blocked
332
331
  // #2021: the cancelled suite happens to have the greater id, so GitHub
333
332
  // reports the failure however much later the green one finished. Reading
334
- // the newest `started_at` instead would call this pull request green
335
- // while GitHub blocks it.
333
+ // the newest `started_at` instead would call this pull request green while
334
+ // GitHub blocks it.
336
335
  const states = statesFromCheckRuns([
337
336
  run(
338
337
  'test-node-versions-result / result',
@@ -496,11 +495,11 @@ describe(anyRunInProgress, () => {
496
495
  * The state #2031 was in when the page showed it a tick.
497
496
  *
498
497
  * `skip-ci` came off, which started a new round. The old round's
499
- * `code-check-result` had concluded `skipped` and was the only run of that
500
- * name on the commit — the new round's aggregate does not exist until the
501
- * jobs it waits on are done. Folding `skipped` into `passed` then made the
502
- * pull request look settled and green, two minutes before
503
- * `code-check-result` concluded `failure`.
498
+ * `code-check-result` had concluded `skipped` and was the only run of that name
499
+ * on the commit — the new round's aggregate does not exist until the jobs it
500
+ * waits on are done. Folding `skipped` into `passed` then made the pull request
501
+ * look settled and green, two minutes before `code-check-result` concluded
502
+ * `failure`.
504
503
  */
505
504
  describe('a required context in a superseded round', () => {
506
505
  const required = [
@@ -607,9 +606,9 @@ describe('a required context in a superseded round', () => {
607
606
  * `skip-ci` came off, which started a round, and `merge-queued` went on a
608
607
  * minute later, which started another and cancelled the first — whose
609
608
  * `*-result` aggregates, `if: always()` over cancelled `needs`, concluded
610
- * `failure`. The newer round was still at its matrix, so its aggregates did
611
- * not exist yet, and the red of the cancelled one was the only run of each
612
- * name on the commit.
609
+ * `failure`. The newer round was still at its matrix, so its aggregates did not
610
+ * exist yet, and the red of the cancelled one was the only run of each name on
611
+ * the commit.
613
612
  */
614
613
  describe('a required context whose workflow has a newer round running', () => {
615
614
  const codeCheck = 359_266_435;
@@ -659,8 +658,8 @@ describe('a required context whose workflow has a newer round running', () => {
659
658
  conclusion: undefined,
660
659
  round: { workflowId: codeCheck, completed: false },
661
660
  },
662
- // Style Check has finished every job it has created, but the round is
663
- // not over: its aggregate is created only after that.
661
+ // Style Check has finished every job it has created, but the round is not
662
+ // over: its aggregate is created only after that.
664
663
  {
665
664
  id: 114_375_644_790,
666
665
  checkSuiteId: 103_247_840_622,
@@ -719,8 +718,8 @@ describe('a required context whose workflow has a newer round running', () => {
719
718
  });
720
719
 
721
720
  // The rule is not "an older round never counts": where the newer round
722
- // finished without a run of that name, GitHub answers with the older run,
723
- // and so does this.
721
+ // finished without a run of that name, GitHub answers with the older run, and
722
+ // so does this.
724
723
  test('a finished round that never ran the job does not hide the older run', () => {
725
724
  const states = statesFromCheckRuns([
726
725
  runs[0],
@@ -737,9 +736,9 @@ describe('a required context whose workflow has a newer round running', () => {
737
736
  assert.strictEqual(states.get('code-check-result / result'), 'failed');
738
737
  });
739
738
 
740
- // Nor "the round still running wins": GitHub resolves a context to the
741
- // suite with the greatest id, and where the cancelled one has it, its red
742
- // holds the merge however the other round goes.
739
+ // Nor "the round still running wins": GitHub resolves a context to the suite
740
+ // with the greatest id, and where the cancelled one has it, its red holds the
741
+ // merge however the other round goes.
743
742
  test('a cancelled round with the greater id still holds the merge', () => {
744
743
  const states = statesFromCheckRuns([
745
744
  {
package/src/claim.mts CHANGED
@@ -4,25 +4,24 @@
4
4
  *
5
5
  * `unblock-prs` leaves a set-aside pull request alone until its head moves —
6
6
  * or, for every reason but `checks-failed` and `awaiting-bypass`, until the
7
- * base does, when it tries the rebase again. A session fixing that pull
8
- * request is then racing the script, and a second session, or the one that
9
- * opened the pull request and is woken by the set-aside comment, may be
10
- * fixing the same failure. The leases on every push keep any of them from
11
- * overwriting another's work, but not from doing it twice. So whoever starts
12
- * on one says so first in a comment whose first line is a hidden record this
13
- * module writes and reads, and everyone else — the script included — leaves
14
- * that pull request to it.
7
+ * base does, when it tries the rebase again. A session fixing that pull request
8
+ * is then racing the script, and a second session, or the one that opened the
9
+ * pull request and is woken by the set-aside comment, may be fixing the same
10
+ * failure. The leases on every push keep any of them from overwriting another's
11
+ * work, but not from doing it twice. So whoever starts on one says so first in
12
+ * a comment whose first line is a hidden record this module writes and reads,
13
+ * and everyone else — the script included — leaves that pull request to it.
15
14
  *
16
15
  * **It lasts while the head is the one it claimed**, and for at most
17
16
  * {@link CLAIM_LIFETIME_MINUTES}. The push that carries the fix moves the head
18
- * and so ends the claim with nothing left to clean up; that push is what
19
- * hands the pull request back to the script, as it always was. The lifetime is
20
- * for a claimant that stopped without pushing. A claimant that needs longer
21
- * writes the claim again.
17
+ * and so ends the claim with nothing left to clean up; that push is what hands
18
+ * the pull request back to the script, as it always was. The lifetime is for a
19
+ * claimant that stopped without pushing. A claimant that needs longer writes
20
+ * the claim again.
22
21
  *
23
22
  * **One comment per pull request, edited in place**, like the set-aside one;
24
- * a claim that has ended is simply written over. Of several, the oldest is
25
- * the one, so two claimants writing at once both read back the same answer.
23
+ * a claim that has ended is simply written over. Of several, the oldest is the
24
+ * one, so two claimants writing at once both read back the same answer.
26
25
  *
27
26
  * **Only the comments the reader's own account wrote count**, as for the
28
27
  * set-aside comment (`set-aside.mts`): the repository is public. `by` is what