@bluewombat/manager-github 0.7.0 → 0.9.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.
- package/README.md +120 -31
- package/SPECS.md +45 -20
- package/dist/adapter/normalize/intent.d.ts +3 -3
- package/dist/adapter/normalize/intent.d.ts.map +1 -1
- package/dist/adapter/normalize/intent.js +4 -4
- package/dist/adapter/normalize/intent.js.map +1 -1
- package/dist/adapter/normalize/normalize.d.ts +4 -1
- package/dist/adapter/normalize/normalize.d.ts.map +1 -1
- package/dist/adapter/normalize/normalize.js +3 -1
- package/dist/adapter/normalize/normalize.js.map +1 -1
- package/dist/adapter/run/run-adapter.d.ts +1 -1
- package/dist/adapter/run/run-adapter.d.ts.map +1 -1
- package/dist/adapter/run/run-adapter.js +28 -2
- package/dist/adapter/run/run-adapter.js.map +1 -1
- package/dist/adapter/types.d.ts +9 -3
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/adapter/types.js +1 -1
- package/dist/adapter/types.js.map +1 -1
- package/dist/emitter/event/field-matrix.d.ts +1 -1
- package/dist/emitter/event/field-matrix.d.ts.map +1 -1
- package/dist/emitter/event/field-matrix.js +5 -9
- package/dist/emitter/event/field-matrix.js.map +1 -1
- package/dist/emitter/github/labels.d.ts +3 -4
- package/dist/emitter/github/labels.d.ts.map +1 -1
- package/dist/emitter/github/labels.js +9 -9
- package/dist/emitter/github/labels.js.map +1 -1
- package/dist/emitter/render/render-event.d.ts.map +1 -1
- package/dist/emitter/render/render-event.js +13 -42
- package/dist/emitter/render/render-event.js.map +1 -1
- package/dist/emitter/run/run-emitter.d.ts +1 -1
- package/dist/emitter/run/run-emitter.js +3 -3
- package/dist/emitter/thread/marker.d.ts +1 -1
- package/dist/emitter/thread/marker.d.ts.map +1 -1
- package/dist/emitter/thread/marker.js +1 -1
- package/dist/emitter/thread/marker.js.map +1 -1
- package/dist/emitter/types.d.ts +8 -10
- package/dist/emitter/types.d.ts.map +1 -1
- package/dist/emitter/types.js +1 -1
- package/dist/emitter/types.js.map +1 -1
- package/dist/github/blockers.d.ts +24 -0
- package/dist/github/blockers.d.ts.map +1 -0
- package/dist/github/blockers.js +50 -0
- package/dist/github/blockers.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -45
- package/dist/index.js.map +1 -1
- package/dist/listener/delivery/process-tree.d.ts +1 -1
- package/dist/listener/delivery/process-tree.js +1 -1
- package/dist/listener/run/run-listener.d.ts +1 -1
- package/dist/listener/run/run-listener.js +1 -1
- package/dist/listener/source/select-events.d.ts +6 -1
- package/dist/listener/source/select-events.d.ts.map +1 -1
- package/dist/listener/source/select-events.js +9 -2
- package/dist/listener/source/select-events.js.map +1 -1
- package/dist/listener/types.d.ts +1 -1
- package/dist/listener/types.d.ts.map +1 -1
- package/dist/listener/types.js +1 -1
- package/dist/listener/types.js.map +1 -1
- package/dist/manager.d.ts +19 -8
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +139 -94
- package/dist/manager.js.map +1 -1
- package/dist/settled.d.ts +5 -4
- package/dist/settled.d.ts.map +1 -1
- package/dist/settled.js +7 -7
- package/dist/settled.js.map +1 -1
- package/dist/setup.d.ts +21 -8
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +44 -11
- package/dist/setup.js.map +1 -1
- package/dist/state-labels.d.ts +23 -0
- package/dist/state-labels.d.ts.map +1 -0
- package/dist/state-labels.js +55 -0
- package/dist/state-labels.js.map +1 -0
- package/dist/submission/lines.d.ts +19 -0
- package/dist/submission/lines.d.ts.map +1 -0
- package/dist/submission/lines.js +91 -0
- package/dist/submission/lines.js.map +1 -0
- package/dist/submission/submission.d.ts +5 -5
- package/dist/submission/submission.d.ts.map +1 -1
- package/dist/submission/submission.js +4 -7
- package/dist/submission/submission.js.map +1 -1
- package/dist/tickets/list-tickets.d.ts +27 -0
- package/dist/tickets/list-tickets.d.ts.map +1 -0
- package/dist/tickets/list-tickets.js +95 -0
- package/dist/tickets/list-tickets.js.map +1 -0
- package/dist/written-fingerprint.d.ts +2 -1
- package/dist/written-fingerprint.d.ts.map +1 -1
- package/dist/written-fingerprint.js +3 -3
- package/dist/written-fingerprint.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Manager: GitHub Issues
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
3
|
+
The FeatureTracker and TicketTracker for GitHub Issues: a Feature is an issue
|
|
4
|
+
carrying `feature-ready`, its Tickets are its sub-issues carrying `task-ready`;
|
|
5
|
+
comments (and optional state labels) go out, over the REST API with a token.
|
|
6
|
+
The same repository is the Authority: it cuts the lines and holds the pull
|
|
7
|
+
requests.
|
|
5
8
|
Contract: [SPECS.md](./SPECS.md).
|
|
6
9
|
|
|
7
10
|
```bash
|
|
@@ -10,27 +13,76 @@ npx mason init --manager @bluewombat/manager-github --manager-option repo=owner/
|
|
|
10
13
|
export GITHUB_TOKEN=…
|
|
11
14
|
```
|
|
12
15
|
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
```yaml
|
|
17
|
+
featureTracker:
|
|
18
|
+
package: "@bluewombat/manager-github"
|
|
19
|
+
options:
|
|
20
|
+
repo: owner/name
|
|
21
|
+
featureReadyLabel: feature-ready
|
|
22
|
+
mergeWhenReadyLabel: merge-when-ready
|
|
23
|
+
resumeLabel: to-resume
|
|
24
|
+
defaultProject: app
|
|
25
|
+
stateLabels: &stateLabels
|
|
26
|
+
invalid: "mason:invalid"
|
|
27
|
+
accepted: "mason:accepted"
|
|
28
|
+
progress: "mason:progress"
|
|
29
|
+
escalated: "mason:escalated"
|
|
30
|
+
escalation_reminder: "mason:escalation_reminder"
|
|
31
|
+
resumed: "mason:resumed"
|
|
32
|
+
submitted: "mason:submitted"
|
|
33
|
+
done: "mason:done"
|
|
34
|
+
cancelled: "mason:cancelled"
|
|
35
|
+
reject_late: "mason:reject_late"
|
|
36
|
+
ticketTracker:
|
|
37
|
+
package: "@bluewombat/manager-github"
|
|
38
|
+
options:
|
|
39
|
+
repo: owner/name
|
|
40
|
+
ticketReadyLabel: task-ready
|
|
41
|
+
resumeLabel: to-resume
|
|
42
|
+
defaultProject: app
|
|
43
|
+
stateLabels: *stateLabels
|
|
24
44
|
```
|
|
25
45
|
|
|
46
|
+
Each label option is written under the side that uses it:
|
|
47
|
+
`featureReadyLabel` and `mergeWhenReadyLabel` under `featureTracker`,
|
|
48
|
+
`ticketReadyLabel` under `ticketTracker`. The package is told which side it
|
|
49
|
+
serves, so `mason setup` creates only that side's labels and `mason doctor`
|
|
50
|
+
names only those; an option under the wrong side is refused by name. The
|
|
51
|
+
options both sides read (`repo`, `tokenEnv`, `resumeLabel`, `defaultProject`,
|
|
52
|
+
`stateLabels`, …) are written under both.
|
|
53
|
+
|
|
54
|
+
A config that gives both sides the same options (a YAML anchor, say) builds one
|
|
55
|
+
manager serving both: every option is then accepted, and the label options may
|
|
56
|
+
share one name.
|
|
57
|
+
|
|
58
|
+
The same package answers both sides here; a Feature tracker of another tool
|
|
59
|
+
takes the first block alone (Features), and this package the second (Tickets,
|
|
60
|
+
lines).
|
|
61
|
+
|
|
26
62
|
The token is read by this package from the environment; it never appears in the
|
|
27
63
|
config file and Host never sees it.
|
|
28
64
|
|
|
65
|
+
## Features and Tickets
|
|
66
|
+
|
|
67
|
+
| On GitHub | Means |
|
|
68
|
+
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
69
|
+
| A top-level issue with `feature-ready` | A Feature: its content is final, its Tickets may be written. Only these are listed. A sub-issue is never a Feature |
|
|
70
|
+
| Its sub-issues | Its Tickets, in the order GitHub gives them |
|
|
71
|
+
| `task-ready` on a sub-issue | The Ticket's specification is final. A Feature starts only when every one of its Tickets carries it |
|
|
72
|
+
| "Blocked by" (issue dependencies) | On a Feature: the Features that must be done first. On a Ticket: the Tickets that must be done first |
|
|
73
|
+
| `merge-when-ready` on a Feature | Its line may be folded without a human. Without it, a human merges the pull request and the system waits |
|
|
74
|
+
| `to-resume` on an escalated Feature or Ticket | Resume |
|
|
75
|
+
| `priority:<n>`, `project:<name>` labels | On a Feature and on a Ticket |
|
|
76
|
+
|
|
77
|
+
The Feature and Ticket labels may share one name (`featureReadyLabel` and
|
|
78
|
+
`ticketReadyLabel` both `ready-for-agent`): a sub-issue is a Ticket whatever it
|
|
79
|
+
carries, and `mason setup` creates the label once.
|
|
80
|
+
|
|
29
81
|
## What an issue says
|
|
30
82
|
|
|
31
83
|
The body is the intention, word for word, less what GitHub itself put there:
|
|
32
84
|
the comments an issue template leaves behind, and the boxes of a task list —
|
|
33
|
-
`- [ ] a CSV downloads` reaches the
|
|
85
|
+
`- [ ] a CSV downloads` reaches the Builder as `- a CSV downloads`. Nothing is
|
|
34
86
|
read out of it: no checklist is required, no criteria are extracted (what
|
|
35
87
|
"done" means is the layer above mason's, not mason's). A body that was only a
|
|
36
88
|
template's comments falls back to the title.
|
|
@@ -38,7 +90,7 @@ template's comments falls back to the title.
|
|
|
38
90
|
That text, with the title, the project and the priority, is the issue's
|
|
39
91
|
fingerprint — what tells an **edit** from an **echo**. Comments, state labels
|
|
40
92
|
and a ticked box all move `updated_at` and deliver the issue again; none of
|
|
41
|
-
them changes the fingerprint. Rewording the body does, and on a
|
|
93
|
+
them changes the fingerprint. Rewording the body does, and on a Ticket in
|
|
42
94
|
flight that is recorded and freezes it once the current unit lands, for a
|
|
43
95
|
human to decide. So: tick the boxes as you please; rewrite the words only when
|
|
44
96
|
you mean it.
|
|
@@ -51,30 +103,35 @@ you mean it.
|
|
|
51
103
|
| `tokenEnv` | no | `GITHUB_TOKEN` | Environment variable holding the token |
|
|
52
104
|
| `token` | no | — | The token itself. For embedding and tests; prefer `tokenEnv` |
|
|
53
105
|
| `apiBase` | no | `https://api.github.com` | REST base, for GitHub Enterprise |
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
106
|
+
| `featureReadyLabel` (featureTracker) | no | `feature-ready` | The label that makes an issue a Feature the system may take |
|
|
107
|
+
| `ticketReadyLabel` (ticketTracker) | no | `task-ready` | The label a sub-issue carries once its specification is final |
|
|
108
|
+
| `mergeWhenReadyLabel` (featureTracker) | no | `merge-when-ready` | On a Feature: its line is folded without a human |
|
|
109
|
+
| `resumeLabel` | no | `to-resume` | On an escalated Feature or Ticket, this label means resume; the escalation comment names it |
|
|
110
|
+
| `defaultProject` | no | none | The Project of a Feature that has no `project:` label. Without it, such a Feature is refused as invalid (`missing-project`). `mason setup` creates the label `project:<defaultProject>` |
|
|
57
111
|
| `defaultPriority` | no | `50` | Priority when no `priority:` label says otherwise (0…100) |
|
|
58
|
-
| `
|
|
112
|
+
| `stateLabels` | no | none | A mapping that names, for every Event, the label it lands as (see State labels). Absent: the Events leave no label |
|
|
59
113
|
| `branch` | no | `main` | The work line pull requests are opened onto. `mason setup` checks it exists and names the repository's default branch when it does not |
|
|
60
114
|
| `remote` | no | `https://github.com/<repo>.git` | Git URL of the repository, for Host's copy of the work line. Over HTTPS, git authenticates with the token in `tokenEnv` — read when git asks, never written to disk — so pushes are the token's account. Set it for GitHub Enterprise, a mirror, or SSH (then this machine's keys are used, and `doctor` says so) |
|
|
61
|
-
| `keepBranch` | no | `false` | Leave the
|
|
115
|
+
| `keepBranch` | no | `false` | Leave the ticket branch on the remote after the fold. By default it is deleted once the squash is on the work line |
|
|
62
116
|
| `commitAuthor` | no | none | `Name <email>`: who the system is on the commits it makes. Without it, commits carry this machine's git identity, and `doctor` warns. Use the token's account (its noreply address works) so GitHub credits the system, not a person |
|
|
63
117
|
|
|
64
118
|
## Submissions
|
|
65
119
|
|
|
66
|
-
This manager is an Authority: it
|
|
67
|
-
as a pull request, and
|
|
120
|
+
This manager is an Authority: it cuts the line of a Feature, offers an
|
|
121
|
+
assembled Ticket (or a Feature's line) to the repository as a pull request, and
|
|
122
|
+
takes an accepted one in.
|
|
68
123
|
|
|
69
124
|
| Method | On GitHub |
|
|
70
125
|
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
126
|
+
| `openLine`| Creates `feature/<n>` from `branch` (`git/refs`). A line that exists is a success |
|
|
127
|
+
| `dropLine`| Deletes a line nobody will fold |
|
|
128
|
+
| `submit` | Opens a pull request from the published branch onto the line it is offered to (a Feature's line, or `branch`). An open one on the same branch is reused, never duplicated |
|
|
129
|
+
| `settled` | Whether the pull request is still open, was merged (by anyone), or was closed unmerged. A human's merge is read here |
|
|
73
130
|
| `fold` | Squash-merges it: the commit's title is the pull request's; its body is what the Project's Describer said (carried on the pull request), else `Closes #N` alone. Then deletes the branch unless `keepBranch` |
|
|
74
131
|
|
|
75
132
|
The pull request is titled after the issue (trailing full stop dropped, `(#N)`
|
|
76
|
-
appended) and its body is the issue's intention
|
|
77
|
-
`Closes #N` — so GitHub closes the issue when the pull request is merged.
|
|
133
|
+
appended) and its body is the issue's intention and
|
|
134
|
+
`Closes #N` — so GitHub closes the issue when the pull request is merged. GitHub honours `Closes` only for a merge into the default branch, so a Ticket folded into a Feature's line stays open until a reservation says otherwise (`docs/RESERVATIONS.md`).
|
|
78
135
|
Nothing in it is generated.
|
|
79
136
|
|
|
80
137
|
`verdict` counts the grace for a commit with no check from the **commit**, not
|
|
@@ -82,7 +139,7 @@ from the pull request: one that was sent back and published again is old while
|
|
|
82
139
|
its commit is seconds old, and reading "no check yet" as "no checks exist" folds
|
|
83
140
|
it unjudged.
|
|
84
141
|
|
|
85
|
-
`
|
|
142
|
+
`clearResume` takes the `resumeLabel` off an issue once a resume has been acted
|
|
86
143
|
on, so an escalation freezes instead of resuming on every pass.
|
|
87
144
|
|
|
88
145
|
`probe` asks whether an issue Host already holds is still there. A poll cannot
|
|
@@ -119,7 +176,7 @@ back whole, as the full read would have been. A 304 sent with an
|
|
|
119
176
|
Authorization header does not count against the token's hourly budget
|
|
120
177
|
(GitHub's [REST best practices](https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api);
|
|
121
178
|
measured: three 304s in a row left `x-ratelimit-used` unchanged). So a tick
|
|
122
|
-
where nothing moved on the watched issues — the listing, a probe of a
|
|
179
|
+
where nothing moved on the watched issues — the listing, a probe of a Ticket
|
|
123
180
|
in flight — costs a round trip and no budget. Handing the answer back rather
|
|
124
181
|
than reading a 304 as "nothing" matters: when Host did not commit its Cursor,
|
|
125
182
|
the same listing is asked again and the issues not consumed yet must come back.
|
|
@@ -130,11 +187,41 @@ per judgement, with nothing to remember an `etag` in. Anything this manager
|
|
|
130
187
|
writes on an issue (a comment, a label) changes the listing, so the next read
|
|
131
188
|
after a report is a full one.
|
|
132
189
|
|
|
190
|
+
## State labels
|
|
191
|
+
|
|
192
|
+
The Events are `invalid`, `accepted`, `progress`, `escalated`, `escalation_reminder`,
|
|
193
|
+
`resumed`, `submitted`, `done`, `cancelled` and `reject_late`. With `stateLabels` set,
|
|
194
|
+
the issue carries the label of its latest Event and the previous one is removed;
|
|
195
|
+
every other label (`project:`, `priority:`, yours) is never touched. `done` and
|
|
196
|
+
`cancelled` also keep a fresh Mason home from rebuilding or taking up an issue that
|
|
197
|
+
already ended, unless the resume label is on it.
|
|
198
|
+
|
|
199
|
+
`stateLabels` names every Event, with any label you like, and gives the same name to
|
|
200
|
+
no two Events:
|
|
201
|
+
|
|
202
|
+
```yaml
|
|
203
|
+
options:
|
|
204
|
+
stateLabels:
|
|
205
|
+
invalid: "mason:invalid"
|
|
206
|
+
accepted: "mason:accepted"
|
|
207
|
+
progress: "mason:progress"
|
|
208
|
+
escalated: "mason:escalated"
|
|
209
|
+
escalation_reminder: "mason:escalation_reminder"
|
|
210
|
+
resumed: "mason:resumed"
|
|
211
|
+
submitted: "mason:submitted"
|
|
212
|
+
done: "termine"
|
|
213
|
+
cancelled: "abandonne"
|
|
214
|
+
reject_late: "mason:reject_late"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Absent, nothing is labelled and the guard on `done` and `cancelled` is off. Naming
|
|
218
|
+
an Event outside the list, leaving one out, or giving a label twice is refused.
|
|
219
|
+
|
|
133
220
|
## Prepare the repository
|
|
134
221
|
|
|
135
222
|
`mason setup` reads the config and says what the repository still needs;
|
|
136
223
|
`--apply` creates it. It is idempotent, so it is safe to re-run after changing
|
|
137
|
-
|
|
224
|
+
the label options or setting `stateLabels`.
|
|
138
225
|
|
|
139
226
|
```bash
|
|
140
227
|
mason setup --apply
|
|
@@ -146,7 +233,7 @@ mason setup --apply
|
|
|
146
233
|
| Issues are enabled | `has_issues` on that same response |
|
|
147
234
|
| The token can write | `permissions.push` on that same response, rather than guessing at scopes |
|
|
148
235
|
| The branch exists | `GET /repos/{owner}/{repo}/branches/{branch}` for `branch` (default `main`); when it is missing and the config named none, the step says the repository's default branch and what to write |
|
|
149
|
-
| Labels | `
|
|
236
|
+
| Labels | `featureReadyLabel`, `ticketReadyLabel`, `mergeWhenReadyLabel`, `resumeLabel`, `project:<defaultProject>`, and one per Event when `stateLabels` is set |
|
|
150
237
|
|
|
151
238
|
Creating a label is the only write; nothing existing is renamed, recoloured, or
|
|
152
239
|
deleted.
|
|
@@ -181,10 +268,12 @@ SPECS.md the contract
|
|
|
181
268
|
README.md how to build and configure it
|
|
182
269
|
src/
|
|
183
270
|
index.ts createManager, checkManager, scaffoldManager — the plugin face
|
|
184
|
-
manager.ts the
|
|
271
|
+
manager.ts the Manager: `features` and `tickets` (listen / adapt / report / probe live in listener/, adapter/, emitter/, probe/)
|
|
185
272
|
github/ Octokit channel shared by listen, adapt, report, and probe
|
|
186
273
|
probe/ whether a minted key's issue is still on the tracker
|
|
187
274
|
repo.ts owner/name
|
|
275
|
+
tickets/ a Feature's sub-issues, their blockers and signals
|
|
276
|
+
submission/ lines, pull requests, settled
|
|
188
277
|
issue-number.ts the issue a key or a payload points at
|
|
189
278
|
labels.ts whether a payload carries a label
|
|
190
279
|
```
|
package/SPECS.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Manager: GitHub Issues
|
|
2
2
|
|
|
3
|
-
A plugin, not a Transformer. GitHub Issues in
|
|
4
|
-
state labels) out,
|
|
5
|
-
|
|
3
|
+
A plugin, not a Transformer. GitHub Issues in (Features and their sub-issues),
|
|
4
|
+
issue comments (and optional state labels) out, and the lines and pull requests
|
|
5
|
+
of the same repository, as one `Manager` (`features` and `tickets`). Listen /
|
|
6
|
+
adapt / report live in this package.
|
|
6
7
|
|
|
7
8
|
## 1. Job
|
|
8
9
|
|
|
@@ -10,15 +11,18 @@ package. GitHub-the-git-host is out of scope — only the tracker.
|
|
|
10
11
|
Host manager-github
|
|
11
12
|
---- --------------
|
|
12
13
|
managerOptions read repo / labels / token
|
|
13
|
-
a Cursor poll the
|
|
14
|
+
a Cursor poll the issues labelled feature-ready
|
|
15
|
+
a Feature list its sub-issues and blockers
|
|
14
16
|
a key probe: is the issue still there
|
|
15
17
|
one semantic Event comment, and maybe label
|
|
18
|
+
a Feature's line openLine: cut feature/<n>; dropLine
|
|
16
19
|
a published branch submit: open (or reuse) the pull request
|
|
17
|
-
a Submission reference fold: squash-merge it, delete the branch unless keepBranch
|
|
18
|
-
|
|
20
|
+
a Submission reference fold: squash-merge it, delete the branch unless keepBranch;
|
|
21
|
+
settled: open / folded / closed
|
|
22
|
+
← Manager
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
**In:** a `ManagerContext`. **Out:** a `
|
|
25
|
+
**In:** a `ManagerContext`. **Out:** a `Manager`, or a reason.
|
|
22
26
|
|
|
23
27
|
## 2. The token
|
|
24
28
|
|
|
@@ -29,7 +33,7 @@ or written to a Thread.
|
|
|
29
33
|
|
|
30
34
|
## 3. Keys
|
|
31
35
|
|
|
32
|
-
`github:<owner>/<name>#<issue>`, or `github:unconvertible` when the payload
|
|
36
|
+
Features and Tickets share one spelling: `github:<owner>/<name>#<issue>`, or `github:unconvertible` when the payload
|
|
33
37
|
carries no issue number. `report` recovers the issue from the key: every key
|
|
34
38
|
this package mints ends in `#<issue>`, so no issue number crosses the Port.
|
|
35
39
|
|
|
@@ -42,18 +46,28 @@ normalised, trailing blanks and runs of blank lines collapsed. Nothing is read:
|
|
|
42
46
|
no criteria, no headings, no meaning. A body that was only that falls back to
|
|
43
47
|
the title, like no body at all.
|
|
44
48
|
|
|
45
|
-
The FeatureStandard's `fingerprint` hashes that intention with the title, the
|
|
49
|
+
The FeatureStandard's and TicketStandard's `fingerprint` hashes that intention with the title, the
|
|
46
50
|
project and the priority. It is what tells an **edit** from an **echo** — a
|
|
47
51
|
comment or a state label moves `updated_at` and delivers the issue again, and
|
|
48
52
|
so does a human ticking a box. None of those is a change of mind, so none of
|
|
49
|
-
them changes the fingerprint; a different fingerprint on a
|
|
53
|
+
them changes the fingerprint; a different fingerprint on a Ticket in flight
|
|
50
54
|
is recorded as pending and freezes it once the current unit lands
|
|
51
55
|
(PRODUCT.md, "An intention edited while in flight"). Rewording the body is an
|
|
52
56
|
edit. Ticking a box is not.
|
|
53
57
|
|
|
54
|
-
##
|
|
58
|
+
## 3c. Features and Tickets
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
A Feature is listed when the issue has no parent (`parent_issue_url` is null) and carries `featureReadyLabel`
|
|
61
|
+
(`labels=<featureReadyLabel>` on the list call). Its `blocked_by` are read from
|
|
62
|
+
`GET /issues/{n}/dependencies/blocked_by`, its `merge_when_ready` from
|
|
63
|
+
`mergeWhenReadyLabel`. `tickets(feature)` reads `GET /issues/{n}/sub_issues`
|
|
64
|
+
and, per sub-issue, its blockers; `task_ready` is `ticketReadyLabel`, `resume` is
|
|
65
|
+
`resumeLabel`, `open` is the issue state. Every failed read is `unavailable`,
|
|
66
|
+
never an empty list.
|
|
67
|
+
|
|
68
|
+
## 4. Resume
|
|
69
|
+
|
|
70
|
+
`signalsResume` is true when the payload carries `resumeLabel`, ignoring case, in
|
|
57
71
|
either label spelling GitHub uses (a string, or an object with `name`). A poll
|
|
58
72
|
returns a snapshot with no `labeled` edge, so the label on the snapshot is the
|
|
59
73
|
only signal there is.
|
|
@@ -76,13 +90,12 @@ it", because from here the two are the same answer.
|
|
|
76
90
|
## 6. Doctor
|
|
77
91
|
|
|
78
92
|
`checkManager` reports the repository, whether the token variable is set
|
|
79
|
-
(`fail` when it is not),
|
|
80
|
-
|
|
81
|
-
repository needs. It never calls the API: the answer must be the same offline.
|
|
93
|
+
(`fail` when it is not), and names the labels the repository needs (`featureReadyLabel`,
|
|
94
|
+
`ticketReadyLabel`, `mergeWhenReadyLabel`, `resumeLabel`). It never calls the API: the answer must be the same offline.
|
|
82
95
|
|
|
83
96
|
## 6. Init
|
|
84
97
|
|
|
85
|
-
`scaffoldManager` fills `repo`, `tokenEnv`, `
|
|
98
|
+
`scaffoldManager` fills `repo`, `tokenEnv`, `resumeLabel` and
|
|
86
99
|
`defaultProject`. It does not create labels on the repository: that needs the
|
|
87
100
|
network, and the operator still owns the tracker. A `repo` already in
|
|
88
101
|
`managerOptions` is kept.
|
|
@@ -99,19 +112,26 @@ with no issue number is `unavailable`, not `gone`.
|
|
|
99
112
|
not answer says nothing about the intention being converted. Probe is the
|
|
100
113
|
path that may read a 404 as absence.
|
|
101
114
|
|
|
115
|
+
## 7b. Lines
|
|
116
|
+
|
|
117
|
+
`openLine({line, from})` reads `git/ref/heads/<from>` and creates `refs/heads/<line>`
|
|
118
|
+
at that commit; a 422 (the ref exists) is a success. `dropLine` deletes the ref
|
|
119
|
+
and ignores a refusal. `settled({reference})` reads the pull request: merged is
|
|
120
|
+
`folded`, closed unmerged is `closed`, otherwise `open`.
|
|
121
|
+
|
|
102
122
|
## 8. Acceptance
|
|
103
123
|
|
|
104
124
|
1. A token in the variable named by `tokenEnv` is enough to build the Port.
|
|
105
125
|
2. No token → a reason naming the variable it looked in.
|
|
106
126
|
3. A missing `repo`, a `repo` that is not `owner/name`, and an unknown option
|
|
107
127
|
key each return a reason.
|
|
108
|
-
4. `checkManager` fails on a missing token and
|
|
128
|
+
4. `checkManager` fails on a missing token and names the four labels.
|
|
109
129
|
5. `setup` without `apply` writes nothing; with `apply` it creates only the
|
|
110
130
|
missing labels, and a second `apply` writes nothing at all.
|
|
111
131
|
6. Disabled issues, a read-only token, and an unreachable repository each block
|
|
112
132
|
before any label is created.
|
|
113
133
|
7. `scaffoldManager` keeps a `repo` it was given and names `GITHUB_TOKEN`.
|
|
114
|
-
8. `invalid`, `accepted`, `
|
|
134
|
+
8. `invalid`, `accepted`, `escalated`, `escalation_reminder` and
|
|
115
135
|
`resumed` comments are written as string literals, not a field dump. An
|
|
116
136
|
`invalid` comment is the heading and the reason as a paragraph, with no
|
|
117
137
|
`- reason:` bullet.
|
|
@@ -124,7 +144,7 @@ path that may read a 404 as absence.
|
|
|
124
144
|
11. `setup` blocks on a `branch` the repository does not have, and names the
|
|
125
145
|
repository's default branch when the config named none.
|
|
126
146
|
12. An `escalated` comment says what a human can do from the issue, in this
|
|
127
|
-
tracker's gestures: add `
|
|
147
|
+
tracker's gestures: add `resumeLabel` to resume, close the issue to
|
|
128
148
|
abandon — and, for an escalation born in `merging`, only the first, since
|
|
129
149
|
a close there is refused. An `escalation_reminder` is the same comment
|
|
130
150
|
under "Still escalated": same diagnosis, same answers.
|
|
@@ -132,4 +152,9 @@ path that may read a 404 as absence.
|
|
|
132
152
|
heading, one line saying it is the stopping step's own words written for
|
|
133
153
|
the agent that repairs it, then the text fenced and folded at 80 columns.
|
|
134
154
|
|
|
135
|
-
|
|
155
|
+
14. A Feature is listed only with `featureReadyLabel`; its Tickets are its sub-issues;
|
|
156
|
+
a blocker read that fails is `unavailable`, never an empty list.
|
|
157
|
+
15. `openLine` of an existing line succeeds; `settled` distinguishes a merge
|
|
158
|
+
from a close.
|
|
159
|
+
|
|
160
|
+
How to build and configure: [README.md](./README.md).
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Intent, Invalid } from "../types.js";
|
|
2
2
|
/** What a repository can say about an issue, in this Block's five words. */
|
|
3
|
-
export type Kind = "create" | "update" | "
|
|
3
|
+
export type Kind = "create" | "update" | "resume" | "cancel" | "delete";
|
|
4
4
|
export type IntentInput = {
|
|
5
5
|
action: string | undefined;
|
|
6
6
|
state: string | undefined;
|
|
7
7
|
labels: string[];
|
|
8
|
-
|
|
8
|
+
resumeLabel: string;
|
|
9
9
|
};
|
|
10
10
|
export type IntentResult = {
|
|
11
11
|
ok: true;
|
|
@@ -19,7 +19,7 @@ export type IntentResult = {
|
|
|
19
19
|
*
|
|
20
20
|
* With an action, the repository said what changed. Without one — a snapshot a
|
|
21
21
|
* subscription listed — only the state is known: open means the intention
|
|
22
|
-
* itself, closed means drop it. `
|
|
22
|
+
* itself, closed means drop it. `resume` needs the edge, not the state: it is the
|
|
23
23
|
* moment the label arrived, and a snapshot cannot tell that from a label that
|
|
24
24
|
* has been there for a week.
|
|
25
25
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/intent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGnD,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/intent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGnD,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AA+BxE,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1F;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAmB3D"}
|
|
@@ -22,7 +22,7 @@ const ACTION_TO_KIND = {
|
|
|
22
22
|
const KIND_TO_INTENT = {
|
|
23
23
|
create: "upsert",
|
|
24
24
|
update: "upsert",
|
|
25
|
-
|
|
25
|
+
resume: "resume",
|
|
26
26
|
cancel: "cancel",
|
|
27
27
|
delete: "cancel",
|
|
28
28
|
};
|
|
@@ -31,7 +31,7 @@ const KIND_TO_INTENT = {
|
|
|
31
31
|
*
|
|
32
32
|
* With an action, the repository said what changed. Without one — a snapshot a
|
|
33
33
|
* subscription listed — only the state is known: open means the intention
|
|
34
|
-
* itself, closed means drop it. `
|
|
34
|
+
* itself, closed means drop it. `resume` needs the edge, not the state: it is the
|
|
35
35
|
* moment the label arrived, and a snapshot cannot tell that from a label that
|
|
36
36
|
* has been there for a week.
|
|
37
37
|
*/
|
|
@@ -49,8 +49,8 @@ export function readIntent(input) {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
if (input.action === "labeled" && hasLabel(input.labels, input.
|
|
53
|
-
return { ok: true, intent: KIND_TO_INTENT.
|
|
52
|
+
if (input.action === "labeled" && hasLabel(input.labels, input.resumeLabel)) {
|
|
53
|
+
return { ok: true, intent: KIND_TO_INTENT.resume };
|
|
54
54
|
}
|
|
55
55
|
return { ok: true, intent: KIND_TO_INTENT[kind] };
|
|
56
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../../src/adapter/normalize/intent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKvC,MAAM,cAAc,GAAyB;IAC3C,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,QAAQ;IACjB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,QAAQ;IACpB,UAAU,EAAE,QAAQ;IACpB,YAAY,EAAE,QAAQ;IACtB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,QAAQ;IACjB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,MAAM,cAAc,GAAyB;IAC3C,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../../src/adapter/normalize/intent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKvC,MAAM,cAAc,GAAyB;IAC3C,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,QAAQ;IACjB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,QAAQ;IACpB,UAAU,EAAE,QAAQ;IACpB,YAAY,EAAE,QAAQ;IACtB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,QAAQ;IACjB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,MAAM,cAAc,GAAyB;IAC3C,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACjB,CAAC;AAWF;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,WAAW,KAAK,CAAC,MAAM,gCAAgC;aAChE;SACF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC"}
|
|
@@ -7,7 +7,10 @@ export type NormalizeOptions = {
|
|
|
7
7
|
defaultPriority: number;
|
|
8
8
|
projectLabelPrefix: string;
|
|
9
9
|
priorityLabelPrefix: string;
|
|
10
|
-
|
|
10
|
+
resumeLabel: string;
|
|
11
|
+
mergeWhenReadyLabel: string;
|
|
12
|
+
/** Keys of the issues that block this one, read beside it: the issue itself does not carry them. */
|
|
13
|
+
blockedBy?: string[];
|
|
11
14
|
normalizedAt: string;
|
|
12
15
|
};
|
|
13
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAA4B,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAMzF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAA4B,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAMzF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAgGF;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAuIpF"}
|
|
@@ -138,7 +138,7 @@ export function normalize(raw, options) {
|
|
|
138
138
|
action: raw.action,
|
|
139
139
|
state: state.value,
|
|
140
140
|
labels: labels.names,
|
|
141
|
-
|
|
141
|
+
resumeLabel: options.resumeLabel,
|
|
142
142
|
});
|
|
143
143
|
if (!intent.ok) {
|
|
144
144
|
return { ok: false, invalid: intent.invalid };
|
|
@@ -206,6 +206,8 @@ export function normalize(raw, options) {
|
|
|
206
206
|
...(title.value !== undefined ? { title: title.value } : {}),
|
|
207
207
|
...(intention !== undefined ? { intention } : {}),
|
|
208
208
|
priority: priority.value ?? options.defaultPriority,
|
|
209
|
+
blocked_by: options.blockedBy ?? [],
|
|
210
|
+
merge_when_ready: labels.names.some((name) => name.toLowerCase() === options.mergeWhenReadyLabel.toLowerCase()),
|
|
209
211
|
...(Object.keys(source).length > 0 ? { source } : {}),
|
|
210
212
|
fingerprint: "",
|
|
211
213
|
normalized_at: options.normalizedAt,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAgB/C,MAAM,cAAc,GAA2B;IAC7C,GAAG,EAAE,EAAE;IACP,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,GAAG;CACZ,CAAC;AAEF,SAAS,OAAO,CAAC,KAAa,EAAE,KAAc;IAC5C,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,UAAU,KAAK,QAAQ,QAAQ,CAAC,KAAK,CAAC,iCAAiC;KAChF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,OAAO,KAAK,EAAE,CAAC;AAC7B,CAAC;AAKD,SAAS,UAAU,CAAC,KAA8B,EAAE,KAAa;IAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5E,CAAC;AAED,qEAAqE;AACrE,SAAS,UAAU,CAAC,KAA8B;IAChD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1D,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,MAAgB,EAAE,MAAc;IACpD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,qBAAqB,MAAM,CAAC,MAAM,KAAK,MAAM,aAAa,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aACvF;SACF,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IAChD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;YAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,KAAK,8BAA8B,EAAE;SAC3F,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE,EAAE,KAAK;QACT,OAAO,EAAE;YACP,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,aAAa,GAAG,sDAAsD;SAC/E;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,GAAc,EAAE,OAAyB;IACjE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAEtB,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QACpE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,2EAA2E;aACpF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC/C,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IAC9C,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC/C,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAC7C,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,MAAM,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,8CAA8C,EAAE;SACxF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC5E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,mBAAmB;gBACzB,MAAM,EAAE,qBAAqB,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,kBAAkB,aAAa,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aAC/G;SACF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC;IACtD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,OAAO,OAAO,CAAC,kBAAkB,gDAAgD;aAC1F;SACF,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,wEAAwE;IACxE,0EAA0E;IAC1E,0CAA0C;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrF,MAAM,SAAS,GAAG,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IACxF,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,mBAAmB;gBACzB,MAAM,EAAE,qDAAqD;aAC9D;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAC3B,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAC3D,OAAO,CAAC,mBAAmB,CAC5B,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,MAAM,MAAM,GAAwC,EAAE,CAAC;IACvD,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC;IACzB,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;IAEhF,8EAA8E;IAC9E,MAAM,OAAO,GAAoB;QAC/B,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,UAAU,EAAE;QACvC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO;QACP,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,QAAQ,EAAE,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,eAAe;QACnD,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;QACnC,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CACjC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAC3E;QACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,OAAO,CAAC,YAAY;KACpC,CAAC;IAEF,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,OAA6C,CAAC,CAAC;IACnF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -22,7 +22,7 @@ export type RunOptions = {
|
|
|
22
22
|
};
|
|
23
23
|
export declare function invalidInvocationResult(write: ProgressWriter, reason: string): RunResult;
|
|
24
24
|
/**
|
|
25
|
-
* Run one
|
|
25
|
+
* Run one Adapter invocation to a run outcome.
|
|
26
26
|
*/
|
|
27
27
|
export declare function runAdapter(options: RunOptions): Promise<RunResult>;
|
|
28
28
|
//# sourceMappingURL=run-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapter/run/run-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapter/run/run-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C,CAAC;AAiBF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAOxF;AAcD;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6HxE"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { listBlockers } from "../../github/blockers.js";
|
|
2
|
+
import { issueNumberFromPayload } from "../../issue-number.js";
|
|
1
3
|
import { fetchIssue } from "../github/fetch-issue.js";
|
|
2
4
|
import { normalize } from "../normalize/normalize.js";
|
|
3
5
|
import { parseRaw } from "../raw/parse-raw.js";
|
|
@@ -36,7 +38,7 @@ function fetchableNumber(issue) {
|
|
|
36
38
|
return undefined;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
|
-
* Run one
|
|
41
|
+
* Run one Adapter invocation to a run outcome.
|
|
40
42
|
*/
|
|
41
43
|
export async function runAdapter(options) {
|
|
42
44
|
const { invocation, raw } = options;
|
|
@@ -72,6 +74,7 @@ export async function runAdapter(options) {
|
|
|
72
74
|
}
|
|
73
75
|
const unwrapped = unwrapIssue(parsed.object);
|
|
74
76
|
let merged = unwrapped;
|
|
77
|
+
let blockedBy = [];
|
|
75
78
|
if (invocation.fetch) {
|
|
76
79
|
const number = fetchableNumber(unwrapped.issue);
|
|
77
80
|
if (options.github === undefined) {
|
|
@@ -99,6 +102,27 @@ export async function runAdapter(options) {
|
|
|
99
102
|
}
|
|
100
103
|
// The Fetch is the base; the raw intention is the fresher of the two.
|
|
101
104
|
merged = { ...unwrapped, issue: { ...fetched.issue, ...unwrapped.issue } };
|
|
105
|
+
// What blocks the issue is not on the issue: it is asked of the API too.
|
|
106
|
+
const blockers = await listBlockers({
|
|
107
|
+
github: options.github,
|
|
108
|
+
repo: invocation.repo,
|
|
109
|
+
number,
|
|
110
|
+
deadlineMs: now() + (invocation.fetchDurationMs ?? 1),
|
|
111
|
+
now,
|
|
112
|
+
shouldInterrupt,
|
|
113
|
+
});
|
|
114
|
+
if (blockers.kind === "interrupted") {
|
|
115
|
+
return finishInterrupted();
|
|
116
|
+
}
|
|
117
|
+
if (blockers.kind === "unavailable") {
|
|
118
|
+
return finishUnavailable(blockers.detail);
|
|
119
|
+
}
|
|
120
|
+
blockedBy = blockers.issues.flatMap((issue) => {
|
|
121
|
+
const blocker = issueNumberFromPayload(issue);
|
|
122
|
+
return blocker === undefined
|
|
123
|
+
? []
|
|
124
|
+
: [`${invocation.manager}:${invocation.repo.owner}/${invocation.repo.name}#${blocker}`];
|
|
125
|
+
});
|
|
102
126
|
}
|
|
103
127
|
}
|
|
104
128
|
if (shouldInterrupt()) {
|
|
@@ -110,7 +134,9 @@ export async function runAdapter(options) {
|
|
|
110
134
|
defaultPriority: invocation.defaultPriority,
|
|
111
135
|
projectLabelPrefix: invocation.projectLabelPrefix,
|
|
112
136
|
priorityLabelPrefix: invocation.priorityLabelPrefix,
|
|
113
|
-
|
|
137
|
+
resumeLabel: invocation.resumeLabel,
|
|
138
|
+
mergeWhenReadyLabel: invocation.mergeWhenReadyLabel,
|
|
139
|
+
blockedBy,
|
|
114
140
|
normalizedAt: invocation.at ?? new Date(now()).toISOString(),
|
|
115
141
|
...(invocation.defaultProject !== undefined
|
|
116
142
|
? { defaultProject: invocation.defaultProject }
|