@nonameolsson/nightjar 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +405 -2
- package/dist/account.d.ts +12 -0
- package/dist/account.js +57 -0
- package/dist/account.js.map +1 -0
- package/dist/adapter-module.d.ts +18 -0
- package/dist/adapter-module.js +83 -0
- package/dist/adapter-module.js.map +1 -0
- package/dist/adapters.d.ts +15 -0
- package/dist/adapters.js +160 -0
- package/dist/adapters.js.map +1 -0
- package/dist/args.d.ts +13 -0
- package/dist/args.js +84 -0
- package/dist/args.js.map +1 -0
- package/dist/ask.d.ts +6 -0
- package/dist/ask.js +27 -0
- package/dist/ask.js.map +1 -0
- package/dist/azure-devops/api.d.ts +34 -0
- package/dist/azure-devops/api.js +98 -0
- package/dist/azure-devops/api.js.map +1 -0
- package/dist/azure-devops/code-host.d.ts +36 -0
- package/dist/azure-devops/code-host.js +185 -0
- package/dist/azure-devops/code-host.js.map +1 -0
- package/dist/azure-devops/fake-azure-devops.d.ts +90 -0
- package/dist/azure-devops/fake-azure-devops.js +728 -0
- package/dist/azure-devops/fake-azure-devops.js.map +1 -0
- package/dist/azure-devops/index.d.ts +8 -0
- package/dist/azure-devops/index.js +11 -0
- package/dist/azure-devops/index.js.map +1 -0
- package/dist/azure-devops/sign-in.d.ts +11 -0
- package/dist/azure-devops/sign-in.js +68 -0
- package/dist/azure-devops/sign-in.js.map +1 -0
- package/dist/azure-devops/text.d.ts +1 -0
- package/dist/azure-devops/text.js +41 -0
- package/dist/azure-devops/text.js.map +1 -0
- package/dist/azure-devops/tracker.d.ts +44 -0
- package/dist/azure-devops/tracker.js +333 -0
- package/dist/azure-devops/tracker.js.map +1 -0
- package/dist/build.d.ts +75 -0
- package/dist/build.js +698 -0
- package/dist/build.js.map +1 -0
- package/dist/check.d.ts +8 -0
- package/dist/check.js +25 -0
- package/dist/check.js.map +1 -0
- package/dist/checks.d.ts +45 -0
- package/dist/checks.js +243 -0
- package/dist/checks.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -0
- package/dist/code-host.d.ts +19 -0
- package/dist/code-host.js +2 -0
- package/dist/code-host.js.map +1 -0
- package/dist/config.d.ts +86 -0
- package/dist/config.js +294 -0
- package/dist/config.js.map +1 -0
- package/dist/contract/case.d.ts +4 -0
- package/dist/contract/case.js +2 -0
- package/dist/contract/case.js.map +1 -0
- package/dist/contract/code-host.d.ts +24 -0
- package/dist/contract/code-host.js +108 -0
- package/dist/contract/code-host.js.map +1 -0
- package/dist/contract/command.d.ts +2 -0
- package/dist/contract/command.js +36 -0
- package/dist/contract/command.js.map +1 -0
- package/dist/contract/feature-writer.d.ts +3 -0
- package/dist/contract/feature-writer.js +101 -0
- package/dist/contract/feature-writer.js.map +1 -0
- package/dist/contract/run.d.ts +18 -0
- package/dist/contract/run.js +89 -0
- package/dist/contract/run.js.map +1 -0
- package/dist/contract/tracker.d.ts +30 -0
- package/dist/contract/tracker.js +250 -0
- package/dist/contract/tracker.js.map +1 -0
- package/dist/create.d.ts +9 -0
- package/dist/create.js +112 -0
- package/dist/create.js.map +1 -0
- package/dist/doctor.d.ts +4 -0
- package/dist/doctor.js +42 -0
- package/dist/doctor.js.map +1 -0
- package/dist/fakes/code-host.d.ts +21 -0
- package/dist/fakes/code-host.js +42 -0
- package/dist/fakes/code-host.js.map +1 -0
- package/dist/fakes/harness.d.ts +7 -0
- package/dist/fakes/harness.js +68 -0
- package/dist/fakes/harness.js.map +1 -0
- package/dist/fakes/machine.d.ts +11 -0
- package/dist/fakes/machine.js +101 -0
- package/dist/fakes/machine.js.map +1 -0
- package/dist/fakes/tracker.d.ts +40 -0
- package/dist/fakes/tracker.js +116 -0
- package/dist/fakes/tracker.js.map +1 -0
- package/dist/feature-file.d.ts +12 -0
- package/dist/feature-file.js +84 -0
- package/dist/feature-file.js.map +1 -0
- package/dist/git.d.ts +9 -0
- package/dist/git.js +12 -0
- package/dist/git.js.map +1 -0
- package/dist/github/api.d.ts +37 -0
- package/dist/github/api.js +66 -0
- package/dist/github/api.js.map +1 -0
- package/dist/github/code-host.d.ts +19 -0
- package/dist/github/code-host.js +105 -0
- package/dist/github/code-host.js.map +1 -0
- package/dist/github/fake-gh.d.ts +17 -0
- package/dist/github/fake-gh.js +51 -0
- package/dist/github/fake-gh.js.map +1 -0
- package/dist/github/fake-github.d.ts +58 -0
- package/dist/github/fake-github.js +285 -0
- package/dist/github/fake-github.js.map +1 -0
- package/dist/github/labels.d.ts +3 -0
- package/dist/github/labels.js +44 -0
- package/dist/github/labels.js.map +1 -0
- package/dist/github/tracker.d.ts +28 -0
- package/dist/github/tracker.js +208 -0
- package/dist/github/tracker.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +19 -0
- package/dist/init.js +225 -0
- package/dist/init.js.map +1 -0
- package/dist/ledger.d.ts +13 -0
- package/dist/ledger.js +49 -0
- package/dist/ledger.js.map +1 -0
- package/dist/main.d.ts +11 -0
- package/dist/main.js +215 -0
- package/dist/main.js.map +1 -0
- package/dist/person-config.d.ts +9 -0
- package/dist/person-config.js +46 -0
- package/dist/person-config.js.map +1 -0
- package/dist/plan.d.ts +9 -0
- package/dist/plan.js +27 -0
- package/dist/plan.js.map +1 -0
- package/dist/ports.d.ts +16 -0
- package/dist/ports.js +104 -0
- package/dist/ports.js.map +1 -0
- package/dist/prompt.d.ts +166 -0
- package/dist/prompt.js +217 -0
- package/dist/prompt.js.map +1 -0
- package/dist/queue.d.ts +20 -0
- package/dist/queue.js +94 -0
- package/dist/queue.js.map +1 -0
- package/dist/say.d.ts +2 -0
- package/dist/say.js +4 -0
- package/dist/say.js.map +1 -0
- package/dist/serve.d.ts +10 -0
- package/dist/serve.js +85 -0
- package/dist/serve.js.map +1 -0
- package/dist/session.d.ts +39 -0
- package/dist/session.js +144 -0
- package/dist/session.js.map +1 -0
- package/dist/settings.d.ts +10 -0
- package/dist/settings.js +92 -0
- package/dist/settings.js.map +1 -0
- package/dist/signals.d.ts +5 -0
- package/dist/signals.js +13 -0
- package/dist/signals.js.map +1 -0
- package/dist/skills.d.ts +4 -0
- package/dist/skills.js +51 -0
- package/dist/skills.js.map +1 -0
- package/dist/status-shape.d.ts +53 -0
- package/dist/status-shape.js +3 -0
- package/dist/status-shape.js.map +1 -0
- package/dist/status.d.ts +23 -0
- package/dist/status.js +56 -0
- package/dist/status.js.map +1 -0
- package/dist/tracker.d.ts +56 -0
- package/dist/tracker.js +12 -0
- package/dist/tracker.js.map +1 -0
- package/dist/workflow.d.ts +33 -0
- package/dist/workflow.js +53 -0
- package/dist/workflow.js.map +1 -0
- package/dist/worktree.d.ts +44 -0
- package/dist/worktree.js +193 -0
- package/dist/worktree.js.map +1 -0
- package/docs/ticket-contract.md +95 -0
- package/package.json +74 -5
- package/plugin/nightjar-status/.claude-plugin/plugin.json +5 -0
- package/plugin/nightjar-status/hooks/format.ts +48 -0
- package/plugin/nightjar-status/hooks/hooks.json +1 -0
- package/plugin/nightjar-status/hooks/register.ts +51 -0
- package/schema/factory.schema.json +437 -0
- package/skills/nightjar-feature/SKILL.md +73 -0
- package/src/status-shape.ts +44 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Calls through the person's own `gh api`, which holds the login, so no token passes through here.
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { firstLine, run } from '../git.js';
|
|
4
|
+
// A GitHub call Nightjar cannot do without; its message names the call and gh's reason.
|
|
5
|
+
export class GitHubFailure extends Error {
|
|
6
|
+
}
|
|
7
|
+
export const ghRunner = (cwd, env) => (args) => run('gh', args, cwd, env);
|
|
8
|
+
export const IssueSchema = z.looseObject({
|
|
9
|
+
// GitHub's own id, which the sub-issue and dependency calls take
|
|
10
|
+
id: z.int().optional(),
|
|
11
|
+
number: z.int(),
|
|
12
|
+
title: z.string(),
|
|
13
|
+
body: z.string().nullable(),
|
|
14
|
+
state: z.string(),
|
|
15
|
+
labels: z.array(z.looseObject({ name: z.string() })),
|
|
16
|
+
assignees: z
|
|
17
|
+
.array(z.looseObject({ login: z.string() }))
|
|
18
|
+
.nullable()
|
|
19
|
+
.optional(),
|
|
20
|
+
user: z.looseObject({ login: z.string() }).nullable(),
|
|
21
|
+
sub_issues_summary: z.looseObject({ total: z.int() }).optional(),
|
|
22
|
+
// the issues list also returns pull requests, which carry this
|
|
23
|
+
pull_request: z.unknown().optional()
|
|
24
|
+
});
|
|
25
|
+
// A Feature with more than 100 Tickets or comments is no Feature for one run.
|
|
26
|
+
export const PAGE = 'per_page=100';
|
|
27
|
+
export class GitHubApi {
|
|
28
|
+
repo;
|
|
29
|
+
gh;
|
|
30
|
+
constructor(repo, gh) {
|
|
31
|
+
this.repo = repo;
|
|
32
|
+
this.gh = gh;
|
|
33
|
+
}
|
|
34
|
+
// gh's own answer, for a caller that reads a refusal itself.
|
|
35
|
+
async raw(args) {
|
|
36
|
+
const got = await this.gh(['api', ...args]);
|
|
37
|
+
if (got.missing)
|
|
38
|
+
throw new GitHubFailure('gh is not on the PATH.');
|
|
39
|
+
return got;
|
|
40
|
+
}
|
|
41
|
+
async call(what, args) {
|
|
42
|
+
const got = await this.raw(args);
|
|
43
|
+
if (!got.ok)
|
|
44
|
+
throw new GitHubFailure(`gh could not ${what}: ${firstLine(got.err)}`);
|
|
45
|
+
if (got.out.trim() === '')
|
|
46
|
+
return null;
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(got.out);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new GitHubFailure(`gh printed no JSON when asked to ${what}.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async parse(what, args, schema) {
|
|
55
|
+
const parsed = schema.safeParse(await this.call(what, args));
|
|
56
|
+
if (!parsed.success)
|
|
57
|
+
throw new GitHubFailure(`GitHub answered ${what} in a shape not known.`);
|
|
58
|
+
return parsed.data;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// owner/name from an origin such as git@github.com:o/r.git or https://github.com/o/r
|
|
62
|
+
export function repoFromRemote(url) {
|
|
63
|
+
const match = /github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(url.trim());
|
|
64
|
+
return match ? `${match[1] ?? ''}/${match[2] ?? ''}` : null;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/github/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CodeHost, DraftRequest, Pull } from '../code-host.js';
|
|
2
|
+
import { type Run } from '../git.js';
|
|
3
|
+
import type { TicketReference } from '../tracker.js';
|
|
4
|
+
import { type GhRunner } from './api.js';
|
|
5
|
+
export type GitRunner = (args: readonly string[], cwd: string) => Promise<Run>;
|
|
6
|
+
export declare class GitHubCodeHost implements CodeHost {
|
|
7
|
+
readonly repo: string;
|
|
8
|
+
private readonly git;
|
|
9
|
+
private readonly api;
|
|
10
|
+
constructor(repo: string, gh: GhRunner, git: GitRunner);
|
|
11
|
+
push(folder: string, branch: string): Promise<void>;
|
|
12
|
+
openPull(branch: string): Promise<Pull | null>;
|
|
13
|
+
createDraft(request: DraftRequest): Promise<Pull>;
|
|
14
|
+
private body;
|
|
15
|
+
private setBody;
|
|
16
|
+
editBody(pull: Pull, body: string): Promise<void>;
|
|
17
|
+
placeReferences(pull: Pull, references: readonly TicketReference[]): Promise<void>;
|
|
18
|
+
comment(pull: Pull, body: string): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// GitHub as a Code host: the branch goes to origin and each Ticket reference into the draft pull request.
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { firstLine } from '../git.js';
|
|
4
|
+
import { GitHubApi, GitHubFailure } from './api.js';
|
|
5
|
+
const PullSchema = z.looseObject({
|
|
6
|
+
number: z.int(),
|
|
7
|
+
html_url: z.string(),
|
|
8
|
+
body: z.string().nullable().optional()
|
|
9
|
+
});
|
|
10
|
+
// Everything after it in a body is the references Nightjar placed.
|
|
11
|
+
const REFERENCES_MARK = '<!-- nightjar:references -->';
|
|
12
|
+
// A GitHub issue, #N, gets `Closes` so GitHub closes it on merge; any other Tracker's reference, such as AB#N, stays as written.
|
|
13
|
+
const placed = (r) => (/^#\d+$/.test(r.text) ? `Closes ${r.text}` : r.text);
|
|
14
|
+
const toPull = (raw) => ({ id: raw.number, url: raw.html_url });
|
|
15
|
+
function split(body) {
|
|
16
|
+
const at = body.indexOf(REFERENCES_MARK);
|
|
17
|
+
if (at < 0)
|
|
18
|
+
return { text: body.trimEnd(), lines: [] };
|
|
19
|
+
const lines = body
|
|
20
|
+
.slice(at + REFERENCES_MARK.length)
|
|
21
|
+
.split('\n')
|
|
22
|
+
.map((l) => l.trim())
|
|
23
|
+
.filter((l) => l !== '');
|
|
24
|
+
return { text: body.slice(0, at).trimEnd(), lines };
|
|
25
|
+
}
|
|
26
|
+
const join = (text, lines) => lines.length === 0 ? text : `${text}\n\n${REFERENCES_MARK}\n${lines.join('\n')}`;
|
|
27
|
+
export class GitHubCodeHost {
|
|
28
|
+
repo;
|
|
29
|
+
git;
|
|
30
|
+
api;
|
|
31
|
+
constructor(repo, gh, git) {
|
|
32
|
+
this.repo = repo;
|
|
33
|
+
this.git = git;
|
|
34
|
+
this.api = new GitHubApi(repo, gh);
|
|
35
|
+
}
|
|
36
|
+
async push(folder, branch) {
|
|
37
|
+
const got = await this.git(['push', '-q', '-u', 'origin', `HEAD:refs/heads/${branch}`], folder);
|
|
38
|
+
if (got.missing)
|
|
39
|
+
throw new GitHubFailure('git is not on the PATH.');
|
|
40
|
+
if (!got.ok)
|
|
41
|
+
throw new GitHubFailure(`git could not push ${branch}: ${firstLine(got.err)}`);
|
|
42
|
+
}
|
|
43
|
+
async openPull(branch) {
|
|
44
|
+
const owner = this.repo.split('/')[0] ?? '';
|
|
45
|
+
const query = new URLSearchParams({ head: `${owner}:${branch}`, state: 'open' });
|
|
46
|
+
const raw = await this.api.parse(`find the pull request of ${branch}`, [`repos/${this.repo}/pulls?${query.toString()}`], z.array(PullSchema));
|
|
47
|
+
const first = raw[0];
|
|
48
|
+
return first ? toPull(first) : null;
|
|
49
|
+
}
|
|
50
|
+
async createDraft(request) {
|
|
51
|
+
const made = await this.api.parse(`open a pull request for ${request.head}`, [
|
|
52
|
+
'-X',
|
|
53
|
+
'POST',
|
|
54
|
+
`repos/${this.repo}/pulls`,
|
|
55
|
+
'-f',
|
|
56
|
+
`title=${request.title}`,
|
|
57
|
+
'-f',
|
|
58
|
+
`head=${request.head}`,
|
|
59
|
+
'-f',
|
|
60
|
+
`base=${request.base}`,
|
|
61
|
+
'-f',
|
|
62
|
+
`body=${request.body}`,
|
|
63
|
+
'-F',
|
|
64
|
+
'draft=true'
|
|
65
|
+
], PullSchema);
|
|
66
|
+
return toPull(made);
|
|
67
|
+
}
|
|
68
|
+
async body(pull) {
|
|
69
|
+
const n = String(pull.id);
|
|
70
|
+
const raw = await this.api.parse(`read pull request #${n}`, [`repos/${this.repo}/pulls/${n}`], PullSchema);
|
|
71
|
+
return raw.body ?? '';
|
|
72
|
+
}
|
|
73
|
+
async setBody(pull, body) {
|
|
74
|
+
const n = String(pull.id);
|
|
75
|
+
await this.api.call(`update pull request #${n}`, [
|
|
76
|
+
'-X',
|
|
77
|
+
'PATCH',
|
|
78
|
+
`repos/${this.repo}/pulls/${n}`,
|
|
79
|
+
'-f',
|
|
80
|
+
`body=${body}`
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
async editBody(pull, body) {
|
|
84
|
+
const { lines } = split(await this.body(pull));
|
|
85
|
+
await this.setBody(pull, join(body.trimEnd(), lines));
|
|
86
|
+
}
|
|
87
|
+
async placeReferences(pull, references) {
|
|
88
|
+
const { text, lines } = split(await this.body(pull));
|
|
89
|
+
const added = references.map(placed).filter((l) => !lines.includes(l));
|
|
90
|
+
if (added.length === 0)
|
|
91
|
+
return;
|
|
92
|
+
await this.setBody(pull, join(text, [...lines, ...added]));
|
|
93
|
+
}
|
|
94
|
+
async comment(pull, body) {
|
|
95
|
+
const n = String(pull.id);
|
|
96
|
+
await this.api.call(`comment on pull request #${n}`, [
|
|
97
|
+
'-X',
|
|
98
|
+
'POST',
|
|
99
|
+
`repos/${this.repo}/issues/${n}/comments`,
|
|
100
|
+
'-f',
|
|
101
|
+
`body=${body}`
|
|
102
|
+
]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=code-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-host.js","sourceRoot":"","sources":["../../src/github/code-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Run } from '../git.js';
|
|
2
|
+
export interface GhCall {
|
|
3
|
+
readonly method: string;
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly query: URLSearchParams;
|
|
6
|
+
readonly fields: Readonly<Record<string, string | string[]>>;
|
|
7
|
+
readonly args: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
export type Route = (call: GhCall) => Run | undefined;
|
|
10
|
+
export declare const ok: (value: unknown) => Run;
|
|
11
|
+
export declare const failed: (err: string) => Run;
|
|
12
|
+
export declare function readCall(args: readonly string[]): GhCall;
|
|
13
|
+
export declare function fakeGh(...routes: Route[]): {
|
|
14
|
+
gh: (args: readonly string[]) => Promise<Run>;
|
|
15
|
+
calls: GhCall[];
|
|
16
|
+
};
|
|
17
|
+
export declare const on: (method: string, path: string, answer: Run | ((call: GhCall) => Run)) => Route;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const ok = (value) => ({
|
|
2
|
+
ok: true,
|
|
3
|
+
out: JSON.stringify(value),
|
|
4
|
+
err: '',
|
|
5
|
+
missing: false
|
|
6
|
+
});
|
|
7
|
+
export const failed = (err) => ({ ok: false, out: '', err, missing: false });
|
|
8
|
+
export function readCall(args) {
|
|
9
|
+
let method = 'GET';
|
|
10
|
+
let target = '';
|
|
11
|
+
const fields = {};
|
|
12
|
+
for (let i = 1; i < args.length; i += 1) {
|
|
13
|
+
const a = args[i] ?? '';
|
|
14
|
+
if (a === '-X')
|
|
15
|
+
method = args[(i += 1)] ?? '';
|
|
16
|
+
else if (a === '-f' || a === '-F') {
|
|
17
|
+
const field = args[(i += 1)] ?? '';
|
|
18
|
+
const at = field.indexOf('=');
|
|
19
|
+
const name = field.slice(0, at);
|
|
20
|
+
const value = field.slice(at + 1);
|
|
21
|
+
const had = fields[name];
|
|
22
|
+
fields[name] = name.endsWith('[]') ? [...(Array.isArray(had) ? had : []), value] : value;
|
|
23
|
+
}
|
|
24
|
+
else if (!a.startsWith('-'))
|
|
25
|
+
target = a;
|
|
26
|
+
}
|
|
27
|
+
const [path = '', query = ''] = target.split('?');
|
|
28
|
+
return { method, path, query: new URLSearchParams(query), fields, args };
|
|
29
|
+
}
|
|
30
|
+
// Each call goes to the first route that answers it; a call no route answers is a 404.
|
|
31
|
+
export function fakeGh(...routes) {
|
|
32
|
+
const calls = [];
|
|
33
|
+
const gh = (args) => {
|
|
34
|
+
const call = readCall(args);
|
|
35
|
+
calls.push(call);
|
|
36
|
+
for (const route of routes) {
|
|
37
|
+
const answer = route(call);
|
|
38
|
+
if (answer !== undefined)
|
|
39
|
+
return Promise.resolve(answer);
|
|
40
|
+
}
|
|
41
|
+
return Promise.resolve(failed('gh: Not Found (HTTP 404)'));
|
|
42
|
+
};
|
|
43
|
+
return { gh, calls };
|
|
44
|
+
}
|
|
45
|
+
// A route answering one method and path.
|
|
46
|
+
export const on = (method, path, answer) => (call) => call.method === method && call.path === path
|
|
47
|
+
? typeof answer === 'function'
|
|
48
|
+
? answer(call)
|
|
49
|
+
: answer
|
|
50
|
+
: undefined;
|
|
51
|
+
//# sourceMappingURL=fake-gh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-gh.js","sourceRoot":"","sources":["../../src/github/fake-gh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { GhRunner } from './api.js';
|
|
2
|
+
export interface NewIssue {
|
|
3
|
+
readonly title: string;
|
|
4
|
+
readonly body: string | null;
|
|
5
|
+
readonly state: 'open' | 'closed';
|
|
6
|
+
readonly labels: readonly string[];
|
|
7
|
+
readonly assignees: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
interface PullHead {
|
|
10
|
+
readonly head: string;
|
|
11
|
+
readonly base: string;
|
|
12
|
+
readonly draft: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ShownPull extends PullHead {
|
|
15
|
+
readonly title: string;
|
|
16
|
+
readonly body: string;
|
|
17
|
+
}
|
|
18
|
+
interface IssueComment {
|
|
19
|
+
readonly login: string;
|
|
20
|
+
readonly body: string;
|
|
21
|
+
readonly createdAt: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class FakeGitHub {
|
|
24
|
+
readonly repo: string;
|
|
25
|
+
readonly person: string;
|
|
26
|
+
private readonly issues;
|
|
27
|
+
private readonly comments;
|
|
28
|
+
private readonly permissions;
|
|
29
|
+
constructor(repo: string, person: string);
|
|
30
|
+
issue(issue: NewIssue): number;
|
|
31
|
+
addSubIssue(parent: number, child: number): void;
|
|
32
|
+
block(blocked: number, by: number): void;
|
|
33
|
+
say(number: number, login: string, body: string): IssueComment;
|
|
34
|
+
grant(login: string, permission: string): void;
|
|
35
|
+
pullAt(number: number): ShownPull;
|
|
36
|
+
said(number: number): string[];
|
|
37
|
+
readonly gh: GhRunner;
|
|
38
|
+
private answer;
|
|
39
|
+
private openIssue;
|
|
40
|
+
private byId;
|
|
41
|
+
private adopt;
|
|
42
|
+
private blockBy;
|
|
43
|
+
private openPull;
|
|
44
|
+
private pulls;
|
|
45
|
+
private renderPull;
|
|
46
|
+
private url;
|
|
47
|
+
private label;
|
|
48
|
+
private unlabel;
|
|
49
|
+
private issueAt;
|
|
50
|
+
private list;
|
|
51
|
+
private renderComment;
|
|
52
|
+
private renderAll;
|
|
53
|
+
private render;
|
|
54
|
+
private commentCount;
|
|
55
|
+
private get;
|
|
56
|
+
private change;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { failed, ok, readCall } from './fake-gh.js';
|
|
2
|
+
const NOT_FOUND = failed('gh: Not Found (HTTP 404)');
|
|
3
|
+
const INVALID = (why) => failed(`gh: Validation Failed: ${why} (HTTP 422)`);
|
|
4
|
+
// GitHub's own id of an issue, which its sub-issue and dependency calls take, apart from its number.
|
|
5
|
+
const databaseId = (number) => 4_000_000 + number * 7;
|
|
6
|
+
// An integer field, as `gh api -F` sends one; `-f` would send it as a string, which GitHub refuses.
|
|
7
|
+
function integerField(call, name) {
|
|
8
|
+
for (let i = 0; i < call.args.length - 1; i += 1) {
|
|
9
|
+
const field = call.args[i + 1] ?? '';
|
|
10
|
+
if (call.args[i] === '-F' && field.startsWith(`${name}=`)) {
|
|
11
|
+
const value = field.slice(name.length + 1);
|
|
12
|
+
return /^\d+$/.test(value) ? Number(value) : null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
export class FakeGitHub {
|
|
18
|
+
repo;
|
|
19
|
+
person;
|
|
20
|
+
issues = new Map();
|
|
21
|
+
comments = new Map();
|
|
22
|
+
permissions = new Map();
|
|
23
|
+
constructor(repo,
|
|
24
|
+
// the login gh is signed in as
|
|
25
|
+
person) {
|
|
26
|
+
this.repo = repo;
|
|
27
|
+
this.person = person;
|
|
28
|
+
}
|
|
29
|
+
// Opens an issue and gives back its number.
|
|
30
|
+
issue(issue) {
|
|
31
|
+
const number = this.issues.size + 1;
|
|
32
|
+
this.issues.set(number, { ...issue, number, subIssues: [], blockedBy: [] });
|
|
33
|
+
return number;
|
|
34
|
+
}
|
|
35
|
+
addSubIssue(parent, child) {
|
|
36
|
+
this.change(parent, (i) => ({ subIssues: [...i.subIssues, child] }));
|
|
37
|
+
}
|
|
38
|
+
block(blocked, by) {
|
|
39
|
+
this.change(blocked, (i) => ({ blockedBy: [...i.blockedBy, by] }));
|
|
40
|
+
}
|
|
41
|
+
say(number, login, body) {
|
|
42
|
+
const at = new Date(Date.UTC(2026, 9, 30, 9, this.commentCount())).toISOString();
|
|
43
|
+
const comment = { login, body, createdAt: at };
|
|
44
|
+
this.comments.set(number, [...(this.comments.get(number) ?? []), comment]);
|
|
45
|
+
return comment;
|
|
46
|
+
}
|
|
47
|
+
// Makes `login` a collaborator with `permission` (read, write, maintain, admin).
|
|
48
|
+
grant(login, permission) {
|
|
49
|
+
this.permissions.set(login, permission);
|
|
50
|
+
}
|
|
51
|
+
// Pull request `number` as GitHub shows it.
|
|
52
|
+
pullAt(number) {
|
|
53
|
+
const issue = this.issues.get(number);
|
|
54
|
+
if (issue?.pull === undefined) {
|
|
55
|
+
throw new Error(`the fake GitHub has no pull request #${String(number)}`);
|
|
56
|
+
}
|
|
57
|
+
return { ...issue.pull, title: issue.title, body: issue.body ?? '' };
|
|
58
|
+
}
|
|
59
|
+
// The bodies of the comments on issue or pull request `number`, oldest first.
|
|
60
|
+
said(number) {
|
|
61
|
+
return (this.comments.get(number) ?? []).map((c) => c.body);
|
|
62
|
+
}
|
|
63
|
+
gh = (args) => Promise.resolve(this.answer(readCall(args)));
|
|
64
|
+
answer(call) {
|
|
65
|
+
const { method, path } = call;
|
|
66
|
+
const repo = `repos/${this.repo}`;
|
|
67
|
+
if (method === 'GET' && path === 'user')
|
|
68
|
+
return ok({ login: this.person });
|
|
69
|
+
if (method === 'GET' && path === `${repo}/issues`)
|
|
70
|
+
return ok(this.list(call.query));
|
|
71
|
+
if (method === 'POST' && path === `${repo}/issues`)
|
|
72
|
+
return this.openIssue(call);
|
|
73
|
+
if (method === 'GET' && path === `${repo}/pulls`)
|
|
74
|
+
return ok(this.pulls(call.query));
|
|
75
|
+
if (method === 'POST' && path === `${repo}/pulls`)
|
|
76
|
+
return this.openPull(call);
|
|
77
|
+
const pullNumber = new RegExp(`^${repo}/pulls/(\\d+)$`).exec(path);
|
|
78
|
+
const pull = pullNumber ? this.issues.get(Number(pullNumber[1])) : undefined;
|
|
79
|
+
if (pull?.pull !== undefined && method === 'GET')
|
|
80
|
+
return ok(this.renderPull(pull));
|
|
81
|
+
if (pull?.pull !== undefined && method === 'PATCH') {
|
|
82
|
+
const body = call.fields.body;
|
|
83
|
+
if (typeof body === 'string')
|
|
84
|
+
this.change(pull.number, () => ({ body }));
|
|
85
|
+
return ok(this.renderPull(this.get(pull.number)));
|
|
86
|
+
}
|
|
87
|
+
const asked = new RegExp(`^${repo}/collaborators/([^/]+)/permission$`).exec(path);
|
|
88
|
+
if (method === 'GET' && asked) {
|
|
89
|
+
return ok({ permission: this.permissions.get(decodeURIComponent(asked[1] ?? '')) ?? 'none' });
|
|
90
|
+
}
|
|
91
|
+
const issue = this.issueAt(path, repo);
|
|
92
|
+
if (issue === undefined)
|
|
93
|
+
return NOT_FOUND;
|
|
94
|
+
const rest = path.slice(`${repo}/issues/${String(issue.number)}`.length);
|
|
95
|
+
if (method === 'GET' && rest === '')
|
|
96
|
+
return ok(this.render(issue));
|
|
97
|
+
if (method === 'GET' && rest === '/sub_issues')
|
|
98
|
+
return ok(this.renderAll(issue.subIssues));
|
|
99
|
+
if (method === 'GET' && rest === '/dependencies/blocked_by') {
|
|
100
|
+
return ok(this.renderAll(issue.blockedBy));
|
|
101
|
+
}
|
|
102
|
+
if (method === 'POST' && rest === '/sub_issues')
|
|
103
|
+
return this.adopt(issue, call);
|
|
104
|
+
if (method === 'POST' && rest === '/dependencies/blocked_by')
|
|
105
|
+
return this.blockBy(issue, call);
|
|
106
|
+
if (method === 'GET' && rest === '/comments') {
|
|
107
|
+
return ok((this.comments.get(issue.number) ?? []).map((c) => this.renderComment(c)));
|
|
108
|
+
}
|
|
109
|
+
if (method === 'POST' && rest === '/comments') {
|
|
110
|
+
return ok(this.renderComment(this.say(issue.number, this.person, String(call.fields.body))));
|
|
111
|
+
}
|
|
112
|
+
if (method === 'POST' && rest === '/labels')
|
|
113
|
+
return this.label(issue, call);
|
|
114
|
+
const label = /^\/labels\/([^/]+)$/.exec(rest);
|
|
115
|
+
if (method === 'DELETE' && label)
|
|
116
|
+
return this.unlabel(issue, decodeURIComponent(label[1] ?? ''));
|
|
117
|
+
return NOT_FOUND;
|
|
118
|
+
}
|
|
119
|
+
openIssue(call) {
|
|
120
|
+
const title = call.fields.title;
|
|
121
|
+
const body = call.fields.body;
|
|
122
|
+
if (typeof title !== 'string' || title.trim() === '')
|
|
123
|
+
return INVALID('title is missing');
|
|
124
|
+
const number = this.issue({
|
|
125
|
+
title,
|
|
126
|
+
body: typeof body === 'string' ? body : null,
|
|
127
|
+
state: 'open',
|
|
128
|
+
labels: [],
|
|
129
|
+
assignees: []
|
|
130
|
+
});
|
|
131
|
+
return ok(this.render(this.get(number)));
|
|
132
|
+
}
|
|
133
|
+
// The issue whose id `field` names, as GitHub takes it.
|
|
134
|
+
byId(call, field) {
|
|
135
|
+
const id = integerField(call, field);
|
|
136
|
+
return [...this.issues.values()].find((i) => databaseId(i.number) === id);
|
|
137
|
+
}
|
|
138
|
+
// GitHub gives a sub-issue one parent and puts it last among the parent's.
|
|
139
|
+
adopt(parent, call) {
|
|
140
|
+
const child = this.byId(call, 'sub_issue_id');
|
|
141
|
+
if (child === undefined)
|
|
142
|
+
return INVALID('sub_issue_id is not the id of an issue');
|
|
143
|
+
const taken = [...this.issues.values()].some((i) => i.subIssues.includes(child.number));
|
|
144
|
+
if (taken)
|
|
145
|
+
return INVALID('the issue already has a parent');
|
|
146
|
+
this.addSubIssue(parent.number, child.number);
|
|
147
|
+
return ok(this.render(this.get(parent.number)));
|
|
148
|
+
}
|
|
149
|
+
blockBy(blocked, call) {
|
|
150
|
+
const blocker = this.byId(call, 'issue_id');
|
|
151
|
+
if (blocker === undefined)
|
|
152
|
+
return INVALID('issue_id is not the id of an issue');
|
|
153
|
+
if (!blocked.blockedBy.includes(blocker.number))
|
|
154
|
+
this.block(blocked.number, blocker.number);
|
|
155
|
+
return ok(this.render(blocker));
|
|
156
|
+
}
|
|
157
|
+
// GitHub refuses a second open pull request for one head branch.
|
|
158
|
+
openPull(call) {
|
|
159
|
+
const field = (name) => {
|
|
160
|
+
const value = call.fields[name];
|
|
161
|
+
return typeof value === 'string' ? value : '';
|
|
162
|
+
};
|
|
163
|
+
const head = field('head');
|
|
164
|
+
const taken = [...this.issues.values()].some((i) => i.state === 'open' && i.pull?.head === head);
|
|
165
|
+
if (taken)
|
|
166
|
+
return failed(`gh: A pull request already exists for ${head}. (HTTP 422)`);
|
|
167
|
+
const number = this.issue({
|
|
168
|
+
title: field('title'),
|
|
169
|
+
body: field('body'),
|
|
170
|
+
state: 'open',
|
|
171
|
+
labels: [],
|
|
172
|
+
assignees: []
|
|
173
|
+
});
|
|
174
|
+
const pull = { head, base: field('base'), draft: field('draft') === 'true' };
|
|
175
|
+
this.change(number, () => ({ pull }));
|
|
176
|
+
return ok(this.renderPull(this.get(number)));
|
|
177
|
+
}
|
|
178
|
+
// GitHub's filters: state open by default, and head as owner:branch.
|
|
179
|
+
pulls(query) {
|
|
180
|
+
const state = query.get('state') ?? 'open';
|
|
181
|
+
const head = query.get('head');
|
|
182
|
+
const owner = this.repo.split('/')[0] ?? '';
|
|
183
|
+
return [...this.issues.values()]
|
|
184
|
+
.filter((i) => i.pull !== undefined &&
|
|
185
|
+
(state === 'all' || i.state === state) &&
|
|
186
|
+
(head === null || head === `${owner}:${i.pull.head}`))
|
|
187
|
+
.map((i) => this.renderPull(i));
|
|
188
|
+
}
|
|
189
|
+
renderPull(issue) {
|
|
190
|
+
return {
|
|
191
|
+
number: issue.number,
|
|
192
|
+
html_url: this.url(issue.number),
|
|
193
|
+
title: issue.title,
|
|
194
|
+
body: issue.body,
|
|
195
|
+
state: issue.state,
|
|
196
|
+
draft: issue.pull?.draft ?? false,
|
|
197
|
+
head: { ref: issue.pull?.head ?? '' },
|
|
198
|
+
base: { ref: issue.pull?.base ?? '' }
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
url(number) {
|
|
202
|
+
return `https://github.com/${this.repo}/pull/${String(number)}`;
|
|
203
|
+
}
|
|
204
|
+
label(issue, call) {
|
|
205
|
+
const asked = call.fields['labels[]'];
|
|
206
|
+
const added = (Array.isArray(asked) ? asked : []).filter((l) => !issue.labels.includes(l));
|
|
207
|
+
const labels = [...issue.labels, ...added];
|
|
208
|
+
this.change(issue.number, () => ({ labels }));
|
|
209
|
+
return ok(labels.map((name) => ({ name })));
|
|
210
|
+
}
|
|
211
|
+
// GitHub answers 404 for a label the issue lacks.
|
|
212
|
+
unlabel(issue, name) {
|
|
213
|
+
if (!issue.labels.includes(name)) {
|
|
214
|
+
return {
|
|
215
|
+
...failed('gh: Label does not exist (HTTP 404)'),
|
|
216
|
+
out: '{"message":"Label does not exist"}'
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const labels = issue.labels.filter((l) => l !== name);
|
|
220
|
+
this.change(issue.number, () => ({ labels }));
|
|
221
|
+
return ok(labels.map((l) => ({ name: l })));
|
|
222
|
+
}
|
|
223
|
+
// The issue a path such as repos/o/r/issues/7/comments names.
|
|
224
|
+
issueAt(path, repo) {
|
|
225
|
+
if (!path.startsWith(`${repo}/`))
|
|
226
|
+
return undefined;
|
|
227
|
+
const match = /^\/issues\/(\d+)(?:\/|$)/.exec(path.slice(repo.length));
|
|
228
|
+
return match ? this.issues.get(Number(match[1])) : undefined;
|
|
229
|
+
}
|
|
230
|
+
// GitHub's filters: state open by default, every label named, the assignee, newest first by default.
|
|
231
|
+
list(query) {
|
|
232
|
+
const state = query.get('state') ?? 'open';
|
|
233
|
+
const labels = (query.get('labels') ?? '').split(',').filter((l) => l !== '');
|
|
234
|
+
const assignee = query.get('assignee');
|
|
235
|
+
const found = [...this.issues.values()].filter((i) => (state === 'all' || i.state === state) &&
|
|
236
|
+
labels.every((l) => i.labels.includes(l)) &&
|
|
237
|
+
(assignee === null || i.assignees.includes(assignee)));
|
|
238
|
+
if (query.get('direction') !== 'asc')
|
|
239
|
+
found.reverse();
|
|
240
|
+
return found.map((i) => this.render(i));
|
|
241
|
+
}
|
|
242
|
+
renderComment(comment) {
|
|
243
|
+
const permission = this.permissions.get(comment.login) ?? 'none';
|
|
244
|
+
return {
|
|
245
|
+
body: comment.body,
|
|
246
|
+
user: { login: comment.login },
|
|
247
|
+
created_at: comment.createdAt,
|
|
248
|
+
author_association: permission === 'none' ? 'NONE' : 'COLLABORATOR'
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
renderAll(numbers) {
|
|
252
|
+
return numbers.flatMap((n) => {
|
|
253
|
+
const issue = this.issues.get(n);
|
|
254
|
+
return issue ? [this.render(issue)] : [];
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
render(issue) {
|
|
258
|
+
return {
|
|
259
|
+
id: databaseId(issue.number),
|
|
260
|
+
number: issue.number,
|
|
261
|
+
title: issue.title,
|
|
262
|
+
body: issue.body,
|
|
263
|
+
state: issue.state,
|
|
264
|
+
labels: issue.labels.map((name) => ({ name })),
|
|
265
|
+
assignees: issue.assignees.map((login) => ({ login })),
|
|
266
|
+
user: { login: this.person },
|
|
267
|
+
sub_issues_summary: { total: issue.subIssues.length },
|
|
268
|
+
...(issue.pull ? { pull_request: { html_url: this.url(issue.number) } } : {})
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
commentCount() {
|
|
272
|
+
return [...this.comments.values()].reduce((n, list) => n + list.length, 0);
|
|
273
|
+
}
|
|
274
|
+
get(number) {
|
|
275
|
+
const issue = this.issues.get(number);
|
|
276
|
+
if (issue === undefined)
|
|
277
|
+
throw new Error(`the fake GitHub has no issue #${String(number)}`);
|
|
278
|
+
return issue;
|
|
279
|
+
}
|
|
280
|
+
change(number, over) {
|
|
281
|
+
const issue = this.get(number);
|
|
282
|
+
this.issues.set(number, { ...issue, ...over(issue) });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=fake-github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-github.js","sourceRoot":"","sources":["../../src/github/fake-github.ts"],"names":[],"mappings":"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"}
|