@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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one effect this package has on the outside world: HTTPS requests to the
|
|
3
|
+
* GitHub REST API, authenticated by a token.
|
|
4
|
+
*
|
|
5
|
+
* The transport is `@octokit/core` with its retry and throttling plugins — not
|
|
6
|
+
* a hand-written HTTP client. What lives here is only what this package owes on
|
|
7
|
+
* top of it: a token in one place, the wait budget of one invocation, and the
|
|
8
|
+
* mapping from a failure to this package's own vocabulary.
|
|
9
|
+
*/
|
|
10
|
+
import { Octokit } from "@octokit/core";
|
|
11
|
+
declare const GithubOctokit: typeof Octokit & import("@octokit/core/types").Constructor<import("@octokit/plugin-retry").RetryPlugin>;
|
|
12
|
+
/** The authenticated channel. Injected, so a run is testable with no network. */
|
|
13
|
+
export type GithubClient = InstanceType<typeof GithubOctokit>;
|
|
14
|
+
/** Identifies the caller to GitHub; the API rejects a request without one. */
|
|
15
|
+
export declare const USER_AGENT = "bluewombat-manager-github";
|
|
16
|
+
export type ClientOptions = {
|
|
17
|
+
/** The token lives here and nowhere else: not in an Invocation, not in a line. */
|
|
18
|
+
token: string;
|
|
19
|
+
apiBase: string;
|
|
20
|
+
/** Extra attempts after the first, on a transport failure, a 5xx, or a rate limit. */
|
|
21
|
+
requestRetries: number;
|
|
22
|
+
/** Absolute time no wait may run past. */
|
|
23
|
+
deadlineMs: number;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
shouldInterrupt?: () => boolean;
|
|
26
|
+
/** Replaces the network in tests. */
|
|
27
|
+
fetch?: typeof globalThis.fetch;
|
|
28
|
+
/**
|
|
29
|
+
* Space writes out the way GitHub asks, and wait out a rate limit. On by
|
|
30
|
+
* default. Turning it off is a test seam: it also gives up the waiting, so a
|
|
31
|
+
* real run must leave it alone.
|
|
32
|
+
*/
|
|
33
|
+
throttle?: boolean;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Build the channel. Retrying a 5xx and honouring a rate limit are the
|
|
37
|
+
* plugins'; deciding that a wait would outlive this invocation is ours, because
|
|
38
|
+
* only this package knows what the duration budget promised.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createClient(options: ClientOptions): GithubClient;
|
|
41
|
+
export declare function trimBase(apiBase: string): string;
|
|
42
|
+
export type Failure = {
|
|
43
|
+
/** A refusal that will not change on a retry: a 404 does not become a 200. */
|
|
44
|
+
permanent: boolean;
|
|
45
|
+
status?: number;
|
|
46
|
+
detail: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Read what went wrong. Anything that reached here already exhausted the
|
|
50
|
+
* plugins' retries, so the question left is only whether retrying *later*
|
|
51
|
+
* could help.
|
|
52
|
+
*/
|
|
53
|
+
export declare function readFailure(error: unknown): Failure;
|
|
54
|
+
export type Call = {
|
|
55
|
+
/** Aborts on the duration clock, and on a stop signal. */
|
|
56
|
+
signal: AbortSignal;
|
|
57
|
+
/** Always call it: the interrupt poll would otherwise hold the process open. */
|
|
58
|
+
release: () => void;
|
|
59
|
+
};
|
|
60
|
+
/** The bound every single request runs under. */
|
|
61
|
+
export declare function callSignal(deadlineMs: number, now: () => number, shouldInterrupt: () => boolean): Call;
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAIxC,QAAA,MAAM,aAAa,yGAAoC,CAAC;AAExD,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAE9D,8EAA8E;AAC9E,eAAO,MAAM,UAAU,8BAA8B,CAAC;AAEtD,MAAM,MAAM,aAAa,GAAG;IAC1B,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC;IAChC,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAwBjE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnD;AAsBD,MAAM,MAAM,IAAI,GAAG;IACjB,0DAA0D;IAC1D,MAAM,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,iDAAiD;AACjD,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,MAAM,EACjB,eAAe,EAAE,MAAM,OAAO,GAC7B,IAAI,CAYN"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one effect this package has on the outside world: HTTPS requests to the
|
|
3
|
+
* GitHub REST API, authenticated by a token.
|
|
4
|
+
*
|
|
5
|
+
* The transport is `@octokit/core` with its retry and throttling plugins — not
|
|
6
|
+
* a hand-written HTTP client. What lives here is only what this package owes on
|
|
7
|
+
* top of it: a token in one place, the wait budget of one invocation, and the
|
|
8
|
+
* mapping from a failure to this package's own vocabulary.
|
|
9
|
+
*/
|
|
10
|
+
import { Octokit } from "@octokit/core";
|
|
11
|
+
import { retry } from "@octokit/plugin-retry";
|
|
12
|
+
import { throttling } from "@octokit/plugin-throttling";
|
|
13
|
+
const GithubOctokit = Octokit.plugin(retry, throttling);
|
|
14
|
+
/** Identifies the caller to GitHub; the API rejects a request without one. */
|
|
15
|
+
export const USER_AGENT = "bluewombat-manager-github";
|
|
16
|
+
/**
|
|
17
|
+
* Build the channel. Retrying a 5xx and honouring a rate limit are the
|
|
18
|
+
* plugins'; deciding that a wait would outlive this invocation is ours, because
|
|
19
|
+
* only this package knows what the duration budget promised.
|
|
20
|
+
*/
|
|
21
|
+
export function createClient(options) {
|
|
22
|
+
const now = options.now ?? (() => Date.now());
|
|
23
|
+
const shouldInterrupt = options.shouldInterrupt ?? (() => false);
|
|
24
|
+
const mayWait = (retryAfterSeconds, retryCount) => {
|
|
25
|
+
if (shouldInterrupt() || retryCount >= options.requestRetries) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return now() + retryAfterSeconds * 1_000 < options.deadlineMs;
|
|
29
|
+
};
|
|
30
|
+
return new GithubOctokit({
|
|
31
|
+
auth: options.token,
|
|
32
|
+
baseUrl: trimBase(options.apiBase),
|
|
33
|
+
userAgent: USER_AGENT,
|
|
34
|
+
retry: { retries: options.requestRetries },
|
|
35
|
+
throttle: {
|
|
36
|
+
enabled: options.throttle ?? true,
|
|
37
|
+
onRateLimit: (retryAfter, _options, _octokit, retryCount) => mayWait(retryAfter, retryCount),
|
|
38
|
+
onSecondaryRateLimit: (retryAfter, _options, _octokit, retryCount) => mayWait(retryAfter, retryCount),
|
|
39
|
+
},
|
|
40
|
+
...(options.fetch !== undefined ? { request: { fetch: options.fetch } } : {}),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export function trimBase(apiBase) {
|
|
44
|
+
return apiBase.replace(/\/+$/, "");
|
|
45
|
+
}
|
|
46
|
+
const DETAIL_LIMIT = 512;
|
|
47
|
+
/**
|
|
48
|
+
* Read what went wrong. Anything that reached here already exhausted the
|
|
49
|
+
* plugins' retries, so the question left is only whether retrying *later*
|
|
50
|
+
* could help.
|
|
51
|
+
*/
|
|
52
|
+
export function readFailure(error) {
|
|
53
|
+
const status = statusOf(error);
|
|
54
|
+
const detail = truncate(messageOf(error));
|
|
55
|
+
if (status === undefined) {
|
|
56
|
+
return { permanent: false, detail };
|
|
57
|
+
}
|
|
58
|
+
if (status === 429 || (status === 403 && rateLimitSpent(error))) {
|
|
59
|
+
return { permanent: false, status, detail: `Rate limited (${status}). ${detail}`.trim() };
|
|
60
|
+
}
|
|
61
|
+
if (status >= 500) {
|
|
62
|
+
return { permanent: false, status, detail };
|
|
63
|
+
}
|
|
64
|
+
return { permanent: true, status, detail };
|
|
65
|
+
}
|
|
66
|
+
/** A 403 with the budget spent is a wait the invocation declined, not a refusal. */
|
|
67
|
+
function rateLimitSpent(error) {
|
|
68
|
+
const headers = error?.response
|
|
69
|
+
?.headers;
|
|
70
|
+
return headers?.["x-ratelimit-remaining"] === "0";
|
|
71
|
+
}
|
|
72
|
+
function statusOf(error) {
|
|
73
|
+
const status = error?.status;
|
|
74
|
+
return typeof status === "number" ? status : undefined;
|
|
75
|
+
}
|
|
76
|
+
function messageOf(error) {
|
|
77
|
+
return error instanceof Error ? error.message : String(error);
|
|
78
|
+
}
|
|
79
|
+
function truncate(text) {
|
|
80
|
+
return text.length <= DETAIL_LIMIT ? text : `${text.slice(0, DETAIL_LIMIT)}…[truncated]`;
|
|
81
|
+
}
|
|
82
|
+
/** The bound every single request runs under. */
|
|
83
|
+
export function callSignal(deadlineMs, now, shouldInterrupt) {
|
|
84
|
+
const controller = new AbortController();
|
|
85
|
+
const poll = setInterval(() => {
|
|
86
|
+
if (shouldInterrupt()) {
|
|
87
|
+
controller.abort();
|
|
88
|
+
}
|
|
89
|
+
}, 20);
|
|
90
|
+
const signal = AbortSignal.any([
|
|
91
|
+
controller.signal,
|
|
92
|
+
AbortSignal.timeout(Math.max(1, deadlineMs - now())),
|
|
93
|
+
]);
|
|
94
|
+
return { signal, release: () => clearInterval(poll) };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CreateManagerResult, type Finding, type ManagerContext, type ManagerQuestion, type ManagerScaffold, type SetupResult } from "@bluewombat/manager-kit";
|
|
2
|
+
export { issueNumberFromExternalId, issueNumberFromPayload } from "./issue-number.js";
|
|
3
|
+
export { payloadHasLabel } from "./labels.js";
|
|
4
|
+
export type { GithubManagerOptions } from "./manager.js";
|
|
5
|
+
export { createGithubManager, DEFAULT_API_BASE, DEFAULT_PRIORITY, DEFAULT_READY_LABEL, DEFAULT_TOKEN_ENV, } from "./manager.js";
|
|
6
|
+
export { parseRepo, type Repository } from "./repo.js";
|
|
7
|
+
export { type SetupSettings, wantedLabels } from "./setup.js";
|
|
8
|
+
/** What `mason init` asks when it runs at a terminal. */
|
|
9
|
+
export declare function questionsManager(): ManagerQuestion[];
|
|
10
|
+
/**
|
|
11
|
+
* `mason setup`. The only entry point of this package that writes to GitHub
|
|
12
|
+
* before a run: it creates the labels the configuration names, once `apply` is
|
|
13
|
+
* asked for.
|
|
14
|
+
*/
|
|
15
|
+
export declare function setupManager(context: ManagerContext, input: {
|
|
16
|
+
apply: boolean;
|
|
17
|
+
}): Promise<SetupResult>;
|
|
18
|
+
export declare const DEFAULT_BRANCH = "main";
|
|
19
|
+
export declare const DEFAULT_GIT_HOST = "github.com";
|
|
20
|
+
/**
|
|
21
|
+
* `manager: "@bluewombat/manager-github"` in the config resolves here. The token
|
|
22
|
+
* is read from the environment by this package: Host never handles a secret.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createManager(context: ManagerContext): CreateManagerResult;
|
|
25
|
+
/**
|
|
26
|
+
* What `mason init` writes. Labels are not created here: that would need the
|
|
27
|
+
* network, and a missing label is a repository fact the operator still owns.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scaffoldManager(context: ManagerContext): ManagerScaffold;
|
|
30
|
+
/** What `mason doctor` reports. Options and environment only, no network. */
|
|
31
|
+
export declare function checkManager(context: ManagerContext): Finding[];
|
|
32
|
+
/** `Name <email>`, the form `git log` prints. */
|
|
33
|
+
export declare function parseAuthor(text: string): {
|
|
34
|
+
ok: true;
|
|
35
|
+
value: {
|
|
36
|
+
name: string;
|
|
37
|
+
email: string;
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
reason: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Where the reference work line is: the repository's own git remote, and the
|
|
45
|
+
* branch pull requests are opened onto. Host keeps a copy of it; these are the
|
|
46
|
+
* words `@bluewombat/isolation-git` reads.
|
|
47
|
+
*
|
|
48
|
+
* Over HTTPS by default, authenticated with the same token as the API —
|
|
49
|
+
* `credentialEnv` names the variable, and the strategy reads it when git asks,
|
|
50
|
+
* so nothing lands in a `.git/config` on disk and the pushes are the token's
|
|
51
|
+
* account, not the machine's SSH key. `remote` overrides the URL (SSH, a
|
|
52
|
+
* mirror, GitHub Enterprise). `author` is who the system is on its commits.
|
|
53
|
+
*/
|
|
54
|
+
export declare function referenceManager(context: ManagerContext): Record<string, unknown> | undefined;
|
|
55
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,OAAO,EAEZ,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,EAGpB,KAAK,WAAW,EAGjB,MAAM,yBAAyB,CAAC;AAWjC,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,yDAAyD;AACzD,wBAAgB,gBAAgB,IAAI,eAAe,EAAE,CA4BpD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GACxB,OAAO,CAAC,WAAW,CAAC,CA0CtB;AAmBD,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAuB7C;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,mBAAmB,CA0C1E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CA0BxE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,EAAE,CAwD/D;AA+FD,iDAAiD;AACjD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GACX;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAStF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAY7F"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { booleanOption, intOption, PRODUCT, rejectUnknownOptions, stringArrayOption, stringOption, } from "@bluewombat/manager-kit";
|
|
2
|
+
import { createGithubManager, DEFAULT_API_BASE, DEFAULT_READY_LABEL, DEFAULT_TOKEN_ENV, } from "./manager.js";
|
|
3
|
+
import { parseRepo } from "./repo.js";
|
|
4
|
+
import { runSetup } from "./setup.js";
|
|
5
|
+
export { issueNumberFromExternalId, issueNumberFromPayload } from "./issue-number.js";
|
|
6
|
+
export { payloadHasLabel } from "./labels.js";
|
|
7
|
+
export { createGithubManager, DEFAULT_API_BASE, DEFAULT_PRIORITY, DEFAULT_READY_LABEL, DEFAULT_TOKEN_ENV, } from "./manager.js";
|
|
8
|
+
export { parseRepo } from "./repo.js";
|
|
9
|
+
export { wantedLabels } from "./setup.js";
|
|
10
|
+
/** What `mason init` asks when it runs at a terminal. */
|
|
11
|
+
export function questionsManager() {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
key: "repo",
|
|
15
|
+
prompt: "GitHub repository (owner/name)",
|
|
16
|
+
required: true,
|
|
17
|
+
parse: (answer) => parseRepo(answer) === null
|
|
18
|
+
? { ok: false, reason: `"${answer}" is not owner/name.` }
|
|
19
|
+
: { ok: true, value: answer },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: "labels",
|
|
23
|
+
prompt: "Label an issue must carry to be picked up",
|
|
24
|
+
fallback: PRODUCT,
|
|
25
|
+
parse: (answer) => ({ ok: true, value: [answer] }),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: "defaultProject",
|
|
29
|
+
prompt: "Project name for issues with no project: label",
|
|
30
|
+
fallback: "app",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: "tokenEnv",
|
|
34
|
+
prompt: "Environment variable holding the token",
|
|
35
|
+
fallback: DEFAULT_TOKEN_ENV,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `mason setup`. The only entry point of this package that writes to GitHub
|
|
41
|
+
* before a run: it creates the labels the configuration names, once `apply` is
|
|
42
|
+
* asked for.
|
|
43
|
+
*/
|
|
44
|
+
export async function setupManager(context, input) {
|
|
45
|
+
const read = readOptions(context);
|
|
46
|
+
if (!read.ok) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
steps: [
|
|
50
|
+
{ id: "options", summary: "read managerOptions", state: "blocked", detail: read.reason },
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const settings = read.settings;
|
|
55
|
+
const token = settings.token ?? context.env[settings.tokenEnv];
|
|
56
|
+
if (token === undefined || token.trim().length === 0) {
|
|
57
|
+
return {
|
|
58
|
+
ok: false,
|
|
59
|
+
steps: [
|
|
60
|
+
{
|
|
61
|
+
id: "token",
|
|
62
|
+
summary: "a token to talk to GitHub",
|
|
63
|
+
state: "blocked",
|
|
64
|
+
detail: `${settings.tokenEnv} is not set.`,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return await runSetup({
|
|
70
|
+
repo: settings.repo,
|
|
71
|
+
token,
|
|
72
|
+
apiBase: settings.apiBase,
|
|
73
|
+
readyLabel: settings.readyLabel,
|
|
74
|
+
labels: settings.labels,
|
|
75
|
+
defaultProject: settings.defaultProject,
|
|
76
|
+
stateLabelPrefix: settings.stateLabelPrefix,
|
|
77
|
+
branch: settings.branch,
|
|
78
|
+
branchConfigured: typeof context.options.branch === "string",
|
|
79
|
+
durationMs: context.durationMs,
|
|
80
|
+
interruptFlag: context.interruptFlag,
|
|
81
|
+
githubFetch: settings.githubFetch,
|
|
82
|
+
}, input);
|
|
83
|
+
}
|
|
84
|
+
const KNOWN_OPTIONS = [
|
|
85
|
+
"repo",
|
|
86
|
+
"token",
|
|
87
|
+
"tokenEnv",
|
|
88
|
+
"apiBase",
|
|
89
|
+
"labels",
|
|
90
|
+
"defaultProject",
|
|
91
|
+
"readyLabel",
|
|
92
|
+
"defaultPriority",
|
|
93
|
+
"stateLabelPrefix",
|
|
94
|
+
"branch",
|
|
95
|
+
"remote",
|
|
96
|
+
"commitAuthor",
|
|
97
|
+
"keepBranch",
|
|
98
|
+
"fetch",
|
|
99
|
+
];
|
|
100
|
+
export const DEFAULT_BRANCH = "main";
|
|
101
|
+
export const DEFAULT_GIT_HOST = "github.com";
|
|
102
|
+
/**
|
|
103
|
+
* `manager: "@bluewombat/manager-github"` in the config resolves here. The token
|
|
104
|
+
* is read from the environment by this package: Host never handles a secret.
|
|
105
|
+
*/
|
|
106
|
+
export function createManager(context) {
|
|
107
|
+
const read = readOptions(context);
|
|
108
|
+
if (!read.ok) {
|
|
109
|
+
return read;
|
|
110
|
+
}
|
|
111
|
+
const settings = read.settings;
|
|
112
|
+
const token = settings.token ?? context.env[settings.tokenEnv];
|
|
113
|
+
if (token === undefined || token.trim().length === 0) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
reason: `GitHub needs a token in ${settings.tokenEnv}. ` +
|
|
117
|
+
'Set the variable, or name another one with managerOptions "tokenEnv".',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const options = {
|
|
121
|
+
repo: settings.repo,
|
|
122
|
+
token,
|
|
123
|
+
durationMs: context.durationMs,
|
|
124
|
+
interruptFlag: context.interruptFlag,
|
|
125
|
+
apiBase: settings.apiBase,
|
|
126
|
+
readyLabel: settings.readyLabel,
|
|
127
|
+
};
|
|
128
|
+
if (settings.labels !== undefined) {
|
|
129
|
+
options.labels = settings.labels;
|
|
130
|
+
}
|
|
131
|
+
if (settings.defaultProject !== undefined) {
|
|
132
|
+
options.defaultProject = settings.defaultProject;
|
|
133
|
+
}
|
|
134
|
+
if (settings.defaultPriority !== undefined) {
|
|
135
|
+
options.defaultPriority = settings.defaultPriority;
|
|
136
|
+
}
|
|
137
|
+
if (settings.stateLabelPrefix !== undefined) {
|
|
138
|
+
options.stateLabelPrefix = settings.stateLabelPrefix;
|
|
139
|
+
}
|
|
140
|
+
if (settings.keepBranch !== undefined) {
|
|
141
|
+
options.keepBranch = settings.keepBranch;
|
|
142
|
+
}
|
|
143
|
+
if (settings.githubFetch !== undefined) {
|
|
144
|
+
options.githubFetch = settings.githubFetch;
|
|
145
|
+
}
|
|
146
|
+
return { ok: true, manager: createGithubManager(options) };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* What `mason init` writes. Labels are not created here: that would need the
|
|
150
|
+
* network, and a missing label is a repository fact the operator still owns.
|
|
151
|
+
*/
|
|
152
|
+
export function scaffoldManager(context) {
|
|
153
|
+
const repo = typeof context.options.repo === "string" ? context.options.repo : "OWNER/REPO";
|
|
154
|
+
// The variable the operator just named, not the default: `init` calls this
|
|
155
|
+
// again with the answers in hand so its next steps do not demand something
|
|
156
|
+
// else than what was typed.
|
|
157
|
+
const tokenEnv = typeof context.options.tokenEnv === "string" && context.options.tokenEnv.length > 0
|
|
158
|
+
? context.options.tokenEnv
|
|
159
|
+
: DEFAULT_TOKEN_ENV;
|
|
160
|
+
// `mason setup` creates the labels, so nothing here asks for that by hand.
|
|
161
|
+
const nextSteps = [`${tokenEnv} — a token with the repo scope, exported in this shell`];
|
|
162
|
+
if (repo === "OWNER/REPO") {
|
|
163
|
+
nextSteps.unshift("managerOptions.repo — set it to owner/name (or pass --manager-option repo=owner/name)");
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
options: {
|
|
167
|
+
repo,
|
|
168
|
+
tokenEnv,
|
|
169
|
+
labels: [PRODUCT],
|
|
170
|
+
readyLabel: "ready",
|
|
171
|
+
defaultProject: "app",
|
|
172
|
+
},
|
|
173
|
+
nextSteps,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/** What `mason doctor` reports. Options and environment only, no network. */
|
|
177
|
+
export function checkManager(context) {
|
|
178
|
+
const read = readOptions(context);
|
|
179
|
+
if (!read.ok) {
|
|
180
|
+
return [{ level: "fail", label: "manager options", detail: read.reason }];
|
|
181
|
+
}
|
|
182
|
+
const settings = read.settings;
|
|
183
|
+
const token = settings.token ?? context.env[settings.tokenEnv];
|
|
184
|
+
const findings = [
|
|
185
|
+
{
|
|
186
|
+
level: "ok",
|
|
187
|
+
label: "repository",
|
|
188
|
+
detail: `${settings.repo.owner}/${settings.repo.name}`,
|
|
189
|
+
},
|
|
190
|
+
token === undefined || token.trim().length === 0
|
|
191
|
+
? { level: "fail", label: "token", detail: `${settings.tokenEnv} is not set` }
|
|
192
|
+
: { level: "ok", label: "token", detail: `${settings.tokenEnv} is set` },
|
|
193
|
+
];
|
|
194
|
+
if (settings.labels === undefined || settings.labels.length === 0) {
|
|
195
|
+
findings.push({
|
|
196
|
+
level: "warn",
|
|
197
|
+
label: "labels",
|
|
198
|
+
detail: "every open issue is admitted; set labels to narrow the Source",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
findings.push({ level: "ok", label: "labels", detail: settings.labels.join(", ") });
|
|
203
|
+
}
|
|
204
|
+
findings.push(settings.commitAuthor === undefined
|
|
205
|
+
? {
|
|
206
|
+
level: "warn",
|
|
207
|
+
label: "commit author",
|
|
208
|
+
detail: "no \"commitAuthor\": commits will carry this machine's git identity, not the system's",
|
|
209
|
+
}
|
|
210
|
+
: {
|
|
211
|
+
level: "ok",
|
|
212
|
+
label: "commit author",
|
|
213
|
+
detail: `${settings.commitAuthor.name} <${settings.commitAuthor.email}>`,
|
|
214
|
+
});
|
|
215
|
+
findings.push(settings.remote.startsWith("https://")
|
|
216
|
+
? {
|
|
217
|
+
level: "ok",
|
|
218
|
+
label: "git remote",
|
|
219
|
+
detail: `${settings.remote} — with ${settings.tokenEnv}`,
|
|
220
|
+
}
|
|
221
|
+
: {
|
|
222
|
+
level: "warn",
|
|
223
|
+
label: "git remote",
|
|
224
|
+
detail: `${settings.remote} — not HTTPS, so git authenticates with this machine's keys, not the token`,
|
|
225
|
+
});
|
|
226
|
+
// Whether the repository has the labels is `mason setup`'s question: doctor
|
|
227
|
+
// stays offline and does not guess.
|
|
228
|
+
return findings;
|
|
229
|
+
}
|
|
230
|
+
function readOptions(context) {
|
|
231
|
+
const known = rejectUnknownOptions(context.options, KNOWN_OPTIONS);
|
|
232
|
+
if (!known.ok) {
|
|
233
|
+
return known;
|
|
234
|
+
}
|
|
235
|
+
const repoRaw = stringOption(context.options, "repo");
|
|
236
|
+
if (!repoRaw.ok) {
|
|
237
|
+
return repoRaw;
|
|
238
|
+
}
|
|
239
|
+
if (repoRaw.value === undefined) {
|
|
240
|
+
return { ok: false, reason: 'managerOptions "repo" is required (owner/name).' };
|
|
241
|
+
}
|
|
242
|
+
const repo = parseRepo(repoRaw.value);
|
|
243
|
+
if (repo === null) {
|
|
244
|
+
return { ok: false, reason: 'managerOptions "repo" must be owner/name.' };
|
|
245
|
+
}
|
|
246
|
+
const token = stringOption(context.options, "token");
|
|
247
|
+
if (!token.ok) {
|
|
248
|
+
return token;
|
|
249
|
+
}
|
|
250
|
+
const tokenEnv = stringOption(context.options, "tokenEnv");
|
|
251
|
+
if (!tokenEnv.ok) {
|
|
252
|
+
return tokenEnv;
|
|
253
|
+
}
|
|
254
|
+
const apiBase = stringOption(context.options, "apiBase");
|
|
255
|
+
if (!apiBase.ok) {
|
|
256
|
+
return apiBase;
|
|
257
|
+
}
|
|
258
|
+
const labels = stringArrayOption(context.options, "labels");
|
|
259
|
+
if (!labels.ok) {
|
|
260
|
+
return labels;
|
|
261
|
+
}
|
|
262
|
+
const defaultProject = stringOption(context.options, "defaultProject");
|
|
263
|
+
if (!defaultProject.ok) {
|
|
264
|
+
return defaultProject;
|
|
265
|
+
}
|
|
266
|
+
const readyLabel = stringOption(context.options, "readyLabel");
|
|
267
|
+
if (!readyLabel.ok) {
|
|
268
|
+
return readyLabel;
|
|
269
|
+
}
|
|
270
|
+
const defaultPriority = intOption(context.options, "defaultPriority", 0, 100);
|
|
271
|
+
if (!defaultPriority.ok) {
|
|
272
|
+
return defaultPriority;
|
|
273
|
+
}
|
|
274
|
+
const stateLabelPrefix = stringOption(context.options, "stateLabelPrefix");
|
|
275
|
+
if (!stateLabelPrefix.ok) {
|
|
276
|
+
return stateLabelPrefix;
|
|
277
|
+
}
|
|
278
|
+
const branch = stringOption(context.options, "branch");
|
|
279
|
+
if (!branch.ok) {
|
|
280
|
+
return branch;
|
|
281
|
+
}
|
|
282
|
+
const remote = stringOption(context.options, "remote");
|
|
283
|
+
if (!remote.ok) {
|
|
284
|
+
return remote;
|
|
285
|
+
}
|
|
286
|
+
const commitAuthor = stringOption(context.options, "commitAuthor");
|
|
287
|
+
if (!commitAuthor.ok) {
|
|
288
|
+
return commitAuthor;
|
|
289
|
+
}
|
|
290
|
+
const author = commitAuthor.value === undefined ? undefined : parseAuthor(commitAuthor.value);
|
|
291
|
+
if (author !== undefined && !author.ok) {
|
|
292
|
+
return author;
|
|
293
|
+
}
|
|
294
|
+
const keepBranch = booleanOption(context.options, "keepBranch");
|
|
295
|
+
if (!keepBranch.ok) {
|
|
296
|
+
return keepBranch;
|
|
297
|
+
}
|
|
298
|
+
const candidateFetch = context.options.fetch;
|
|
299
|
+
if (candidateFetch !== undefined && typeof candidateFetch !== "function") {
|
|
300
|
+
return { ok: false, reason: 'managerOptions "fetch" must be a function (tests only).' };
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
ok: true,
|
|
304
|
+
settings: {
|
|
305
|
+
repo,
|
|
306
|
+
token: token.value,
|
|
307
|
+
tokenEnv: tokenEnv.value ?? DEFAULT_TOKEN_ENV,
|
|
308
|
+
apiBase: apiBase.value ?? DEFAULT_API_BASE,
|
|
309
|
+
readyLabel: readyLabel.value ?? DEFAULT_READY_LABEL,
|
|
310
|
+
labels: labels.value,
|
|
311
|
+
defaultProject: defaultProject.value,
|
|
312
|
+
defaultPriority: defaultPriority.value,
|
|
313
|
+
stateLabelPrefix: stateLabelPrefix.value,
|
|
314
|
+
branch: branch.value ?? DEFAULT_BRANCH,
|
|
315
|
+
remote: remote.value ?? `https://${DEFAULT_GIT_HOST}/${repo.owner}/${repo.name}.git`,
|
|
316
|
+
commitAuthor: author?.value,
|
|
317
|
+
keepBranch: keepBranch.value,
|
|
318
|
+
githubFetch: candidateFetch,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/** `Name <email>`, the form `git log` prints. */
|
|
323
|
+
export function parseAuthor(text) {
|
|
324
|
+
const match = /^\s*(.+?)\s*<([^<>\s]+@[^<>\s]+)>\s*$/.exec(text);
|
|
325
|
+
if (match?.[1] === undefined || match[2] === undefined) {
|
|
326
|
+
return {
|
|
327
|
+
ok: false,
|
|
328
|
+
reason: `managerOptions "commitAuthor" must read "Name <email>", e.g. "${PRODUCT} <${PRODUCT}@example.com>".`,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return { ok: true, value: { name: match[1], email: match[2] } };
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Where the reference work line is: the repository's own git remote, and the
|
|
335
|
+
* branch pull requests are opened onto. Host keeps a copy of it; these are the
|
|
336
|
+
* words `@bluewombat/isolation-git` reads.
|
|
337
|
+
*
|
|
338
|
+
* Over HTTPS by default, authenticated with the same token as the API —
|
|
339
|
+
* `credentialEnv` names the variable, and the strategy reads it when git asks,
|
|
340
|
+
* so nothing lands in a `.git/config` on disk and the pushes are the token's
|
|
341
|
+
* account, not the machine's SSH key. `remote` overrides the URL (SSH, a
|
|
342
|
+
* mirror, GitHub Enterprise). `author` is who the system is on its commits.
|
|
343
|
+
*/
|
|
344
|
+
export function referenceManager(context) {
|
|
345
|
+
const read = readOptions(context);
|
|
346
|
+
if (!read.ok) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
const { remote, branch, tokenEnv, commitAuthor } = read.settings;
|
|
350
|
+
return {
|
|
351
|
+
remote,
|
|
352
|
+
branch,
|
|
353
|
+
...(remote.startsWith("https://") ? { credentialEnv: tokenEnv } : {}),
|
|
354
|
+
...(commitAuthor === undefined ? {} : { author: commitAuthor }),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The issue number encoded in `owner/name#42`. */
|
|
2
|
+
export declare function issueNumberFromExternalId(externalId: string): number | undefined;
|
|
3
|
+
/** The issue number a listing or webhook payload carries. */
|
|
4
|
+
export declare function issueNumberFromPayload(payload: Record<string, unknown>): number | undefined;
|
|
5
|
+
//# sourceMappingURL=issue-number.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-number.d.ts","sourceRoot":"","sources":["../src/issue-number.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMhF;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAS3F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** The issue number encoded in `owner/name#42`. */
|
|
2
|
+
export function issueNumberFromExternalId(externalId) {
|
|
3
|
+
const hash = externalId.lastIndexOf("#");
|
|
4
|
+
if (hash < 0) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
return parsePositiveInt(externalId.slice(hash + 1));
|
|
8
|
+
}
|
|
9
|
+
/** The issue number a listing or webhook payload carries. */
|
|
10
|
+
export function issueNumberFromPayload(payload) {
|
|
11
|
+
const nested = payload.issue;
|
|
12
|
+
if (nested !== null && typeof nested === "object" && !Array.isArray(nested)) {
|
|
13
|
+
const inner = issueNumberFromPayload(nested);
|
|
14
|
+
if (inner !== undefined) {
|
|
15
|
+
return inner;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return parsePositiveInt(payload.number);
|
|
19
|
+
}
|
|
20
|
+
function parsePositiveInt(value) {
|
|
21
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0) {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
if (typeof value === "string" && /^\d+$/.test(value.trim())) {
|
|
25
|
+
const parsed = Number(value.trim());
|
|
26
|
+
if (parsed > 0) {
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=issue-number.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-number.js","sourceRoot":"","sources":["../src/issue-number.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7B,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5E,MAAM,KAAK,GAAG,sBAAsB,CAAC,MAAiC,CAAC,CAAC;QACxE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/labels.d.ts
ADDED