pr-report-core 0.2.0 → 0.3.0

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 (107) hide show
  1. package/README.md +5 -2
  2. package/dist/branch-rules.d.mts +30 -0
  3. package/dist/branch-rules.d.mts.map +1 -0
  4. package/dist/branch-rules.mjs +71 -0
  5. package/dist/branch-rules.mjs.map +1 -0
  6. package/dist/checks.d.mts +61 -62
  7. package/dist/checks.d.mts.map +1 -1
  8. package/dist/checks.mjs +0 -1
  9. package/dist/checks.mjs.map +1 -1
  10. package/dist/claim.d.mts +21 -15
  11. package/dist/claim.d.mts.map +1 -1
  12. package/dist/claim.mjs +1 -1
  13. package/dist/claim.mjs.map +1 -1
  14. package/dist/closing-issues.d.mts +18 -19
  15. package/dist/closing-issues.d.mts.map +1 -1
  16. package/dist/closing-issues.mjs +0 -1
  17. package/dist/closing-issues.mjs.map +1 -1
  18. package/dist/code-owners.d.mts +33 -34
  19. package/dist/code-owners.d.mts.map +1 -1
  20. package/dist/code-owners.mjs +0 -2
  21. package/dist/code-owners.mjs.map +1 -1
  22. package/dist/index.d.mts +3 -0
  23. package/dist/index.d.mts.map +1 -1
  24. package/dist/index.mjs +3 -0
  25. package/dist/index.mjs.map +1 -1
  26. package/dist/issue-claim.d.mts +56 -0
  27. package/dist/issue-claim.d.mts.map +1 -0
  28. package/dist/issue-claim.mjs +87 -0
  29. package/dist/issue-claim.mjs.map +1 -0
  30. package/dist/issue-priority.d.mts +44 -0
  31. package/dist/issue-priority.d.mts.map +1 -0
  32. package/dist/issue-priority.mjs +91 -0
  33. package/dist/issue-priority.mjs.map +1 -0
  34. package/dist/labels.d.mts +43 -42
  35. package/dist/labels.d.mts.map +1 -1
  36. package/dist/labels.mjs +2 -1
  37. package/dist/labels.mjs.map +1 -1
  38. package/dist/merge-after.d.mts +22 -16
  39. package/dist/merge-after.d.mts.map +1 -1
  40. package/dist/merge-after.mjs +87 -24
  41. package/dist/merge-after.mjs.map +1 -1
  42. package/dist/queue-comments.d.mts +2 -2
  43. package/dist/queue-order.d.mts +32 -32
  44. package/dist/queue-order.mjs +0 -2
  45. package/dist/queue-order.mjs.map +1 -1
  46. package/dist/queue-owner.d.mts +14 -14
  47. package/dist/queue-owner.d.mts.map +1 -1
  48. package/dist/queue-owner.mjs +18 -0
  49. package/dist/queue-owner.mjs.map +1 -1
  50. package/dist/report.d.mts +4 -4
  51. package/dist/review-hold.d.mts +14 -14
  52. package/dist/ruleset.d.mts +12 -13
  53. package/dist/ruleset.d.mts.map +1 -1
  54. package/dist/ruleset.mjs +0 -1
  55. package/dist/ruleset.mjs.map +1 -1
  56. package/dist/set-aside.d.mts +29 -28
  57. package/dist/set-aside.d.mts.map +1 -1
  58. package/dist/set-aside.mjs +2 -0
  59. package/dist/set-aside.mjs.map +1 -1
  60. package/dist/stack.d.mts +14 -15
  61. package/dist/stack.d.mts.map +1 -1
  62. package/dist/stack.mjs +0 -1
  63. package/dist/stack.mjs.map +1 -1
  64. package/dist/start-after.d.mts +20 -21
  65. package/dist/start-after.d.mts.map +1 -1
  66. package/dist/start-after.mjs +0 -1
  67. package/dist/start-after.mjs.map +1 -1
  68. package/dist/summarize.d.mts +2 -2
  69. package/dist/timestamp.d.mts +10 -10
  70. package/dist/tree.d.mts +5 -5
  71. package/dist/types.d.mts +32 -33
  72. package/dist/types.d.mts.map +1 -1
  73. package/package.json +10 -10
  74. package/src/branch-rules.mts +105 -0
  75. package/src/branch-rules.test.mts +221 -0
  76. package/src/checks.mts +64 -65
  77. package/src/checks.test.mts +30 -31
  78. package/src/claim.mts +16 -16
  79. package/src/closing-issues.mts +18 -19
  80. package/src/closing-issues.test.mts +2 -2
  81. package/src/code-owners.mts +39 -41
  82. package/src/index.mts +3 -0
  83. package/src/issue-claim.mts +138 -0
  84. package/src/issue-claim.test.mts +149 -0
  85. package/src/issue-priority.mts +116 -0
  86. package/src/issue-priority.test.mts +71 -0
  87. package/src/labels.mts +43 -42
  88. package/src/merge-after.mts +142 -49
  89. package/src/merge-after.test.mts +80 -3
  90. package/src/queue-comments.mts +2 -2
  91. package/src/queue-order.mts +60 -62
  92. package/src/queue-order.test.mts +6 -6
  93. package/src/queue-owner.mts +46 -25
  94. package/src/queue-owner.test.mts +4 -2
  95. package/src/report.mts +9 -9
  96. package/src/review-hold.mts +14 -14
  97. package/src/review-hold.test.mts +3 -3
  98. package/src/ruleset.mts +12 -13
  99. package/src/set-aside.mts +30 -28
  100. package/src/set-aside.test.mts +22 -0
  101. package/src/stack.mts +14 -15
  102. package/src/stack.test.mts +4 -4
  103. package/src/start-after.mts +20 -21
  104. package/src/summarize.mts +2 -2
  105. package/src/timestamp.mts +14 -14
  106. package/src/tree.mts +5 -5
  107. package/src/types.mts +32 -33
