@bluewombat/manager-github 0.1.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 +162 -0
- package/SPECS.md +126 -0
- package/dist/adapter/github/fetch-issue.d.ts +29 -0
- package/dist/adapter/github/fetch-issue.d.ts.map +1 -0
- package/dist/adapter/github/fetch-issue.js +34 -0
- package/dist/adapter/github/fetch-issue.js.map +1 -0
- package/dist/adapter/normalize/body.d.ts +24 -0
- package/dist/adapter/normalize/body.d.ts.map +1 -0
- package/dist/adapter/normalize/body.js +104 -0
- package/dist/adapter/normalize/body.js.map +1 -0
- package/dist/adapter/normalize/fingerprint.d.ts +8 -0
- package/dist/adapter/normalize/fingerprint.d.ts.map +1 -0
- package/dist/adapter/normalize/fingerprint.js +26 -0
- package/dist/adapter/normalize/fingerprint.js.map +1 -0
- package/dist/adapter/normalize/intent.d.ts +27 -0
- package/dist/adapter/normalize/intent.d.ts.map +1 -0
- package/dist/adapter/normalize/intent.js +57 -0
- package/dist/adapter/normalize/intent.js.map +1 -0
- package/dist/adapter/normalize/labels.d.ts +17 -0
- package/dist/adapter/normalize/labels.d.ts.map +1 -0
- package/dist/adapter/normalize/labels.js +43 -0
- package/dist/adapter/normalize/labels.js.map +1 -0
- package/dist/adapter/normalize/noise.d.ts +13 -0
- package/dist/adapter/normalize/noise.d.ts.map +1 -0
- package/dist/adapter/normalize/noise.js +28 -0
- package/dist/adapter/normalize/noise.js.map +1 -0
- package/dist/adapter/normalize/normalize.d.ts +22 -0
- package/dist/adapter/normalize/normalize.d.ts.map +1 -0
- package/dist/adapter/normalize/normalize.js +216 -0
- package/dist/adapter/normalize/normalize.js.map +1 -0
- package/dist/adapter/progress/emit.d.ts +3 -0
- package/dist/adapter/progress/emit.d.ts.map +1 -0
- package/dist/adapter/progress/emit.js +6 -0
- package/dist/adapter/progress/emit.js.map +1 -0
- package/dist/adapter/raw/parse-raw.d.ts +14 -0
- package/dist/adapter/raw/parse-raw.d.ts.map +1 -0
- package/dist/adapter/raw/parse-raw.js +47 -0
- package/dist/adapter/raw/parse-raw.js.map +1 -0
- package/dist/adapter/raw/unwrap.d.ts +12 -0
- package/dist/adapter/raw/unwrap.d.ts.map +1 -0
- package/dist/adapter/raw/unwrap.js +19 -0
- package/dist/adapter/raw/unwrap.js.map +1 -0
- package/dist/adapter/run/run-adapter.d.ts +28 -0
- package/dist/adapter/run/run-adapter.d.ts.map +1 -0
- package/dist/adapter/run/run-adapter.js +131 -0
- package/dist/adapter/run/run-adapter.js.map +1 -0
- package/dist/adapter/types.d.ts +69 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/types.js +3 -0
- package/dist/adapter/types.js.map +1 -0
- package/dist/emitter/event/field-matrix.d.ts +29 -0
- package/dist/emitter/event/field-matrix.d.ts.map +1 -0
- package/dist/emitter/event/field-matrix.js +94 -0
- package/dist/emitter/event/field-matrix.js.map +1 -0
- package/dist/emitter/github/comments.d.ts +14 -0
- package/dist/emitter/github/comments.d.ts.map +1 -0
- package/dist/emitter/github/comments.js +69 -0
- package/dist/emitter/github/comments.js.map +1 -0
- package/dist/emitter/github/labels.d.ts +18 -0
- package/dist/emitter/github/labels.d.ts.map +1 -0
- package/dist/emitter/github/labels.js +81 -0
- package/dist/emitter/github/labels.js.map +1 -0
- package/dist/emitter/github/result.d.ts +19 -0
- package/dist/emitter/github/result.d.ts.map +1 -0
- package/dist/emitter/github/result.js +2 -0
- package/dist/emitter/github/result.js.map +1 -0
- package/dist/emitter/progress/emit.d.ts +3 -0
- package/dist/emitter/progress/emit.d.ts.map +1 -0
- package/dist/emitter/progress/emit.js +6 -0
- package/dist/emitter/progress/emit.js.map +1 -0
- package/dist/emitter/render/render-event.d.ts +20 -0
- package/dist/emitter/render/render-event.d.ts.map +1 -0
- package/dist/emitter/render/render-event.js +293 -0
- package/dist/emitter/render/render-event.js.map +1 -0
- package/dist/emitter/render/truncate.d.ts +9 -0
- package/dist/emitter/render/truncate.d.ts.map +1 -0
- package/dist/emitter/render/truncate.js +10 -0
- package/dist/emitter/render/truncate.js.map +1 -0
- package/dist/emitter/run/run-emitter.d.ts +27 -0
- package/dist/emitter/run/run-emitter.d.ts.map +1 -0
- package/dist/emitter/run/run-emitter.js +121 -0
- package/dist/emitter/run/run-emitter.js.map +1 -0
- package/dist/emitter/thread/marker.d.ts +15 -0
- package/dist/emitter/thread/marker.d.ts.map +1 -0
- package/dist/emitter/thread/marker.js +37 -0
- package/dist/emitter/thread/marker.js.map +1 -0
- package/dist/emitter/types.d.ts +64 -0
- package/dist/emitter/types.d.ts.map +1 -0
- package/dist/emitter/types.js +3 -0
- package/dist/emitter/types.js.map +1 -0
- package/dist/github/client.d.ts +63 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +96 -0
- package/dist/github/client.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +357 -0
- package/dist/index.js.map +1 -0
- package/dist/issue-number.d.ts +5 -0
- package/dist/issue-number.d.ts.map +1 -0
- package/dist/issue-number.js +32 -0
- package/dist/issue-number.js.map +1 -0
- package/dist/labels.d.ts +3 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +24 -0
- package/dist/labels.js.map +1 -0
- package/dist/listener/delivery/run-hook.d.ts +8 -0
- package/dist/listener/delivery/run-hook.d.ts.map +1 -0
- package/dist/listener/delivery/run-hook.js +50 -0
- package/dist/listener/delivery/run-hook.js.map +1 -0
- package/dist/listener/github/list-issues.d.ts +30 -0
- package/dist/listener/github/list-issues.d.ts.map +1 -0
- package/dist/listener/github/list-issues.js +36 -0
- package/dist/listener/github/list-issues.js.map +1 -0
- package/dist/listener/progress/emit.d.ts +3 -0
- package/dist/listener/progress/emit.d.ts.map +1 -0
- package/dist/listener/progress/emit.js +6 -0
- package/dist/listener/progress/emit.js.map +1 -0
- package/dist/listener/run/run-listener.d.ts +35 -0
- package/dist/listener/run/run-listener.d.ts.map +1 -0
- package/dist/listener/run/run-listener.js +217 -0
- package/dist/listener/run/run-listener.js.map +1 -0
- package/dist/listener/source/select-events.d.ts +46 -0
- package/dist/listener/source/select-events.d.ts.map +1 -0
- package/dist/listener/source/select-events.js +102 -0
- package/dist/listener/source/select-events.js.map +1 -0
- package/dist/listener/types.d.ts +56 -0
- package/dist/listener/types.d.ts.map +1 -0
- package/dist/listener/types.js +3 -0
- package/dist/listener/types.js.map +1 -0
- package/dist/manager.d.ts +29 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +256 -0
- package/dist/manager.js.map +1 -0
- package/dist/probe/probe-issue.d.ts +20 -0
- package/dist/probe/probe-issue.d.ts.map +1 -0
- package/dist/probe/probe-issue.js +45 -0
- package/dist/probe/probe-issue.js.map +1 -0
- package/dist/repo.d.ts +6 -0
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +14 -0
- package/dist/repo.js.map +1 -0
- package/dist/setup.d.ts +43 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +281 -0
- package/dist/setup.js.map +1 -0
- package/dist/submission/submission.d.ts +44 -0
- package/dist/submission/submission.d.ts.map +1 -0
- package/dist/submission/submission.js +189 -0
- package/dist/submission/submission.js.map +1 -0
- package/dist/written-fingerprint.d.ts +7 -0
- package/dist/written-fingerprint.d.ts.map +1 -0
- package/dist/written-fingerprint.js +38 -0
- package/dist/written-fingerprint.js.map +1 -0
- package/package.json +51 -0
package/dist/setup.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { EVENT_NAMES, PRODUCT } from "@bluewombat/manager-kit";
|
|
2
|
+
import { callSignal, createClient, readFailure } from "./github/client.js";
|
|
3
|
+
const PER_PAGE = 100;
|
|
4
|
+
/** Colours are only there so a human can tell the families apart at a glance. */
|
|
5
|
+
const READY_COLOUR = "0e8a16";
|
|
6
|
+
const ADMISSION_COLOUR = "1d76db";
|
|
7
|
+
const STATE_COLOUR = "5319e7";
|
|
8
|
+
const PROJECT_COLOUR = "c5def5";
|
|
9
|
+
/**
|
|
10
|
+
* Bring one repository to the shape a run expects: reachable, issues on, a
|
|
11
|
+
* token that can write, and every label the config names.
|
|
12
|
+
*
|
|
13
|
+
* Idempotent by construction — it asks what is there before it creates
|
|
14
|
+
* anything, and creating a label that already exists is never attempted.
|
|
15
|
+
*/
|
|
16
|
+
export async function runSetup(settings, input) {
|
|
17
|
+
const now = () => Date.now();
|
|
18
|
+
const deadlineMs = now() + settings.durationMs;
|
|
19
|
+
const shouldInterrupt = () => settings.interruptFlag.interrupted;
|
|
20
|
+
const github = createClient({
|
|
21
|
+
token: settings.token,
|
|
22
|
+
apiBase: settings.apiBase,
|
|
23
|
+
requestRetries: settings.githubFetch === undefined ? 2 : 0,
|
|
24
|
+
deadlineMs,
|
|
25
|
+
now,
|
|
26
|
+
shouldInterrupt,
|
|
27
|
+
throttle: settings.githubFetch === undefined,
|
|
28
|
+
...(settings.githubFetch !== undefined ? { fetch: settings.githubFetch } : {}),
|
|
29
|
+
});
|
|
30
|
+
const context = { deadlineMs, now, shouldInterrupt };
|
|
31
|
+
const steps = [];
|
|
32
|
+
const repository = await readRepository(github, settings.repo, settings, context);
|
|
33
|
+
if (repository.ok === false) {
|
|
34
|
+
steps.push(repository.step);
|
|
35
|
+
return { ok: false, steps };
|
|
36
|
+
}
|
|
37
|
+
steps.push(...repository.steps);
|
|
38
|
+
if (repository.steps.some((step) => step.state === "blocked")) {
|
|
39
|
+
return { ok: false, steps };
|
|
40
|
+
}
|
|
41
|
+
const present = await readLabels(github, settings.repo, context);
|
|
42
|
+
if (present.ok === false) {
|
|
43
|
+
steps.push(present.step);
|
|
44
|
+
return { ok: false, steps };
|
|
45
|
+
}
|
|
46
|
+
const known = new Set(present.names.map((name) => name.toLowerCase()));
|
|
47
|
+
for (const wanted of wantedLabels(settings)) {
|
|
48
|
+
if (known.has(wanted.name.toLowerCase())) {
|
|
49
|
+
steps.push({
|
|
50
|
+
id: `label:${wanted.name}`,
|
|
51
|
+
summary: `label ${wanted.name}`,
|
|
52
|
+
state: "satisfied",
|
|
53
|
+
detail: "already on the repository",
|
|
54
|
+
});
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (!input.apply) {
|
|
58
|
+
steps.push({
|
|
59
|
+
id: `label:${wanted.name}`,
|
|
60
|
+
summary: `create label ${wanted.name}`,
|
|
61
|
+
state: "missing",
|
|
62
|
+
detail: wanted.description,
|
|
63
|
+
});
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
steps.push(await createLabel(github, settings.repo, wanted, context));
|
|
67
|
+
}
|
|
68
|
+
return { ok: steps.every((step) => step.state !== "blocked"), steps };
|
|
69
|
+
}
|
|
70
|
+
/** Every label this configuration will look for or write, and why it exists. */
|
|
71
|
+
export function wantedLabels(settings) {
|
|
72
|
+
const wanted = [];
|
|
73
|
+
for (const name of settings.labels ?? []) {
|
|
74
|
+
wanted.push({
|
|
75
|
+
name,
|
|
76
|
+
colour: ADMISSION_COLOUR,
|
|
77
|
+
description: `${PRODUCT} admits an issue only when it carries this label`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
wanted.push({
|
|
81
|
+
name: settings.readyLabel,
|
|
82
|
+
colour: READY_COLOUR,
|
|
83
|
+
description: `on an escalated feature, ${PRODUCT} resumes it`,
|
|
84
|
+
});
|
|
85
|
+
if (settings.defaultProject !== undefined) {
|
|
86
|
+
wanted.push({
|
|
87
|
+
name: `project:${settings.defaultProject}`,
|
|
88
|
+
colour: PROJECT_COLOUR,
|
|
89
|
+
description: `routes the issue to this ${PRODUCT} Project`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (settings.stateLabelPrefix !== undefined) {
|
|
93
|
+
for (const event of EVENT_NAMES) {
|
|
94
|
+
wanted.push({
|
|
95
|
+
name: `${settings.stateLabelPrefix}${event}`,
|
|
96
|
+
colour: STATE_COLOUR,
|
|
97
|
+
description: `${PRODUCT} state: ${event}`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// A repeated name would try to create the same label twice.
|
|
102
|
+
const seen = new Set();
|
|
103
|
+
return wanted.filter((label) => {
|
|
104
|
+
const key = label.name.toLowerCase();
|
|
105
|
+
if (seen.has(key)) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
seen.add(key);
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async function readRepository(github, repo, settings, context) {
|
|
113
|
+
const slug = `${repo.owner}/${repo.name}`;
|
|
114
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
115
|
+
try {
|
|
116
|
+
const response = await github.request("GET /repos/{owner}/{repo}", {
|
|
117
|
+
owner: repo.owner,
|
|
118
|
+
repo: repo.name,
|
|
119
|
+
request: { signal: call.signal },
|
|
120
|
+
});
|
|
121
|
+
const data = response.data;
|
|
122
|
+
const steps = [
|
|
123
|
+
{ id: "repository", summary: `repository ${slug}`, state: "satisfied" },
|
|
124
|
+
];
|
|
125
|
+
steps.push(data.has_issues === true
|
|
126
|
+
? { id: "issues", summary: "issues are enabled", state: "satisfied" }
|
|
127
|
+
: {
|
|
128
|
+
id: "issues",
|
|
129
|
+
summary: "issues are enabled",
|
|
130
|
+
state: "blocked",
|
|
131
|
+
detail: `Issues are turned off on ${slug}; ${PRODUCT} has no Source without them.`,
|
|
132
|
+
});
|
|
133
|
+
// The authenticated repository response carries what this token may do,
|
|
134
|
+
// which beats guessing at scope names.
|
|
135
|
+
const push = data.permissions?.push;
|
|
136
|
+
steps.push(push === true || push === undefined
|
|
137
|
+
? {
|
|
138
|
+
id: "write-access",
|
|
139
|
+
summary: "the token can write",
|
|
140
|
+
state: "satisfied",
|
|
141
|
+
...(push === undefined ? { detail: "not reported by the API; assuming it can" } : {}),
|
|
142
|
+
}
|
|
143
|
+
: {
|
|
144
|
+
id: "write-access",
|
|
145
|
+
summary: "the token can write",
|
|
146
|
+
state: "blocked",
|
|
147
|
+
detail: `The token can read ${slug} but not write to it; comments and labels would fail.`,
|
|
148
|
+
});
|
|
149
|
+
steps.push(await readBranch(github, repo, settings, {
|
|
150
|
+
defaultBranch: typeof data.default_branch === "string" ? data.default_branch : undefined,
|
|
151
|
+
}, context));
|
|
152
|
+
return { ok: true, steps };
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
const failure = readFailure(error);
|
|
156
|
+
return {
|
|
157
|
+
ok: false,
|
|
158
|
+
step: {
|
|
159
|
+
id: "repository",
|
|
160
|
+
summary: `repository ${slug}`,
|
|
161
|
+
state: "blocked",
|
|
162
|
+
detail: failure.status === 404
|
|
163
|
+
? `Not found, or this token cannot see it: ${slug}`
|
|
164
|
+
: failure.detail,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
call.release();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The branch pull requests are opened onto has to exist. When the config did
|
|
174
|
+
* not name one, `main` is a guess, and a repository on another default branch
|
|
175
|
+
* would otherwise fail at the first run, one step later than here.
|
|
176
|
+
*/
|
|
177
|
+
async function readBranch(github, repo, settings, repository, context) {
|
|
178
|
+
const slug = `${repo.owner}/${repo.name}`;
|
|
179
|
+
const { branch, branchConfigured } = settings;
|
|
180
|
+
const summary = `branch ${branch}`;
|
|
181
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
182
|
+
try {
|
|
183
|
+
await github.request("GET /repos/{owner}/{repo}/branches/{branch}", {
|
|
184
|
+
owner: repo.owner,
|
|
185
|
+
repo: repo.name,
|
|
186
|
+
branch,
|
|
187
|
+
request: { signal: call.signal },
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
const failure = readFailure(error);
|
|
192
|
+
if (failure.status !== 404) {
|
|
193
|
+
return { id: "branch", summary, state: "blocked", detail: failure.detail };
|
|
194
|
+
}
|
|
195
|
+
const hint = repository.defaultBranch === undefined || repository.defaultBranch === branch
|
|
196
|
+
? ""
|
|
197
|
+
: ` Its default branch is "${repository.defaultBranch}": set managerOptions.branch to it, or to the branch pull requests should target.`;
|
|
198
|
+
return {
|
|
199
|
+
id: "branch",
|
|
200
|
+
summary,
|
|
201
|
+
state: "blocked",
|
|
202
|
+
detail: branchConfigured
|
|
203
|
+
? `No branch "${branch}" on ${slug} (managerOptions.branch).${hint}`
|
|
204
|
+
: `No branch "${branch}" on ${slug}, and managerOptions.branch does not say.${hint}`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
call.release();
|
|
209
|
+
}
|
|
210
|
+
const detail = repository.defaultBranch === undefined || repository.defaultBranch === branch
|
|
211
|
+
? "the repository's default branch"
|
|
212
|
+
: `not the default branch (${repository.defaultBranch}); pull requests are opened onto it`;
|
|
213
|
+
return { id: "branch", summary, state: "satisfied", detail };
|
|
214
|
+
}
|
|
215
|
+
async function readLabels(github, repo, context) {
|
|
216
|
+
const names = [];
|
|
217
|
+
let page = 1;
|
|
218
|
+
for (;;) {
|
|
219
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
220
|
+
try {
|
|
221
|
+
const response = await github.request("GET /repos/{owner}/{repo}/labels", {
|
|
222
|
+
owner: repo.owner,
|
|
223
|
+
repo: repo.name,
|
|
224
|
+
per_page: PER_PAGE,
|
|
225
|
+
page,
|
|
226
|
+
request: { signal: call.signal },
|
|
227
|
+
});
|
|
228
|
+
for (const label of response.data) {
|
|
229
|
+
names.push(label.name);
|
|
230
|
+
}
|
|
231
|
+
if (response.data.length < PER_PAGE) {
|
|
232
|
+
return { ok: true, names };
|
|
233
|
+
}
|
|
234
|
+
page += 1;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
ok: false,
|
|
239
|
+
step: {
|
|
240
|
+
id: "labels",
|
|
241
|
+
summary: "read the repository labels",
|
|
242
|
+
state: "blocked",
|
|
243
|
+
detail: readFailure(error).detail,
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
call.release();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function createLabel(github, repo, wanted, context) {
|
|
253
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
254
|
+
try {
|
|
255
|
+
await github.request("POST /repos/{owner}/{repo}/labels", {
|
|
256
|
+
owner: repo.owner,
|
|
257
|
+
repo: repo.name,
|
|
258
|
+
name: wanted.name,
|
|
259
|
+
color: wanted.colour,
|
|
260
|
+
description: wanted.description,
|
|
261
|
+
request: { signal: call.signal },
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
id: `label:${wanted.name}`,
|
|
265
|
+
summary: `create label ${wanted.name}`,
|
|
266
|
+
state: "applied",
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
return {
|
|
271
|
+
id: `label:${wanted.name}`,
|
|
272
|
+
summary: `create label ${wanted.name}`,
|
|
273
|
+
state: "blocked",
|
|
274
|
+
detail: readFailure(error).detail,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
finally {
|
|
278
|
+
call.release();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAoC,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,YAAY,EAAqB,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG9F,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErB,iFAAiF;AACjF,MAAM,YAAY,GAAG,QAAQ,CAAC;AAC9B,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAClC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAC9B,MAAM,cAAc,GAAG,QAAQ,CAAC;AAoBhC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAuB,EACvB,KAAyB;IAEzB,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC;IAC/C,MAAM,eAAe,GAAG,GAAY,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC;IAC1E,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,cAAc,EAAE,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,UAAU;QACV,GAAG;QACH,eAAe;QACf,QAAQ,EAAE,QAAQ,CAAC,WAAW,KAAK,SAAS;QAC5C,GAAG,CAAC,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/E,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC;IACrD,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClF,IAAI,UAAU,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvE,KAAK,MAAM,MAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,EAAE;gBAC1B,OAAO,EAAE,SAAS,MAAM,CAAC,IAAI,EAAE;gBAC/B,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,2BAA2B;aACpC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,EAAE;gBAC1B,OAAO,EAAE,gBAAgB,MAAM,CAAC,IAAI,EAAE;gBACtC,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,MAAM,CAAC,WAAW;aAC3B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,QAK5B;IACC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC;YACV,IAAI;YACJ,MAAM,EAAE,gBAAgB;YACxB,WAAW,EAAE,GAAG,OAAO,kDAAkD;SAC1E,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,IAAI,CAAC;QACV,IAAI,EAAE,QAAQ,CAAC,UAAU;QACzB,MAAM,EAAE,YAAY;QACpB,WAAW,EAAE,4BAA4B,OAAO,aAAa;KAC9D,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,WAAW,QAAQ,CAAC,cAAc,EAAE;YAC1C,MAAM,EAAE,cAAc;YACtB,WAAW,EAAE,4BAA4B,OAAO,UAAU;SAC3D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,GAAG,QAAQ,CAAC,gBAAgB,GAAG,KAAK,EAAE;gBAC5C,MAAM,EAAE,YAAY;gBACpB,WAAW,EAAE,GAAG,OAAO,WAAW,KAAK,EAAE;aAC1C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,4DAA4D;IAC5D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAID,KAAK,UAAU,cAAc,CAC3B,MAAoB,EACpB,IAAgB,EAChB,QAA4D,EAC5D,OAAoB;IAEpB,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,2BAA2B,EAAE;YACjE,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC3B,MAAM,KAAK,GAAgB;YACzB,EAAE,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE;SACxE,CAAC;QACF,KAAK,CAAC,IAAI,CACR,IAAI,CAAC,UAAU,KAAK,IAAI;YACtB,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,WAAW,EAAE;YACrE,CAAC,CAAC;gBACE,EAAE,EAAE,QAAQ;gBACZ,OAAO,EAAE,oBAAoB;gBAC7B,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,4BAA4B,IAAI,KAAK,OAAO,8BAA8B;aACnF,CACN,CAAC;QACF,wEAAwE;QACxE,uCAAuC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC;QACpC,KAAK,CAAC,IAAI,CACR,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;YACjC,CAAC,CAAC;gBACE,EAAE,EAAE,cAAc;gBAClB,OAAO,EAAE,qBAAqB;gBAC9B,KAAK,EAAE,WAAW;gBAClB,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,0CAA0C,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtF;YACH,CAAC,CAAC;gBACE,EAAE,EAAE,cAAc;gBAClB,OAAO,EAAE,qBAAqB;gBAC9B,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,sBAAsB,IAAI,uDAAuD;aAC1F,CACN,CAAC;QACF,KAAK,CAAC,IAAI,CACR,MAAM,UAAU,CACd,MAAM,EACN,IAAI,EACJ,QAAQ,EACR;YACE,aAAa,EAAE,OAAO,IAAI,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;SACzF,EACD,OAAO,CACR,CACF,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE;gBACJ,EAAE,EAAE,YAAY;gBAChB,OAAO,EAAE,cAAc,IAAI,EAAE;gBAC7B,KAAK,EAAE,SAAS;gBAChB,MAAM,EACJ,OAAO,CAAC,MAAM,KAAK,GAAG;oBACpB,CAAC,CAAC,2CAA2C,IAAI,EAAE;oBACnD,CAAC,CAAC,OAAO,CAAC,MAAM;aACrB;SACF,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,UAAU,CACvB,MAAoB,EACpB,IAAgB,EAChB,QAA4D,EAC5D,UAAiD,EACjD,OAAoB;IAEpB,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,QAAQ,CAAC;IAC9C,MAAM,OAAO,GAAG,UAAU,MAAM,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,6CAA6C,EAAE;YAClE,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM;YACN,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC3B,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAC7E,CAAC;QACD,MAAM,IAAI,GACR,UAAU,CAAC,aAAa,KAAK,SAAS,IAAI,UAAU,CAAC,aAAa,KAAK,MAAM;YAC3E,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,2BAA2B,UAAU,CAAC,aAAa,mFAAmF,CAAC;QAC7I,OAAO;YACL,EAAE,EAAE,QAAQ;YACZ,OAAO;YACP,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,gBAAgB;gBACtB,CAAC,CAAC,cAAc,MAAM,QAAQ,IAAI,4BAA4B,IAAI,EAAE;gBACpE,CAAC,CAAC,cAAc,MAAM,QAAQ,IAAI,4CAA4C,IAAI,EAAE;SACvF,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GACV,UAAU,CAAC,aAAa,KAAK,SAAS,IAAI,UAAU,CAAC,aAAa,KAAK,MAAM;QAC3E,CAAC,CAAC,iCAAiC;QACnC,CAAC,CAAC,2BAA2B,UAAU,CAAC,aAAa,qCAAqC,CAAC;IAC/F,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AAC/D,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,MAAoB,EACpB,IAAgB,EAChB,OAAoB;IAEpB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QAClF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,kCAAkC,EAAE;gBACxE,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,QAAQ,EAAE,QAAQ;gBAClB,IAAI;gBACJ,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;aACjC,CAAC,CAAC;YACH,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;YACD,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;gBACpC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YACD,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE;oBACJ,EAAE,EAAE,QAAQ;oBACZ,OAAO,EAAE,4BAA4B;oBACrC,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM;iBAClC;aACF,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,MAAoB,EACpB,IAAgB,EAChB,MAAmB,EACnB,OAAoB;IAEpB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,mCAAmC,EAAE;YACxD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,MAAM,CAAC,MAAM;YACpB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC,CAAC,CAAC;QACH,OAAO;YACL,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,EAAE;YAC1B,OAAO,EAAE,gBAAgB,MAAM,CAAC,IAAI,EAAE;YACtC,KAAK,EAAE,SAAS;SACjB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,EAAE;YAC1B,OAAO,EAAE,gBAAgB,MAAM,CAAC,IAAI,EAAE;YACtC,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM;SAClC,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FoldResult, SubmissionRequest, SubmissionResult } from "@bluewombat/manager-kit";
|
|
2
|
+
import { type GithubClient } from "../github/client.js";
|
|
3
|
+
import type { Repository } from "../repo.js";
|
|
4
|
+
/**
|
|
5
|
+
* A pull request is this Authority's Submission.
|
|
6
|
+
*
|
|
7
|
+
* It opens one and it merges one. Whether the work is good is decided nowhere in
|
|
8
|
+
* this file: the `ci-green` Gate reads the checks and answers, like any other
|
|
9
|
+
* Gate. An Authority acts; it does not judge.
|
|
10
|
+
*
|
|
11
|
+
* The reference travels as the pull request's address: it identifies the
|
|
12
|
+
* Submission here, and it is the one thing worth showing a human reading the
|
|
13
|
+
* issue — a path on the machine that ran is of no use to them.
|
|
14
|
+
*/
|
|
15
|
+
export type SubmissionContext = {
|
|
16
|
+
repo: Repository;
|
|
17
|
+
github: GithubClient;
|
|
18
|
+
deadlineMs: number;
|
|
19
|
+
now: () => number;
|
|
20
|
+
shouldInterrupt: () => boolean;
|
|
21
|
+
/** Leave the feature branch on the remote after the fold. Default: delete it. */
|
|
22
|
+
keepBranch?: boolean | undefined;
|
|
23
|
+
};
|
|
24
|
+
export declare function referenceOf(repo: Repository, number: number): string;
|
|
25
|
+
export declare function numberFromReference(reference: string): number | undefined;
|
|
26
|
+
export declare function submitPullRequest(input: SubmissionRequest, context: SubmissionContext): Promise<SubmissionResult>;
|
|
27
|
+
export declare function foldPullRequest(reference: string, context: SubmissionContext): Promise<FoldResult>;
|
|
28
|
+
/** `commit_title` and `commit_message` for the squash, from what the pull request carries. */
|
|
29
|
+
export declare function commitOf(pullTitle: string, pullBody: string): {
|
|
30
|
+
commit_title: string;
|
|
31
|
+
commit_message: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The issue's title, made a pull request title: no trailing full stop, and
|
|
35
|
+
* the issue's number where GitHub links it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function titleOf(input: Pick<SubmissionRequest, "key" | "title">): string;
|
|
38
|
+
/**
|
|
39
|
+
* What the pull request delivers, from what was asked and what was planned.
|
|
40
|
+
* Nothing here is generated: the intention is the human's words, the steps are
|
|
41
|
+
* the Plan's. `Closes #N` lets GitHub close the issue when this is merged.
|
|
42
|
+
*/
|
|
43
|
+
export declare function bodyOf(input: Pick<SubmissionRequest, "key" | "title" | "intention" | "steps" | "description">): string;
|
|
44
|
+
//# sourceMappingURL=submission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../../src/submission/submission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAc,KAAK,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAEjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,OAAO,CAAC;IAC/B,iFAAiF;IACjF,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOzE;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA+B3B;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,UAAU,CAAC,CA+CrB;AA0BD,8FAA8F;AAC9F,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAelD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG,MAAM,CAK/E;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,aAAa,CAAC,GACtF,MAAM,CAuBR"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { PRODUCT } from "@bluewombat/manager-kit";
|
|
2
|
+
import { callSignal, readFailure } from "../github/client.js";
|
|
3
|
+
import { issueNumberFromExternalId } from "../issue-number.js";
|
|
4
|
+
export function referenceOf(repo, number) {
|
|
5
|
+
return `https://github.com/${repo.owner}/${repo.name}/pull/${number}`;
|
|
6
|
+
}
|
|
7
|
+
export function numberFromReference(reference) {
|
|
8
|
+
const matched = /\/pull\/(\d+)\s*$/.exec(reference.trim());
|
|
9
|
+
if (matched?.[1] === undefined) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const parsed = Number.parseInt(matched[1], 10);
|
|
13
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
14
|
+
}
|
|
15
|
+
export async function submitPullRequest(input, context) {
|
|
16
|
+
const existing = await openPullRequestFor(input.ref, context);
|
|
17
|
+
if (existing.kind === "unavailable") {
|
|
18
|
+
return { outcome: "unavailable" };
|
|
19
|
+
}
|
|
20
|
+
if (existing.kind === "found") {
|
|
21
|
+
// Republished to the same place: the Authority is judging the same
|
|
22
|
+
// Submission with new content, so there is nothing to open.
|
|
23
|
+
return { outcome: "submitted", reference: referenceOf(context.repo, existing.number) };
|
|
24
|
+
}
|
|
25
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
26
|
+
try {
|
|
27
|
+
const response = await context.github.request("POST /repos/{owner}/{repo}/pulls", {
|
|
28
|
+
owner: context.repo.owner,
|
|
29
|
+
repo: context.repo.name,
|
|
30
|
+
title: titleOf(input),
|
|
31
|
+
head: input.ref,
|
|
32
|
+
base: input.target,
|
|
33
|
+
body: bodyOf(input),
|
|
34
|
+
request: { signal: call.signal },
|
|
35
|
+
});
|
|
36
|
+
return { outcome: "submitted", reference: referenceOf(context.repo, response.data.number) };
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const failure = readFailure(error);
|
|
40
|
+
return failure.permanent
|
|
41
|
+
? { outcome: "refused", reason: failure.detail }
|
|
42
|
+
: { outcome: "unavailable" };
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
call.release();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function foldPullRequest(reference, context) {
|
|
49
|
+
const number = numberFromReference(reference);
|
|
50
|
+
if (number === undefined) {
|
|
51
|
+
return { outcome: "unavailable" };
|
|
52
|
+
}
|
|
53
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
54
|
+
try {
|
|
55
|
+
// One commit on the work line per feature, saying what the pull request
|
|
56
|
+
// was opened with — the message decided then and kept on it, so a restart
|
|
57
|
+
// loses nothing — and closing the issue. The branch keeps the
|
|
58
|
+
// Subtask-by-Subtask history for whoever wants it.
|
|
59
|
+
const pull = await context.github.request("GET /repos/{owner}/{repo}/pulls/{pull_number}", {
|
|
60
|
+
owner: context.repo.owner,
|
|
61
|
+
repo: context.repo.name,
|
|
62
|
+
pull_number: number,
|
|
63
|
+
request: { signal: call.signal },
|
|
64
|
+
});
|
|
65
|
+
const merged = await context.github.request("PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge", {
|
|
66
|
+
owner: context.repo.owner,
|
|
67
|
+
repo: context.repo.name,
|
|
68
|
+
pull_number: number,
|
|
69
|
+
merge_method: "squash",
|
|
70
|
+
...commitOf(pull.data.title, pull.data.body ?? ""),
|
|
71
|
+
request: { signal: call.signal },
|
|
72
|
+
});
|
|
73
|
+
// The branch has done its job once the work line holds the squash. It is
|
|
74
|
+
// deleted best-effort: the fold happened whatever this call says, and a
|
|
75
|
+
// branch left behind is clutter, not a failure.
|
|
76
|
+
if (context.keepBranch !== true) {
|
|
77
|
+
await deleteBranch(pull.data.head.ref, context, call.signal);
|
|
78
|
+
}
|
|
79
|
+
const reference = merged.data.sha;
|
|
80
|
+
return typeof reference === "string" ? { outcome: "folded", reference } : { outcome: "folded" };
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const failure = readFailure(error);
|
|
84
|
+
if (failure.status === 405 || failure.status === 409) {
|
|
85
|
+
return { outcome: "conflict", reason: failure.detail };
|
|
86
|
+
}
|
|
87
|
+
return failure.permanent
|
|
88
|
+
? { outcome: "conflict", reason: failure.detail }
|
|
89
|
+
: { outcome: "unavailable" };
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
call.release();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function deleteBranch(ref, context, signal) {
|
|
96
|
+
try {
|
|
97
|
+
await context.github.request("DELETE /repos/{owner}/{repo}/git/refs/{ref}", {
|
|
98
|
+
owner: context.repo.owner,
|
|
99
|
+
repo: context.repo.name,
|
|
100
|
+
ref: `heads/${ref}`,
|
|
101
|
+
request: { signal },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Already gone, protected, or unreachable: the fold stands either way.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The fold's message rides on the pull request, invisibly, from the moment it
|
|
110
|
+
* is opened: subject line first, then the body. `fold` reads it back here.
|
|
111
|
+
*/
|
|
112
|
+
const COMMIT_MESSAGE_OPEN = "<!-- commit-message\n";
|
|
113
|
+
const COMMIT_MESSAGE_CLOSE = "\n-->";
|
|
114
|
+
/** `commit_title` and `commit_message` for the squash, from what the pull request carries. */
|
|
115
|
+
export function commitOf(pullTitle, pullBody) {
|
|
116
|
+
const closes = /^Closes #\d+$/m.exec(pullBody)?.[0];
|
|
117
|
+
const start = pullBody.indexOf(COMMIT_MESSAGE_OPEN);
|
|
118
|
+
const end = start < 0 ? -1 : pullBody.indexOf(COMMIT_MESSAGE_CLOSE, start);
|
|
119
|
+
if (start < 0 || end < 0) {
|
|
120
|
+
return { commit_title: pullTitle, commit_message: closes ?? "" };
|
|
121
|
+
}
|
|
122
|
+
const stored = pullBody.slice(start + COMMIT_MESSAGE_OPEN.length, end).trim();
|
|
123
|
+
const [subject, ...rest] = stored.split("\n");
|
|
124
|
+
const body = rest.join("\n").trim();
|
|
125
|
+
const withClose = [body, closes].filter((part) => part !== undefined && part.length > 0);
|
|
126
|
+
return {
|
|
127
|
+
commit_title: subject?.trim() || pullTitle,
|
|
128
|
+
commit_message: withClose.join("\n\n"),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The issue's title, made a pull request title: no trailing full stop, and
|
|
133
|
+
* the issue's number where GitHub links it.
|
|
134
|
+
*/
|
|
135
|
+
export function titleOf(input) {
|
|
136
|
+
const issue = issueNumberFromExternalId(input.key);
|
|
137
|
+
const base = (input.title ?? "").trim().replace(/[.\s]+$/, "");
|
|
138
|
+
const title = base.length > 0 ? base : `${PRODUCT} ${input.key}`;
|
|
139
|
+
return issue === undefined ? title : `${title} (#${issue})`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* What the pull request delivers, from what was asked and what was planned.
|
|
143
|
+
* Nothing here is generated: the intention is the human's words, the steps are
|
|
144
|
+
* the Plan's. `Closes #N` lets GitHub close the issue when this is merged.
|
|
145
|
+
*/
|
|
146
|
+
export function bodyOf(input) {
|
|
147
|
+
const sections = [];
|
|
148
|
+
// What the reader sees first: the Project's words when a Describer gave
|
|
149
|
+
// them, else what the human asked, as they wrote it.
|
|
150
|
+
const slotBody = input.description?.body?.trim() ?? "";
|
|
151
|
+
const intention = input.intention?.trim() ?? "";
|
|
152
|
+
const description = slotBody.length > 0 ? slotBody : intention;
|
|
153
|
+
if (description.length > 0) {
|
|
154
|
+
sections.push(description);
|
|
155
|
+
}
|
|
156
|
+
if (input.steps !== undefined && input.steps.length > 0) {
|
|
157
|
+
sections.push(["## Changes", ...input.steps.map((line, at) => `${at + 1}. ${line}`)].join("\n"));
|
|
158
|
+
}
|
|
159
|
+
const issue = issueNumberFromExternalId(input.key);
|
|
160
|
+
sections.push(issue === undefined ? `Key: \`${input.key}\`` : `Closes #${issue}`);
|
|
161
|
+
// The fold's message, decided now and kept here: the Describer's words, or
|
|
162
|
+
// the title and the intention — the human's own — when there is no slot.
|
|
163
|
+
const subject = input.description?.subject.trim() || titleOf(input);
|
|
164
|
+
const stored = [subject, description].filter((part) => part.length > 0).join("\n\n");
|
|
165
|
+
sections.push(`${COMMIT_MESSAGE_OPEN}${stored}${COMMIT_MESSAGE_CLOSE}`);
|
|
166
|
+
return sections.join("\n\n");
|
|
167
|
+
}
|
|
168
|
+
async function openPullRequestFor(head, context) {
|
|
169
|
+
const call = callSignal(context.deadlineMs, context.now, context.shouldInterrupt);
|
|
170
|
+
try {
|
|
171
|
+
const response = await context.github.request("GET /repos/{owner}/{repo}/pulls", {
|
|
172
|
+
owner: context.repo.owner,
|
|
173
|
+
repo: context.repo.name,
|
|
174
|
+
head: `${context.repo.owner}:${head}`,
|
|
175
|
+
state: "open",
|
|
176
|
+
per_page: 1,
|
|
177
|
+
request: { signal: call.signal },
|
|
178
|
+
});
|
|
179
|
+
const first = response.data[0];
|
|
180
|
+
return first === undefined ? { kind: "none" } : { kind: "found", number: first.number };
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return { kind: "unavailable" };
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
call.release();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=submission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/submission/submission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a human wrote on the issue: title, body, state, and the labels that are
|
|
3
|
+
* not this manager's own. A comment or a state label moves `updated_at`, and
|
|
4
|
+
* neither is a change to the intention.
|
|
5
|
+
*/
|
|
6
|
+
export declare function writtenFingerprint(payload: Record<string, unknown>, stateLabelPrefix: string | undefined): string;
|
|
7
|
+
//# sourceMappingURL=written-fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"written-fingerprint.d.ts","sourceRoot":"","sources":["../src/written-fingerprint.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CAcR"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { fingerprintOf } from "./adapter/normalize/fingerprint.js";
|
|
2
|
+
/**
|
|
3
|
+
* What a human wrote on the issue: title, body, state, and the labels that are
|
|
4
|
+
* not this manager's own. A comment or a state label moves `updated_at`, and
|
|
5
|
+
* neither is a change to the intention.
|
|
6
|
+
*/
|
|
7
|
+
export function writtenFingerprint(payload, stateLabelPrefix) {
|
|
8
|
+
const labels = labelNames(payload)
|
|
9
|
+
.filter((name) => stateLabelPrefix === undefined ||
|
|
10
|
+
!name.toLowerCase().startsWith(stateLabelPrefix.toLowerCase()))
|
|
11
|
+
.sort();
|
|
12
|
+
return fingerprintOf({
|
|
13
|
+
title: payload.title,
|
|
14
|
+
body: payload.body,
|
|
15
|
+
state: payload.state,
|
|
16
|
+
labels,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function labelNames(payload) {
|
|
20
|
+
const labels = payload.labels;
|
|
21
|
+
if (!Array.isArray(labels)) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const names = [];
|
|
25
|
+
for (const entry of labels) {
|
|
26
|
+
if (typeof entry === "string") {
|
|
27
|
+
names.push(entry);
|
|
28
|
+
}
|
|
29
|
+
else if (entry !== null && typeof entry === "object" && "name" in entry) {
|
|
30
|
+
const name = entry.name;
|
|
31
|
+
if (typeof name === "string") {
|
|
32
|
+
names.push(name);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return names;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=written-fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"written-fingerprint.js","sourceRoot":"","sources":["../src/written-fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAEnE;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAgC,EAChC,gBAAoC;IAEpC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC;SAC/B,MAAM,CACL,CAAC,IAAI,EAAE,EAAE,CACP,gBAAgB,KAAK,SAAS;QAC9B,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CACjE;SACA,IAAI,EAAE,CAAC;IACV,OAAO,aAAa,CAAC;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,OAAgC;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YAC1E,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;YAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bluewombat/manager-github",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "GitHub Issues FeatureManager: issues in, comments and labels out; pull requests as Authority.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"mason",
|
|
8
|
+
"bluewombat",
|
|
9
|
+
"mason-manager",
|
|
10
|
+
"github"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"homepage": "https://github.com/tilap/bluewombat/tree/main/packages/plugins/manager-github#readme",
|
|
14
|
+
"bugs": "https://github.com/tilap/bluewombat/issues",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/tilap/bluewombat.git",
|
|
18
|
+
"directory": "packages/plugins/manager-github"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"SPECS.md"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=24.20.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"lint": "biome check .",
|
|
40
|
+
"format": "biome check --write .",
|
|
41
|
+
"tsc": "tsc --noEmit",
|
|
42
|
+
"test": "tsx --test $(find src -name '*.test.ts')",
|
|
43
|
+
"build": "tsc -p tsconfig.build.json"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@bluewombat/manager-kit": "^0.1.0",
|
|
47
|
+
"@octokit/core": "^7.0.8",
|
|
48
|
+
"@octokit/plugin-retry": "^8.1.1",
|
|
49
|
+
"@octokit/plugin-throttling": "^11.0.5"
|
|
50
|
+
}
|
|
51
|
+
}
|