pm-github 2026.10.19 → 2026.10.24
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/CHANGELOG.md +42 -5
- package/README.md +203 -7
- package/dist/closeout.d.ts +5 -3
- package/dist/closeout.d.ts.map +1 -1
- package/dist/closeout.js +27 -28
- package/dist/closeout.js.map +1 -1
- package/dist/gate.d.ts +10 -5
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +151 -14
- package/dist/gate.js.map +1 -1
- package/dist/identity.d.ts +62 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +178 -0
- package/dist/identity.js.map +1 -0
- package/dist/import-fidelity.d.ts +28 -2
- package/dist/import-fidelity.d.ts.map +1 -1
- package/dist/import-fidelity.js +260 -28
- package/dist/import-fidelity.js.map +1 -1
- package/dist/index.d.ts +169 -76
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +389 -71
- package/dist/index.js.map +1 -1
- package/dist/refresh.d.ts +41 -0
- package/dist/refresh.d.ts.map +1 -0
- package/dist/refresh.js +223 -0
- package/dist/refresh.js.map +1 -0
- package/dist/webhooks.d.ts +55 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +188 -0
- package/dist/webhooks.js.map +1 -0
- package/manifest.json +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type PmItem, type PreparedGithubImport } from "./index.ts";
|
|
2
|
+
/** An existing item and its unique linked issue number. */
|
|
3
|
+
export interface RefreshTarget {
|
|
4
|
+
id: string;
|
|
5
|
+
number: number;
|
|
6
|
+
item: PmItem;
|
|
7
|
+
}
|
|
8
|
+
/** A machine-readable field delta; null means absent. */
|
|
9
|
+
export interface RefreshChange {
|
|
10
|
+
field: string;
|
|
11
|
+
old: unknown;
|
|
12
|
+
new: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** Per-item result, including non-destructive failures. */
|
|
15
|
+
export interface RefreshEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
number: number;
|
|
18
|
+
changes: RefreshChange[];
|
|
19
|
+
reason?: "not_found_or_inaccessible" | "inaccessible" | "transferred" | "api_error" | "incomplete_response" | "invalid_issue";
|
|
20
|
+
}
|
|
21
|
+
/** Select only explicit provenance, refusing conflicting links and duplicate local owners. */
|
|
22
|
+
export declare function selectRefreshTargets(items: readonly PmItem[], repo: string): RefreshTarget[];
|
|
23
|
+
/** Compare only refresh-owned fields; use the same source lifecycle projection as import finalization. */
|
|
24
|
+
export declare function refreshChanges(entry: PreparedGithubImport): RefreshChange[];
|
|
25
|
+
/** Build a zero-create refresh plan, then commit changed existing targets with import transactions. */
|
|
26
|
+
export declare function runRefresh(repoArg: string | undefined, pmRoot: string, options: Record<string, unknown>, scope?: {
|
|
27
|
+
numbers: readonly number[];
|
|
28
|
+
}): Promise<{
|
|
29
|
+
repo: string;
|
|
30
|
+
dryRun: boolean;
|
|
31
|
+
atomic: boolean;
|
|
32
|
+
selected: number;
|
|
33
|
+
filtered: number;
|
|
34
|
+
unchanged: number;
|
|
35
|
+
updated: number;
|
|
36
|
+
missing: number;
|
|
37
|
+
created: number;
|
|
38
|
+
resumed: number;
|
|
39
|
+
plan: RefreshEntry[];
|
|
40
|
+
}>;
|
|
41
|
+
//# sourceMappingURL=refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../refresh.ts"],"names":[],"mappings":"AAKA,OAAO,EAIS,KAAK,MAAM,EAAE,KAAK,oBAAoB,EACrD,MAAM,YAAY,CAAC;AAGpB,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC3E,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE;AAC5E,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,2BAA2B,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,qBAAqB,GAAG,eAAe,CAAC;CAC/H;AAED,8FAA8F;AAC9F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAyB5F;AA2DD,0GAA0G;AAC1G,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,aAAa,EAAE,CAS3E;AAqBD,uGAAuG;AACvG,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE;IAAE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;;;;;;;;;;;;GAmFrJ"}
|
package/dist/refresh.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/** Refresh an explicit local GitHub mirror through the importer's existing mapping and transaction. */
|
|
2
|
+
import { mkdtemp, cp, rm, chmod, readdir, lstat } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, basename } from "node:path";
|
|
5
|
+
import { listAllComplete, certifyCompleteListResult, previewItemMutations } from "@unbrained/pm-cli/sdk";
|
|
6
|
+
import { CommandError, EXIT_CODE, decodeCompletePmItems, githubGraphQLResponse, importGithubAtomic, listUnfinishedGithubImports, parseImportOptions, parseProvenanceTag, prepareGithubImport, readGithubImportPlan, resolveGitHubToken, resumeGithubImport, validateGithubImportFidelity, validateGithubImportPlan, } from "./index.js";
|
|
7
|
+
import { fetchImportTimeline, importFidelityFields, normalizeImportValue, readImportReleases } from "./import-fidelity.js";
|
|
8
|
+
/** Select only explicit provenance, refusing conflicting links and duplicate local owners. */
|
|
9
|
+
export function selectRefreshTargets(items, repo) {
|
|
10
|
+
const targets = new Map();
|
|
11
|
+
for (const item of items) {
|
|
12
|
+
if (!item.id)
|
|
13
|
+
continue;
|
|
14
|
+
const numbers = new Set();
|
|
15
|
+
for (const tag of item.tags ?? []) {
|
|
16
|
+
const parsed = parseProvenanceTag(tag);
|
|
17
|
+
if (parsed?.repo === repo)
|
|
18
|
+
numbers.add(parsed.number);
|
|
19
|
+
}
|
|
20
|
+
if (typeof item.github_url === "string") {
|
|
21
|
+
// Only /issues/ locators are refreshable: the batch query reads issue(...)
|
|
22
|
+
// nodes, so accepting /pull/ links would report every PR-linked item as
|
|
23
|
+
// missing on each run.
|
|
24
|
+
const url = /^https:\/\/github\.com\/([^/]+\/[^/]+)\/issues\/(\d+)\/?$/i.exec(item.github_url);
|
|
25
|
+
if (url?.[1].toLowerCase() === repo)
|
|
26
|
+
numbers.add(Number(url[2]));
|
|
27
|
+
}
|
|
28
|
+
if (typeof item.github_repo === "string" && item.github_repo.toLowerCase() === repo && typeof item.github_number === "number")
|
|
29
|
+
numbers.add(item.github_number);
|
|
30
|
+
if (numbers.size > 1)
|
|
31
|
+
throw new CommandError(`Refresh found conflicting GitHub identities for ${item.id}.`);
|
|
32
|
+
for (const number of numbers) {
|
|
33
|
+
if (!Number.isSafeInteger(number) || number < 1)
|
|
34
|
+
throw new CommandError(`Refresh found an invalid issue number for ${item.id}.`);
|
|
35
|
+
if (targets.has(number))
|
|
36
|
+
throw new CommandError(`Refresh found multiple existing owners for issue #${number}.`);
|
|
37
|
+
targets.set(number, { id: item.id, number, item });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return [...targets.values()].sort((a, b) => a.number - b.number);
|
|
41
|
+
}
|
|
42
|
+
const ISSUE_FIELDS = `number title body state stateReason createdAt updatedAt closedAt url author { __typename login }
|
|
43
|
+
labels(first:100) { nodes { name } pageInfo { hasNextPage endCursor } }`;
|
|
44
|
+
/** Fetch only the selected numbers, preserving partial failures and every label page. */
|
|
45
|
+
async function fetchRefreshBatch(repo, targets, token) {
|
|
46
|
+
const [owner, name] = repo.split("/");
|
|
47
|
+
const fields = targets.map(target => `i${target.number}: issue(number:${target.number}) { ${ISSUE_FIELDS} }`).join("\n");
|
|
48
|
+
const response = await githubGraphQLResponse(token, `query($owner:String!,$name:String!) { repository(owner:$owner,name:$name) { ${fields} } }`, { owner, name });
|
|
49
|
+
const results = [];
|
|
50
|
+
for (const target of targets) {
|
|
51
|
+
const alias = `i${target.number}`;
|
|
52
|
+
const error = response.errors?.find(error => !error.path || (error.path[0] === "repository" && (error.path.length === 1 || error.path[1] === alias)));
|
|
53
|
+
let reason;
|
|
54
|
+
const node = response.data.repository?.[alias];
|
|
55
|
+
if (error && error.type !== "NOT_FOUND")
|
|
56
|
+
reason = error.type === "FORBIDDEN" ? "inaccessible" : "api_error";
|
|
57
|
+
else if (response.data.repository === null || node === null)
|
|
58
|
+
reason = "not_found_or_inaccessible";
|
|
59
|
+
else if (node === undefined)
|
|
60
|
+
reason = "incomplete_response";
|
|
61
|
+
else if (node.url.toLowerCase() !== `https://github.com/${repo}/issues/${target.number}`)
|
|
62
|
+
reason = "transferred";
|
|
63
|
+
else if (node.number !== target.number || !node.title.trim() || !["OPEN", "CLOSED"].includes(node.state))
|
|
64
|
+
reason = "invalid_issue";
|
|
65
|
+
if (reason) {
|
|
66
|
+
results.push({ target, reason });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const issue = node;
|
|
70
|
+
const labels = [...issue.labels.nodes];
|
|
71
|
+
let page = issue.labels.pageInfo;
|
|
72
|
+
const cursors = new Set();
|
|
73
|
+
while (page.hasNextPage) {
|
|
74
|
+
if (!page.endCursor || cursors.has(page.endCursor))
|
|
75
|
+
throw new CommandError(`Refresh labels for issue #${target.number} have an invalid cursor.`);
|
|
76
|
+
cursors.add(page.endCursor);
|
|
77
|
+
const next = await githubGraphQLResponse(token, `query($owner:String!,$name:String!,$number:Int!,$cursor:String!) { repository(owner:$owner,name:$name) { issue(number:$number) { labels(first:100,after:$cursor) { nodes { name } pageInfo { hasNextPage endCursor } } } } }`, { owner, name, number: target.number, cursor: page.endCursor });
|
|
78
|
+
// A repository or issue can vanish between requests (transfer or delete);
|
|
79
|
+
// guard the connection so the host sees a CommandError, not a TypeError.
|
|
80
|
+
const connection = next.data?.repository?.issue?.labels ?? null;
|
|
81
|
+
if (next.errors?.length || connection === null)
|
|
82
|
+
throw new CommandError(`Refresh could not read every label for issue #${target.number}.`);
|
|
83
|
+
labels.push(...connection.nodes);
|
|
84
|
+
page = connection.pageInfo;
|
|
85
|
+
}
|
|
86
|
+
results.push({ target, issue: {
|
|
87
|
+
number: issue.number, title: issue.title, body: issue.body, state: issue.state.toLowerCase(),
|
|
88
|
+
state_reason: issue.stateReason?.toLowerCase(), labels,
|
|
89
|
+
created_at: issue.createdAt, updated_at: issue.updatedAt, closed_at: issue.closedAt,
|
|
90
|
+
html_url: issue.url, user: issue.author ? { login: issue.author.__typename === "Bot" ? `${issue.author.login.replace(/\[bot\]$/i, "")}[bot]` : issue.author.login } : null,
|
|
91
|
+
assignee: null, milestone: null,
|
|
92
|
+
} });
|
|
93
|
+
}
|
|
94
|
+
return results;
|
|
95
|
+
}
|
|
96
|
+
/** Compare only refresh-owned fields; use the same source lifecycle projection as import finalization. */
|
|
97
|
+
export function refreshChanges(entry) {
|
|
98
|
+
const desired = { ...importFidelityFields(entry.fidelity, Boolean(entry.linkOnly)),
|
|
99
|
+
...(entry.linkOnly ? {} : { title: entry.title, status: entry.status }), tags: entry.tags };
|
|
100
|
+
return Object.entries(desired).flatMap(([field, value]) => {
|
|
101
|
+
const old = entry.match[field] ?? null;
|
|
102
|
+
const next = value ?? null;
|
|
103
|
+
const equal = JSON.stringify(normalizeImportValue(field, old)) === JSON.stringify(normalizeImportValue(field, next));
|
|
104
|
+
return equal ? [] : [{ field, old, new: next }];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** Isolate SDK-derived cache writes for offline diagnostics, previews and no-op applies. @internal */
|
|
108
|
+
export async function readRefreshItems(pmRoot) {
|
|
109
|
+
const scratch = await mkdtemp(join(tmpdir(), "pm-github-refresh-read-"));
|
|
110
|
+
try {
|
|
111
|
+
if (!(await lstat(pmRoot)).isDirectory())
|
|
112
|
+
throw new CommandError("Offline tracker reads need an ordinary tracker directory; replace a linked root with a regular copy.");
|
|
113
|
+
const root = join(scratch, "pm");
|
|
114
|
+
await cp(pmRoot, root, { recursive: true, filter: source => !["runtime", "locks", "github-webhooks", "extensions"].includes(basename(source)) });
|
|
115
|
+
// Source permissions are retained by cp; only the disposable copy may host SDK caches.
|
|
116
|
+
await chmod(root, 0o700);
|
|
117
|
+
for (const entry of await readdir(root, { recursive: true, withFileTypes: true })) {
|
|
118
|
+
if (!entry.isDirectory() && !entry.isFile())
|
|
119
|
+
throw new CommandError("Offline tracker reads refuse linked or special files; use an ordinary tracker copy.");
|
|
120
|
+
await chmod(join(entry.parentPath, entry.name), entry.isDirectory() ? 0o700 : 0o600);
|
|
121
|
+
}
|
|
122
|
+
return decodeCompletePmItems(certifyCompleteListResult(await listAllComplete({ includeBody: true }, { pmRoot: root, cwd: root, noExtensions: true })));
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await rm(scratch, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** Build a zero-create refresh plan, then commit changed existing targets with import transactions. */
|
|
129
|
+
export async function runRefresh(repoArg, pmRoot, options, scope) {
|
|
130
|
+
if (!repoArg || !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repoArg))
|
|
131
|
+
throw new CommandError("Usage: pm github refresh <owner/repo> [--dry-run] [--since <date|relative>] [--limit N] [--atomic]", EXIT_CODE.USAGE);
|
|
132
|
+
const repo = repoArg.toLowerCase();
|
|
133
|
+
const opts = parseImportOptions(options);
|
|
134
|
+
/** Selected targets bounded by the caller's --limit, in ascending order. */
|
|
135
|
+
const bounded = (candidates) => (opts.limit === undefined ? [...candidates] : candidates.slice(0, opts.limit)).filter(target => scope === undefined || scope.numbers.includes(target.number));
|
|
136
|
+
let items = await readRefreshItems(pmRoot);
|
|
137
|
+
let all = selectRefreshTargets(items, repo);
|
|
138
|
+
let targets = bounded(all);
|
|
139
|
+
const token = resolveGitHubToken();
|
|
140
|
+
// Resume interrupted transactions for the selected targets BEFORE the
|
|
141
|
+
// unchanged filter: a crash after finalization leaves linked items already
|
|
142
|
+
// matching the source, so the pending journal would otherwise hide behind an
|
|
143
|
+
// ordinary no-op report and never commit.
|
|
144
|
+
const pending = (await listUnfinishedGithubImports(pmRoot))
|
|
145
|
+
.filter(journal => !journal.itemIds.length || journal.itemIds.some(id => targets.some(target => target.id === id)));
|
|
146
|
+
let resumed = 0;
|
|
147
|
+
if (pending.length) {
|
|
148
|
+
if (opts.dryRun) {
|
|
149
|
+
throw new CommandError(`Refresh cannot preview while GitHub transaction ${pending.map(journal => journal.transactionId).join(", ")} is unfinished for selected linked items. Re-run without --dry-run to complete it.`);
|
|
150
|
+
}
|
|
151
|
+
// Validate the complete recovery set before the first transaction can write.
|
|
152
|
+
const records = [];
|
|
153
|
+
for (const journal of pending) {
|
|
154
|
+
const record = await readGithubImportPlan(pmRoot, journal.transactionId);
|
|
155
|
+
if (!record || record.transactionId !== journal.transactionId) {
|
|
156
|
+
throw new CommandError(`Refresh found unfinished GitHub transaction ${journal.transactionId} (status ${journal.status}) for selected linked items, but its original plan is missing or mismatched. If it came from \`pm github import --atomic\`, re-run that import to resume it; otherwise resolve the durable journal at ${join(pmRoot, "transactions", "sdk", `${journal.transactionId}.json`)} manually; nothing was refreshed.`, EXIT_CODE.GENERIC_FAILURE);
|
|
157
|
+
}
|
|
158
|
+
validateGithubImportPlan(record, items);
|
|
159
|
+
if (record.repo.toLowerCase() !== repo) {
|
|
160
|
+
throw new CommandError(`Refresh cannot replay GitHub transaction ${journal.transactionId} for ${record.repo} while refreshing ${repo}. Re-run refresh for ${record.repo} first; nothing was refreshed.`);
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
await previewItemMutations({ pmRoot, transactionId: record.transactionId, author: "pm-github", mutations: record.mutations });
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
throw new CommandError(`Refresh cannot replay unfinished GitHub transaction ${journal.transactionId}: its persisted plan cannot resume the durable journal; nothing was refreshed.`);
|
|
167
|
+
}
|
|
168
|
+
records.push(record);
|
|
169
|
+
}
|
|
170
|
+
for (const record of records) {
|
|
171
|
+
await resumeGithubImport(pmRoot, record);
|
|
172
|
+
resumed++;
|
|
173
|
+
}
|
|
174
|
+
// The replay finalized the interrupted targets; re-read so this run
|
|
175
|
+
// compares the committed state instead of the pre-replay snapshot.
|
|
176
|
+
items = await readRefreshItems(pmRoot);
|
|
177
|
+
all = selectRefreshTargets(items, repo);
|
|
178
|
+
targets = bounded(all);
|
|
179
|
+
}
|
|
180
|
+
const plan = [];
|
|
181
|
+
const prepared = [];
|
|
182
|
+
let unchanged = 0;
|
|
183
|
+
let missing = 0;
|
|
184
|
+
let filtered = 0;
|
|
185
|
+
const context = { items, releases: readImportReleases(pmRoot), timeline: fetchImportTimeline };
|
|
186
|
+
for (let offset = 0; offset < targets.length; offset += 100) {
|
|
187
|
+
const batch = await fetchRefreshBatch(repo, targets.slice(offset, offset + 100), token);
|
|
188
|
+
for (const result of batch) {
|
|
189
|
+
const row = { id: result.target.id, number: result.target.number, changes: [] };
|
|
190
|
+
if (result.reason) {
|
|
191
|
+
row.reason = result.reason;
|
|
192
|
+
missing++;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
const issue = result.issue;
|
|
196
|
+
if (opts.since && Date.parse(issue.updated_at) < Date.parse(opts.since)) {
|
|
197
|
+
filtered++;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const entry = (await prepareGithubImport(issue, repo, opts, token, result.target.item, undefined, context));
|
|
201
|
+
row.changes = refreshChanges(entry);
|
|
202
|
+
if (row.changes.length)
|
|
203
|
+
prepared.push(entry);
|
|
204
|
+
else
|
|
205
|
+
unchanged++;
|
|
206
|
+
}
|
|
207
|
+
plan.push(row);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Validate all finalization projections even when applying one item at a time.
|
|
211
|
+
for (const entry of prepared)
|
|
212
|
+
validateGithubImportFidelity(entry, repo, `Refresh issue #${entry.issueNumber}`, items);
|
|
213
|
+
if (!opts.dryRun && prepared.length) {
|
|
214
|
+
if (opts.atomic)
|
|
215
|
+
await importGithubAtomic(pmRoot, repo, prepared, { updateOnly: true });
|
|
216
|
+
else
|
|
217
|
+
for (const entry of prepared)
|
|
218
|
+
await importGithubAtomic(pmRoot, repo, [entry], { updateOnly: true });
|
|
219
|
+
}
|
|
220
|
+
return { repo, dryRun: opts.dryRun, atomic: opts.atomic, selected: targets.length, filtered,
|
|
221
|
+
unchanged, updated: prepared.length, missing, created: 0, resumed, plan };
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Stable refusal discriminators; no secret, payload or storage path is included in diagnostics. */
|
|
2
|
+
export type WebhookRefusalCode = "invalid_signature" | "invalid_event" | "invalid_options" | "delivery_conflict" | "inbox_corrupt" | "inbox_unavailable" | "provider_unavailable";
|
|
3
|
+
/** A machine-readable refusal with an actionable, public-safe remedy. */
|
|
4
|
+
export declare class WebhookRefusal extends Error {
|
|
5
|
+
/** Recognized by the pm command host as a handled failure, preventing handler replay. */
|
|
6
|
+
readonly exitCode = 1;
|
|
7
|
+
/** Stable discriminator shared by SDK and CLI diagnostics. */
|
|
8
|
+
readonly code: WebhookRefusalCode;
|
|
9
|
+
/** Public-safe instructions for recovering from this refusal. */
|
|
10
|
+
readonly remedy: string;
|
|
11
|
+
/** Construct a typed refusal with a compact JSON diagnostic for CLI callers. */
|
|
12
|
+
constructor(code: WebhookRefusalCode, remedy: string);
|
|
13
|
+
}
|
|
14
|
+
/** Exact bytes and delivery headers supplied by the receiving adapter; secret stays in memory. */
|
|
15
|
+
export interface GithubWebhookDelivery {
|
|
16
|
+
repo: string;
|
|
17
|
+
delivery: string;
|
|
18
|
+
event: string;
|
|
19
|
+
signature: string;
|
|
20
|
+
secret: string;
|
|
21
|
+
payload: Uint8Array;
|
|
22
|
+
}
|
|
23
|
+
/** Compact proposed updates; fetch full values with polling refresh --dry-run before applying. */
|
|
24
|
+
export interface WebhookProposal {
|
|
25
|
+
id: string;
|
|
26
|
+
number: number;
|
|
27
|
+
fields: string[];
|
|
28
|
+
lifecycle: Array<{
|
|
29
|
+
field: string;
|
|
30
|
+
old: unknown;
|
|
31
|
+
new: unknown;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/** A bounded reconciliation receipt, also persisted for operator inspection. */
|
|
35
|
+
export interface WebhookReconciliation {
|
|
36
|
+
ok: true;
|
|
37
|
+
repo: string;
|
|
38
|
+
selected: number;
|
|
39
|
+
remaining: number;
|
|
40
|
+
reconciled: number;
|
|
41
|
+
retry: number;
|
|
42
|
+
unlinked: number;
|
|
43
|
+
proposals: WebhookProposal[];
|
|
44
|
+
recovery: string;
|
|
45
|
+
}
|
|
46
|
+
/** Authenticate exact bytes before parsing, locking, initializing storage or performing any write. */
|
|
47
|
+
export declare function acceptGithubWebhook(pmRoot: string, input: GithubWebhookDelivery): Promise<{
|
|
48
|
+
ok: true;
|
|
49
|
+
repo: string;
|
|
50
|
+
delivery: string;
|
|
51
|
+
duplicate: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
/** Read current provider state once per linked issue, persist compact proposals, and leave failed hints retryable. */
|
|
54
|
+
export declare function reconcileGithubWebhooks(pmRoot: string, repoArg: string, limit?: number): Promise<WebhookReconciliation>;
|
|
55
|
+
//# sourceMappingURL=webhooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../webhooks.ts"],"names":[],"mappings":"AAOA,oGAAoG;AACpG,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,eAAe,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,eAAe,GAAG,mBAAmB,GAAG,sBAAsB,CAAC;AAClL,yEAAyE;AACzE,qBAAa,cAAe,SAAQ,KAAK;IACvC,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,KAAK;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,YAAY,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAKnD;CACF;AACD,kGAAkG;AAClG,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;CACrB;AASD,kGAAkG;AAClG,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACjE;AACD,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiDD,sGAAsG;AACtG,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CA+BjK;AAWD,sHAAsH;AACtH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwCzH"}
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/** Durable authenticated issue-event hints; provider reads, never event payloads, produce proposals. */
|
|
2
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { open, mkdir, readdir, readFile } from "node:fs/promises";
|
|
4
|
+
import { join, basename } from "node:path";
|
|
5
|
+
import { acquireLock, writeFileAtomic } from "@unbrained/pm-cli/sdk";
|
|
6
|
+
import { runRefresh } from "./refresh.js";
|
|
7
|
+
/** A machine-readable refusal with an actionable, public-safe remedy. */
|
|
8
|
+
export class WebhookRefusal extends Error {
|
|
9
|
+
/** Recognized by the pm command host as a handled failure, preventing handler replay. */
|
|
10
|
+
exitCode = 1;
|
|
11
|
+
/** Stable discriminator shared by SDK and CLI diagnostics. */
|
|
12
|
+
code;
|
|
13
|
+
/** Public-safe instructions for recovering from this refusal. */
|
|
14
|
+
remedy;
|
|
15
|
+
/** Construct a typed refusal with a compact JSON diagnostic for CLI callers. */
|
|
16
|
+
constructor(code, remedy) {
|
|
17
|
+
super(JSON.stringify({ ok: false, code, remedy }));
|
|
18
|
+
this.name = "WebhookRefusal";
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.remedy = remedy;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Normalize an explicit repository boundary before opening storage. */
|
|
24
|
+
function repository(value) {
|
|
25
|
+
if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value))
|
|
26
|
+
throw new WebhookRefusal("invalid_options", "Supply an explicit owner/repo.");
|
|
27
|
+
return value.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
/** Narrow untrusted JSON without assuming the provider schema. */
|
|
30
|
+
function object(value) {
|
|
31
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
32
|
+
}
|
|
33
|
+
/** Hash public identities into fixed-length storage names. */
|
|
34
|
+
function hash(value) {
|
|
35
|
+
return createHash("sha256").update(value).digest("hex");
|
|
36
|
+
}
|
|
37
|
+
/** Preserve typed refusals while hiding native errors that may include paths or payloads. */
|
|
38
|
+
function refusal(error, code, remedy) {
|
|
39
|
+
if (error instanceof WebhookRefusal)
|
|
40
|
+
throw error;
|
|
41
|
+
throw new WebhookRefusal(code, remedy);
|
|
42
|
+
}
|
|
43
|
+
/** Flush published records and the containing directory before acknowledging durable intake. */
|
|
44
|
+
async function persist(file, value) {
|
|
45
|
+
await writeFileAtomic(file, JSON.stringify(value) + "\n");
|
|
46
|
+
await flush(file);
|
|
47
|
+
}
|
|
48
|
+
/** Finish a prior publisher's flush as well as a fresh receipt's durable acknowledgment. */
|
|
49
|
+
async function flush(file) {
|
|
50
|
+
for (const target of [file, join(file, ".."), join(file, "../.."), join(file, "../../..")]) {
|
|
51
|
+
const handle = await open(target, "r");
|
|
52
|
+
try {
|
|
53
|
+
await handle.sync();
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
await handle.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Serialize independent writers using the host's token-owned, crash-recoverable tracker lock. */
|
|
61
|
+
async function locked(pmRoot, repo, operation, lockId = "github-webhooks") {
|
|
62
|
+
try {
|
|
63
|
+
await readFile(join(pmRoot, "settings.json"), "utf8");
|
|
64
|
+
// Age alone cannot prove a worker is dead while it awaits provider or disk I/O.
|
|
65
|
+
const release = await acquireLock(pmRoot, lockId, 300, "pm-github", false, true, 5000);
|
|
66
|
+
try {
|
|
67
|
+
const parent = join(pmRoot, "github-webhooks");
|
|
68
|
+
await mkdir(parent, { recursive: true, mode: 0o700 });
|
|
69
|
+
const directory = join(parent, hash(repo));
|
|
70
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
71
|
+
return await operation(directory);
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
await release();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
refusal(error, "inbox_unavailable", "Restore initialized writable local tracker storage; inspect stale locks and recover only after confirming their worker has stopped, then retry; retain github-webhooks receipts.");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Authenticate exact bytes before parsing, locking, initializing storage or performing any write. */
|
|
82
|
+
export async function acceptGithubWebhook(pmRoot, input) {
|
|
83
|
+
if (!input.secret || !/^sha256=[a-f0-9]{64}$/.test(input.signature) ||
|
|
84
|
+
!timingSafeEqual(createHmac("sha256", input.secret).update(input.payload).digest(), Buffer.from(input.signature.slice(7), "hex"))) {
|
|
85
|
+
throw new WebhookRefusal("invalid_signature", "Supply the original unmodified payload bytes, X-Hub-Signature-256 and the matching webhook secret.");
|
|
86
|
+
}
|
|
87
|
+
const repo = repository(input.repo);
|
|
88
|
+
if (input.event !== "issues" || !/^[A-Za-z0-9-]{1,128}$/.test(input.delivery) || input.payload.byteLength > 25 * 1024 * 1024) {
|
|
89
|
+
throw new WebhookRefusal("invalid_event", "Supply an issues event, its original X-GitHub-Delivery identifier and a payload of at most 25 MiB.");
|
|
90
|
+
}
|
|
91
|
+
let payload;
|
|
92
|
+
try {
|
|
93
|
+
payload = object(JSON.parse(Buffer.from(input.payload).toString("utf8")));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new WebhookRefusal("invalid_event", "Supply the signed GitHub JSON payload without re-encoding it.");
|
|
97
|
+
}
|
|
98
|
+
const issue = object(payload.issue);
|
|
99
|
+
const source = object(payload.repository);
|
|
100
|
+
if (typeof payload.action !== "string" || !payload.action.trim() || typeof source.full_name !== "string" || source.full_name.toLowerCase() !== repo ||
|
|
101
|
+
!Number.isSafeInteger(issue.number) || Number(issue.number) < 1 || "pull_request" in issue) {
|
|
102
|
+
throw new WebhookRefusal("invalid_event", "Supply an issue event from the explicitly selected repository; pull requests and ambiguous identities are unsupported.");
|
|
103
|
+
}
|
|
104
|
+
const record = { version: 1, repo, delivery: input.delivery, digest: hash(input.payload), number: Number(issue.number) };
|
|
105
|
+
return locked(pmRoot, repo, async (directory) => {
|
|
106
|
+
const file = join(directory, `${hash(record.delivery)}.json`);
|
|
107
|
+
if ((await readdir(directory)).includes(`${hash(record.delivery)}.json`)) {
|
|
108
|
+
const existing = await readRecord(file, repo);
|
|
109
|
+
if (JSON.stringify(existing) !== JSON.stringify(record))
|
|
110
|
+
throw new WebhookRefusal("delivery_conflict", "The delivery identifier already names different bytes; retain both source receipts and investigate the adapter.");
|
|
111
|
+
// A previous process may have died after rename but before its flush.
|
|
112
|
+
await flush(file);
|
|
113
|
+
return { ok: true, repo, delivery: record.delivery, duplicate: true };
|
|
114
|
+
}
|
|
115
|
+
await persist(file, record);
|
|
116
|
+
return { ok: true, repo, delivery: record.delivery, duplicate: false };
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** Refuse malformed durable hints before fetching or acknowledging any selected delivery. */
|
|
120
|
+
async function readRecord(file, repo) {
|
|
121
|
+
try {
|
|
122
|
+
const value = object(JSON.parse(await readFile(file, "utf8")));
|
|
123
|
+
if (value.version !== 1 || value.repo !== repo || typeof value.delivery !== "string" || !/^[A-Za-z0-9-]{1,128}$/.test(value.delivery) ||
|
|
124
|
+
typeof value.digest !== "string" || !/^[a-f0-9]{64}$/.test(value.digest) || !Number.isSafeInteger(value.number) || Number(value.number) < 1 ||
|
|
125
|
+
basename(file) !== `${hash(value.delivery)}.json`)
|
|
126
|
+
throw new Error("invalid record");
|
|
127
|
+
return { version: 1, repo, delivery: value.delivery, digest: value.digest, number: Number(value.number) };
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
throw new WebhookRefusal("inbox_corrupt", "Restore the affected delivery receipt from backup or redelivery; do not delete the inbox. Poll with github refresh meanwhile.");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Read current provider state once per linked issue, persist compact proposals, and leave failed hints retryable. */
|
|
134
|
+
export async function reconcileGithubWebhooks(pmRoot, repoArg, limit = 20) {
|
|
135
|
+
const repo = repository(repoArg);
|
|
136
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
137
|
+
throw new WebhookRefusal("invalid_options", "Use a delivery limit from 1 to 100 (default 20).");
|
|
138
|
+
return locked(pmRoot, repo, async (directory) => {
|
|
139
|
+
const names = new Set(await readdir(directory));
|
|
140
|
+
const files = [...names].filter(file => /^[a-f0-9]{64}\.json$/.test(file)).sort();
|
|
141
|
+
const selected = files.filter(file => !names.has(file.replace(".json", ".done.json")));
|
|
142
|
+
let after = "";
|
|
143
|
+
if (names.has("cursor.json")) {
|
|
144
|
+
try {
|
|
145
|
+
const cursor = object(JSON.parse(await readFile(join(directory, "cursor.json"), "utf8")));
|
|
146
|
+
if (typeof cursor.after !== "string" || !/^[a-f0-9]{64}\.json$/.test(cursor.after))
|
|
147
|
+
throw new Error("invalid cursor");
|
|
148
|
+
after = cursor.after;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
throw new WebhookRefusal("inbox_corrupt", "Restore the reconciliation cursor from backup; retain delivery receipts and poll with github refresh meanwhile.");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const batch = [...selected.filter(file => file > after), ...selected.filter(file => file <= after)].slice(0, limit);
|
|
155
|
+
const records = await Promise.all(batch.map(file => readRecord(join(directory, file), repo)));
|
|
156
|
+
// Advance even when a provider request throws, so retries cannot starve later hints.
|
|
157
|
+
if (batch.length)
|
|
158
|
+
await persist(join(directory, "cursor.json"), { after: batch[batch.length - 1] });
|
|
159
|
+
let preview;
|
|
160
|
+
try {
|
|
161
|
+
preview = records.length ? await runRefresh(repo, pmRoot, { "dry-run": true }, { numbers: records.map(record => record.number) }) : undefined;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
refusal(error, "provider_unavailable", "Retry reconciliation after restoring GitHub access or completing unfinished imports with github refresh; pending deliveries are retained.");
|
|
165
|
+
}
|
|
166
|
+
const proposals = [];
|
|
167
|
+
for (const row of preview?.plan ?? []) {
|
|
168
|
+
if (row.changes.length)
|
|
169
|
+
proposals.push({ id: row.id, number: row.number, fields: row.changes.map(change => change.field),
|
|
170
|
+
lifecycle: row.changes.filter(change => ["status", "github_state", "github_updated_at", "closed_at", "completed_at"].includes(change.field)) });
|
|
171
|
+
}
|
|
172
|
+
let reconciled = 0;
|
|
173
|
+
let unlinked = 0;
|
|
174
|
+
for (const record of records) {
|
|
175
|
+
const row = preview.plan.find(entry => entry.number === record.number);
|
|
176
|
+
if (row?.reason)
|
|
177
|
+
continue;
|
|
178
|
+
if (!row)
|
|
179
|
+
unlinked++;
|
|
180
|
+
await persist(join(directory, `${hash(record.delivery)}.done.json`), { delivery: record.delivery, reconciledAt: new Date().toISOString(),
|
|
181
|
+
outcome: row ? "proposed" : "unlinked", proposals: proposals.filter(proposal => proposal.number === record.number) });
|
|
182
|
+
reconciled++;
|
|
183
|
+
}
|
|
184
|
+
return { ok: true, repo, selected: records.length, remaining: selected.length - reconciled, reconciled, retry: records.length - reconciled, unlinked,
|
|
185
|
+
proposals, recovery: `pm github refresh ${repo} --dry-run` };
|
|
186
|
+
}, "github-webhooks-reconcile");
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../webhooks.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C,yEAAyE;AACzE,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,yFAAyF;IAChF,QAAQ,GAAG,CAAC,CAAC;IACtB,8DAA8D;IACrD,IAAI,CAAqB;IAClC,iEAAiE;IACxD,MAAM,CAAS;IACxB,gFAAgF;IAChF,YAAY,IAAwB,EAAE,MAAc;QAClD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAsCD,wEAAwE;AACxE,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,iBAAiB,EAAE,gCAAgC,CAAC,CAAC;IACrI,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC;AACD,kEAAkE;AAClE,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAgC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtH,CAAC;AACD,8DAA8D;AAC9D,SAAS,IAAI,CAAC,KAA0B;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AACD,6FAA6F;AAC7F,SAAS,OAAO,CAAC,KAAc,EAAE,IAAwB,EAAE,MAAc;IACvE,IAAI,KAAK,YAAY,cAAc;QAAE,MAAM,KAAK,CAAC;IACjD,MAAM,IAAI,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AACD,gGAAgG;AAChG,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,KAAc;IACjD,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1D,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC;AACD,4FAA4F;AAC5F,KAAK,UAAU,KAAK,CAAC,IAAY;IAC/B,KAAK,MAAM,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAAC,CAAC;IAChE,CAAC;AACH,CAAC;AACD,kGAAkG;AAClG,KAAK,UAAU,MAAM,CAAI,MAAc,EAAE,IAAY,EAAE,SAA4C,EAAE,MAAM,GAAG,iBAAiB;IAC7H,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QACtD,gFAAgF;QAChF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACvF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACzD,OAAO,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YAAC,MAAM,OAAO,EAAE,CAAC;QAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,EAAE,mBAAmB,EAAE,kLAAkL,CAAC,CAAC;IAC1N,CAAC;AACH,CAAC;AACD,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,KAA4B;IACpF,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QACjE,CAAC,eAAe,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QACpI,MAAM,IAAI,cAAc,CAAC,mBAAmB,EAAE,oGAAoG,CAAC,CAAC;IACtJ,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;QAC7H,MAAM,IAAI,cAAc,CAAC,eAAe,EAAE,oGAAoG,CAAC,CAAC;IAClJ,CAAC;IACD,IAAI,OAAgC,CAAC;IACrC,IAAI,CAAC;QAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAClF,MAAM,CAAC;QAAC,MAAM,IAAI,cAAc,CAAC,eAAe,EAAE,+DAA+D,CAAC,CAAC;IAAC,CAAC;IACrH,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,IAAI;QACjJ,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,cAAc,IAAI,KAAK,EAAE,CAAC;QAC7F,MAAM,IAAI,cAAc,CAAC,eAAe,EAAE,wHAAwH,CAAC,CAAC;IACtK,CAAC;IACD,MAAM,MAAM,GAAgB,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACtI,OAAO,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAC,SAAS,EAAC,EAAE;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9C,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,mBAAmB,EAAE,iHAAiH,CAAC,CAAC;YAC1N,sEAAsE;YACtE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACxE,CAAC;QACD,MAAM,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AACD,6FAA6F;AAC7F,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,IAAY;IAClD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;YACnI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;YAC3I,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACvF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IAC5G,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,IAAI,cAAc,CAAC,eAAe,EAAE,+HAA+H,CAAC,CAAC;IAAC,CAAC;AACzL,CAAC;AACD,sHAAsH;AACtH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAc,EAAE,OAAe,EAAE,KAAK,GAAG,EAAE;IACvF,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG;QAAE,MAAM,IAAI,cAAc,CAAC,iBAAiB,EAAE,kDAAkD,CAAC,CAAC;IAC9J,OAAO,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAC,SAAS,EAAC,EAAE;QAC5C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QACvF,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC1F,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBACtH,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBAAC,MAAM,IAAI,cAAc,CAAC,eAAe,EAAE,iHAAiH,CAAC,CAAC;YAAC,CAAC;QAC3K,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACpH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9F,qFAAqF;QACrF,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACpG,IAAI,OAA2D,CAAC;QAChE,IAAI,CAAC;YAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAAC,CAAC;QACtJ,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,EAAE,sBAAsB,EAAE,2IAA2I,CAAC,CAAC;QAAC,CAAC;QACtM,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM;gBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;oBACtH,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,mBAAmB,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QACpJ,CAAC;QACD,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,OAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;YACxE,IAAI,GAAG,EAAE,MAAM;gBAAE,SAAS;YAC1B,IAAI,CAAC,GAAG;gBAAE,QAAQ,EAAE,CAAC;YACrB,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACtI,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxH,UAAU,EAAE,CAAC;QACf,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,GAAG,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,QAAQ;YAClJ,SAAS,EAAE,QAAQ,EAAE,qBAAqB,IAAI,YAAY,EAAE,CAAC;IACjE,CAAC,EAAE,2BAA2B,CAAC,CAAC;AAClC,CAAC"}
|
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-github",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.24",
|
|
4
4
|
"description": "GitHub Issues + Projects v2 integration. Imports issues as pm items (`pm github import`), exports pm items as GitHub issues, syncs issue state, and bidirectionally syncs pm items with a GitHub Projects v2 board (`pm github project import/sync/list/fields`) — mapping pm status to the board Status column with idempotent, no-data-loss provenance.",
|
|
5
5
|
"author": "@unbraind",
|
|
6
6
|
"entry": "./dist/index.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-github",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.24",
|
|
4
4
|
"description": "GitHub Issues importer extension for pm-cli",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"changelog:check": "npm run changelog:full -- --check",
|
|
35
35
|
"release:check": "npm run typecheck && npm run build && npm run docstring && npm run lint && npm run duplication && npm run privacy && npm run coverage && npm run audit:prod && npm run pack:dry-run && npm run changelog:check && npm run verify:release-publish-attestation",
|
|
36
36
|
"prepublishOnly": "npm run release:check",
|
|
37
|
-
"release:notes": "pm-changelog --pm-root .agents/pm --pm-arg=--output-limit --pm-arg=unbounded --pm-arg=--output-budget --pm-arg=unbounded --stdout --since-previous-tag --until-release-tag --release-version-from-package --date-from-version --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release --pm-bin ./node_modules/.bin/pm
|
|
37
|
+
"release:notes": "pm-changelog --pm-root .agents/pm --pm-arg=--output-limit --pm-arg=unbounded --pm-arg=--output-budget --pm-arg=unbounded --stdout --since-previous-tag --until-release-tag --release-version-from-package --date-from-version --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --respect-item-release --pm-bin ./node_modules/.bin/pm",
|
|
38
38
|
"prepare": "node scripts/prepare-merge-driver.ts",
|
|
39
39
|
"merge:install": "pm merge install",
|
|
40
40
|
"coverage": "npm run build && npm run build:test && node scripts/coverage-gate.ts",
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"@babel/plugin-syntax-typescript": "8.0.3",
|
|
52
52
|
"@toon-format/toon": "4.4.0",
|
|
53
53
|
"@types/node": "26.6.5",
|
|
54
|
-
"@unbrained/pm-cli": "2026.10.
|
|
54
|
+
"@unbrained/pm-cli": "2026.10.20",
|
|
55
55
|
"c8": "12.0.0",
|
|
56
|
-
"eslint": "10.
|
|
56
|
+
"eslint": "10.13.0",
|
|
57
57
|
"jscpd": "5.4.1",
|
|
58
|
-
"pm-changelog": "2026.10.
|
|
59
|
-
"pm-ops": "2026.10.
|
|
58
|
+
"pm-changelog": "2026.10.20",
|
|
59
|
+
"pm-ops": "2026.10.20",
|
|
60
60
|
"typescript": "7.0.2"
|
|
61
61
|
},
|
|
62
62
|
"keywords": [
|
|
@@ -124,5 +124,8 @@
|
|
|
124
124
|
"duplicationGate": {
|
|
125
125
|
"threshold": 0,
|
|
126
126
|
"minTokens": 50
|
|
127
|
+
},
|
|
128
|
+
"dependencies": {
|
|
129
|
+
"entities": "8.1.0"
|
|
127
130
|
}
|
|
128
131
|
}
|