@@ -82,9 +82,9 @@ export const progressOf = (
82
82
  : 'none';
83
83
 
84
84
  /**
85
- * Whether `labels` holds `name`, whatever its case. GitHub's label names
86
- * are: adding `in-progress` to a repository that has `In-Progress` puts that
87
- * one on, so an exact match would not see the label it just added.
85
+ * Whether `labels` holds `name`, whatever its case. GitHub's label names are:
86
+ * adding `in-progress` to a repository that has `In-Progress` puts that one on,
87
+ * so an exact match would not see the label it just added.
88
88
  */
89
89
  export const hasLabel = (
90
90
  labels: readonly Readonly<{ name: string }>[],
@@ -114,9 +114,9 @@ export const issuesInProgress = (
114
114
  );
115
115
 
116
116
  /**
117
- * What GitHub says about a numbered item, in the terms both of its APIs
118
- * share once lower-cased: GraphQL's `CLOSED` / `NOT_PLANNED` are REST's
119
- * `closed` / `not_planned`.
117
+ * What GitHub says about a numbered item, in the terms both of its APIs share
118
+ * once lower-cased: GraphQL's `CLOSED` / `NOT_PLANNED` are REST's `closed` /
119
+ * `not_planned`.
120
120
  */
121
121
  export type ReferencedFacts = Readonly<
122
122
  | {
@@ -129,9 +129,8 @@ export type ReferencedFacts = Readonly<
129
129
  >;
130
130
 
131
131
  /**
132
- * Where one named item stands. An issue closed with no reason recorded is
133
- * taken as completed, which was the only way to close one before reasons
134
- * existed.
132
+ * Where one named item stands. An issue closed with no reason recorded is taken
133
+ * as completed, which was the only way to close one before reasons existed.
135
134
  */
136
135
  export const referenceStatusOf = (facts: ReferencedFacts): ReferenceStatus => {
137
136
  if (facts.state.toLowerCase() === 'open') {
@@ -152,9 +151,9 @@ export const referenceStatusOf = (facts: ReferencedFacts): ReferenceStatus => {
152
151
  *
153
152
  * `statusOf` says where each named number stands; the open issues among
154
153
  * `issues` are `waiting` whatever it says, so a caller need only know about
155
- * what is not in the list. Cycles are found among the declarations of
156
- * `issues` alone: a pull request declares no `Start-After:`, and the body of
157
- * an issue that is not listed was not read.
154
+ * what is not in the list. Cycles are found among the declarations of `issues`
155
+ * alone: a pull request declares no `Start-After:`, and the body of an issue
156
+ * that is not listed was not read.
158
157
  *
159
158
  * Nothing is transitive: an issue that names an open one is blocked whatever
160
159
  * that one is waiting for in turn.
@@ -202,15 +201,15 @@ export const decideStartStates = (
202
201
  */
203
202
  export type InheritedOrder = Readonly<{
204
203
  /**
205
- * The open pull requests it merges after because of them, as if its body
206
- * had declared them: one an issue names, or one closing an open issue an
207
- * issue names. Lowest number first, and never itself.
204
+ * The open pull requests it merges after because of them, as if its body had
205
+ * declared them: one an issue names, or one closing an open issue an issue
206
+ * names. Lowest number first, and never itself.
208
207
  */
209
208
  mergeAfter: readonly number[];
210
209
  /**
211
- * The open issues named that no open pull request closes. They hold
212
- * nothing — waiting on work nobody has started could hold the merge for
213
- * ever — but they are not done, and a reader is told so. Lowest first.
210
+ * The open issues named that no open pull request closes. They hold nothing —
211
+ * waiting on work nobody has started could hold the merge for ever — but they
212
+ * are not done, and a reader is told so. Lowest first.
214
213
  */
215
214
  notStarted: readonly number[];
216
215
  }>;
@@ -219,9 +218,9 @@ export type InheritedOrder = Readonly<{
219
218
  * Each open pull request's {@link InheritedOrder}, keyed by its number.
220
219
  *
221
220
  * `closes` is the open issues each closes, by closing keyword or by GitHub's
222
- * own link; `startAfterOf` what each issue whose body was read declares, and
223
- * an issue missing from it declares nothing. `openIssues` is what is known to
224
- * be an open issue, which only decides what is reported as
221
+ * own link; `startAfterOf` what each issue whose body was read declares, and an
222
+ * issue missing from it declares nothing. `openIssues` is what is known to be
223
+ * an open issue, which only decides what is reported as
225
224
  * {@link InheritedOrder.notStarted}: anything named that is neither an open
226
225
  * pull request nor an open issue — merged, closed, unknown — constrains
227
226
  * nothing, since the issue's own start state is what asks for it to be looked
package/src/summarize.mts CHANGED
@@ -8,8 +8,8 @@ import type { ReportEntry, Summary } from './types.mjs';
8
8
  *
9
9
  * Here rather than in whoever displays it. Two of these are questions this
10
10
  * repository's conventions answer — `queued` is a label, and `failing` is the
11
- * verdict reached over the contexts the ruleset requires — and both
12
- * `pr-report` and the Pull Requests Manager page lead with them.
11
+ * verdict reached over the contexts the ruleset requires — and both `pr-report`
12
+ * and the Pull Requests Manager page lead with them.
13
13
  */
14
14
  export const summarize = (entries: readonly ReportEntry[]): Summary => {
15
15
  const count = (predicate: (entry: ReportEntry) => boolean): number =>
package/src/timestamp.mts CHANGED
@@ -1,20 +1,20 @@
1
1
  /**
2
- * GitHub's timestamps, as the numbers the page and the claims
3
- * (`claim.mts`) do arithmetic with.
2
+ * GitHub's timestamps, as the numbers the page and the claims (`claim.mts`) do
3
+ * arithmetic with.
4
4
  */
5
5
 
6
6
  import { Arr, Num, Result } from 'ts-data-forge';
7
7
 
8
8
  /**
9
- * Milliseconds since the epoch, or `undefined` for a string that is not
10
- * the one shape GitHub sends: `2026-09-24T09:39:18Z`, UTC, sometimes with a
11
- * fraction of a second.
9
+ * Milliseconds since the epoch, or `undefined` for a string that is not the one
10
+ * shape GitHub sends: `2026-09-24T09:39:18Z`, UTC, sometimes with a fraction of
11
+ * a second.
12
12
  *
13
- * Counted out field by field rather than handed to `Date`, whose parse is
14
- * left to the engine for anything but the exact format ECMAScript defines
15
- * and whose months count from zero, and rather than to `Temporal`, which not
16
- * every browser the page may be opened in has yet, nor every Node.js version
17
- * this package is tested on.
13
+ * Counted out field by field rather than handed to `Date`, whose parse is left
14
+ * to the engine for anything but the exact format ECMAScript defines and whose
15
+ * months count from zero, and rather than to `Temporal`, which not every
16
+ * browser the page may be opened in has yet, nor every Node.js version this
17
+ * package is tested on.
18
18
  */
19
19
  export const epochMsOf = (timestamp: string): number | undefined => {
20
20
  if (!timestamp.endsWith('Z')) {
@@ -65,10 +65,10 @@ const SECONDS_PER_HOUR = 3600;
65
65
  const SECONDS_PER_DAY = 86_400;
66
66
 
67
67
  /**
68
- * Days from 1970-01-01 to a date of the proleptic Gregorian calendar, with
69
- * the month counted from 1. Howard Hinnant's `days_from_civil`: the year is
70
- * taken to start in March, so the leap day falls at its end and every month
71
- * before it has a fixed length.
68
+ * Days from 1970-01-01 to a date of the proleptic Gregorian calendar, with the
69
+ * month counted from 1. Howard Hinnant's `days_from_civil`: the year is taken
70
+ * to start in March, so the leap day falls at its end and every month before it
71
+ * has a fixed length.
72
72
  */
73
73
  const daysFromCivil = (year: number, month: number, day: number): number => {
74
74
  const marchYear = month <= 2 ? year - 1 : year;
package/src/tree.mts CHANGED
@@ -22,11 +22,11 @@ export type Forest = Readonly<{
22
22
  * nothing and is dropped — the pull request it named has merged, which is
23
23
  * exactly the constraint being satisfied.
24
24
  *
25
- * Two things a forest cannot hold are handled rather than drawn. A pull
26
- * request that declared several predecessors appears under each of them, but
27
- * is expanded under the first only ({@link TreeNode.repeated} marks the rest),
28
- * so a diamond does not duplicate everything below it. A pull request on a
29
- * cycle is left out altogether and reported through {@link Forest.cycles}:
25
+ * Two things a forest cannot hold are handled rather than drawn. A pull request
26
+ * that declared several predecessors appears under each of them, but is
27
+ * expanded under the first only ({@link TreeNode.repeated} marks the rest), so
28
+ * a diamond does not duplicate everything below it. A pull request on a cycle
29
+ * is left out altogether and reported through {@link Forest.cycles}:
30
30
  * every member of a cycle waits, in the end, for itself, so there is no
31
31
  * position in a merge order to draw it at.
32
32
  */
package/src/types.mts CHANGED
@@ -14,23 +14,22 @@ export type RepoRef = Readonly<{ owner: string; name: string }>;
14
14
  * What one context has reported on a head commit.
15
15
  *
16
16
  * `skipped` is its own state rather than a kind of `passed`. GitHub counts a
17
- * skip as met, and so does the verdict — but once the two are one word a
18
- * reader cannot tell them apart, and the aggregate that skipped may be from a
19
- * round that was superseded by one about to fail.
17
+ * skip as met, and so does the verdict — but once the two are one word a reader
18
+ * cannot tell them apart, and the aggregate that skipped may be from a round
19
+ * that was superseded by one about to fail.
20
20
  */
21
21
  export type ContextState = 'failed' | 'passed' | 'pending' | 'skipped';
22
22
 
23
23
  export type ChecksSummary = Readonly<{
24
24
  /**
25
- * `paused` is `skip-ci`: the gated jobs boot no runner and
26
- * `no-skip-ci-label` sits `pending` by design, so neither "pending" nor
27
- * "failing" describes it.
25
+ * `paused` is `skip-ci`: the gated jobs boot no runner and `no-skip-ci-label`
26
+ * sits `pending` by design, so neither "pending" nor "failing" describes it.
28
27
  */
29
28
  verdict: 'failing' | 'passed' | 'paused' | 'pending';
30
29
  /**
31
30
  * Every required context by what it reported. These four,
32
- * {@link ChecksSummary.missing} and {@link ChecksSummary.notRun} are
33
- * disjoint and cover the required list.
31
+ * {@link ChecksSummary.missing} and {@link ChecksSummary.notRun} are disjoint
32
+ * and cover the required list.
34
33
  */
35
34
  passed: readonly string[];
36
35
  failed: readonly string[];
@@ -44,9 +43,9 @@ export type ChecksSummary = Readonly<{
44
43
  missing: readonly string[];
45
44
  /**
46
45
  * Required contexts with nothing reported, on a pull request whose base the
47
- * ruleset does not cover — a stacked one. A workflow may run on pull
48
- * requests into `main` only, and then its contexts never come here; nothing
49
- * waits for them, since GitHub requires nothing of this base either.
46
+ * ruleset does not cover — a stacked one. A workflow may run on pull requests
47
+ * into `main` only, and then its contexts never come here; nothing waits for
48
+ * them, since GitHub requires nothing of this base either.
50
49
  */
51
50
  notRun: readonly string[];
52
51
  /** How many contexts the verdict was reached over. */
@@ -86,28 +85,28 @@ export type PullRequestFacts = Readonly<{
86
85
  labels: readonly Label[];
87
86
  /**
88
87
  * Whether auto-merge is armed. Separate from `merge-queued`, which is the
89
- * author saying a pull request is to be landed: the label is the request
90
- * and this is the mechanism, which `unblock-prs` arms when it picks the
91
- * pull request.
88
+ * author saying a pull request is to be landed: the label is the request and
89
+ * this is the mechanism, which `unblock-prs` arms when it picks the pull
90
+ * request.
92
91
  */
93
92
  autoMerge: boolean;
94
93
  headRef: string;
95
94
  headSha: string;
96
95
  baseRef: string;
97
96
  /**
98
- * Whether the head branch lives in a fork, which keeps it from being read
99
- * as the parent of a stacked pull request. See `stack.mts`.
97
+ * Whether the head branch lives in a fork, which keeps it from being read as
98
+ * the parent of a stacked pull request. See `stack.mts`.
100
99
  */
101
100
  fromFork: boolean;
102
101
  url: string;
103
102
  /**
104
- * When anything about the pull request last changed — a label, a comment,
105
- * an edit — which is why it is not {@link PullRequestFacts.headCommittedAt}.
103
+ * When anything about the pull request last changed — a label, a comment, an
104
+ * edit — which is why it is not {@link PullRequestFacts.headCommittedAt}.
106
105
  */
107
106
  updatedAt: string;
108
107
  /**
109
- * When the head commit was made, which is when the branch was last pushed
110
- * to as nearly as GitHub records it. Undefined when it could not be read.
108
+ * When the head commit was made, which is when the branch was last pushed to
109
+ * as nearly as GitHub records it. Undefined when it could not be read.
111
110
  */
112
111
  headCommittedAt: string | undefined;
113
112
  /** Undefined when the comparison could not be read. */
@@ -115,8 +114,8 @@ export type PullRequestFacts = Readonly<{
115
114
  /** What every context reported on the head commit, required or not. */
116
115
  reported: ReadonlyMap<string, ContextState>;
117
116
  /**
118
- * Whether any check run on the head commit has not finished, required or
119
- * not. See `anyRunInProgress` for why the required ones are not enough.
117
+ * Whether any check run on the head commit has not finished, required or not.
118
+ * See `anyRunInProgress` for why the required ones are not enough.
120
119
  */
121
120
  checksRunning: boolean;
122
121
  linkedIssues: readonly LinkedIssue[];
@@ -132,8 +131,8 @@ export type ReportEntry = PullRequestFacts &
132
131
  */
133
132
  stackedOn: number | undefined;
134
133
  /**
135
- * The open pull requests it merges after because an issue it closes
136
- * starts after them (`start-after.mts`'s `inheritStartAfter`), less what
134
+ * The open pull requests it merges after because an issue it closes starts
135
+ * after them (`start-after.mts`'s `inheritStartAfter`), less what
137
136
  * `mergeAfter` and `stackedOn` already say.
138
137
  */
139
138
  inheritedMergeAfter: readonly number[];
@@ -153,9 +152,9 @@ export type ReportEntry = PullRequestFacts &
153
152
 
154
153
  /**
155
154
  * One pull request in the merge order. `repeated` marks the second and later
156
- * appearances of a pull request with more than one predecessor — declared,
157
- * or the one it is stacked on: it is drawn under each of them, but expanded
158
- * under the first only.
155
+ * appearances of a pull request with more than one predecessor — declared, or
156
+ * the one it is stacked on: it is drawn under each of them, but expanded under
157
+ * the first only.
159
158
  */
160
159
  export type TreeNode = Readonly<{
161
160
  number: number;
@@ -166,8 +165,8 @@ export type TreeNode = Readonly<{
166
165
  /**
167
166
  * One pull request that has already landed, for the section that says what
168
167
  * shipped. Nothing that is true of an open pull request — a merge order, a
169
- * check verdict, a distance from its base — is true of one that has merged,
170
- * so it is its own shape rather than an entry with the fields blanked.
168
+ * check verdict, a distance from its base — is true of one that has merged, so
169
+ * it is its own shape rather than an entry with the fields blanked.
171
170
  */
172
171
  export type MergedPullRequest = Readonly<{
173
172
  number: number;
@@ -202,8 +201,8 @@ export type OpenIssue = Readonly<{
202
201
  */
203
202
  startAfter: readonly number[];
204
203
  /**
205
- * What a `Merge-After:` in its body names. That line is not read on an
206
- * issue, and is shown as a slip to fix: `Start-After:` is the issue's.
204
+ * What a `Merge-After:` in its body names. That line is not read on an issue,
205
+ * and is shown as a slip to fix: `Start-After:` is the issue's.
207
206
  */
208
207
  misplacedMergeAfter: readonly number[];
209
208
  }>;
@@ -224,8 +223,8 @@ export type IssueDeclarations = Readonly<{
224
223
  /** Each issue's `Start-After:`; an issue not in it declares nothing. */
225
224
  startAfter: ReadonlyMap<number, readonly number[]>;
226
225
  /**
227
- * The numbers known to be open issues, beyond the ones an open pull
228
- * request links as open. Decides only what is said not to be started.
226
+ * The numbers known to be open issues, beyond the ones an open pull request
227
+ * links as open. Decides only what is said not to be started.
229
228
  */
230
229
  open: ReadonlySet<number>;
231
230
  }>;