@archme/cli 0.11.2 → 0.11.3
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/dist/cli.js +107 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -17291,6 +17291,16 @@ var init_defaultBranch = __esm({
|
|
|
17291
17291
|
});
|
|
17292
17292
|
|
|
17293
17293
|
// ../shared/prRefs.ts
|
|
17294
|
+
function parsePrRefs(message) {
|
|
17295
|
+
if (!message) return [];
|
|
17296
|
+
const refs = [...message.matchAll(PR_REF)].map((m) => Number(m[1]));
|
|
17297
|
+
const bare = refs.length ? null : bareMergePrNumber(message);
|
|
17298
|
+
return bare === null ? refs : [bare];
|
|
17299
|
+
}
|
|
17300
|
+
function lastPrRef(message) {
|
|
17301
|
+
const refs = parsePrRefs(message);
|
|
17302
|
+
return refs[refs.length - 1] ?? null;
|
|
17303
|
+
}
|
|
17294
17304
|
function pushCommitSubject(message) {
|
|
17295
17305
|
if (message == null) return null;
|
|
17296
17306
|
const [subject = "", ...body] = message.split("\n");
|
|
@@ -17298,10 +17308,15 @@ function pushCommitSubject(message) {
|
|
|
17298
17308
|
const title = body.find((line) => line.trim())?.trim();
|
|
17299
17309
|
return pr && title && !TRAILER_LINE.test(title) ? `${title} (#${pr[1]})` : subject;
|
|
17300
17310
|
}
|
|
17301
|
-
|
|
17311
|
+
function bareMergePrNumber(subject) {
|
|
17312
|
+
const pr = subject ? MERGE_PR_SUBJECT.exec(subject.trim()) : null;
|
|
17313
|
+
return pr ? Number(pr[1]) : null;
|
|
17314
|
+
}
|
|
17315
|
+
var PR_REF, MERGE_PR_SUBJECT, TRAILER_LINE;
|
|
17302
17316
|
var init_prRefs = __esm({
|
|
17303
17317
|
"../shared/prRefs.ts"() {
|
|
17304
17318
|
init_repoContainer();
|
|
17319
|
+
PR_REF = /\(#(\d+)\)/g;
|
|
17305
17320
|
MERGE_PR_SUBJECT = /^Merge pull request #(\d+) from \S+$/;
|
|
17306
17321
|
TRAILER_LINE = /^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+:\s/;
|
|
17307
17322
|
}
|
|
@@ -17676,6 +17691,87 @@ var init_localPrAdapters = __esm({
|
|
|
17676
17691
|
}
|
|
17677
17692
|
});
|
|
17678
17693
|
|
|
17694
|
+
// ../shared/pushSubject.ts
|
|
17695
|
+
async function resolvePushSubject(message, push, lookup, timeoutMs = PUSH_SUBJECT_TIMEOUT_MS) {
|
|
17696
|
+
const subject = pushCommitSubject(message);
|
|
17697
|
+
if (!subject) return subject;
|
|
17698
|
+
const bare = bareMergePrNumber(subject);
|
|
17699
|
+
if (bare === null && lastPrRef(subject) !== null) return subject;
|
|
17700
|
+
try {
|
|
17701
|
+
const found = await withTimeout(findPr(subject, bare, push, lookup), timeoutMs);
|
|
17702
|
+
return found ? `${found.title} (#${found.number})` : subject;
|
|
17703
|
+
} catch {
|
|
17704
|
+
return subject;
|
|
17705
|
+
}
|
|
17706
|
+
}
|
|
17707
|
+
async function findPr(subject, bare, push, lookup) {
|
|
17708
|
+
if (bare !== null) {
|
|
17709
|
+
const title = (await lookup.pullTitle(bare))?.trim();
|
|
17710
|
+
return title ? { number: bare, title } : null;
|
|
17711
|
+
}
|
|
17712
|
+
const pr = mergedPrForCommit(await lookup.pullsForCommit(push.sha), push);
|
|
17713
|
+
return pr ? { number: pr.number, title: pr.title?.trim() || subject } : null;
|
|
17714
|
+
}
|
|
17715
|
+
function mergedPrForCommit(prs, push) {
|
|
17716
|
+
const merged = prs.filter((p) => p.mergedAt && (!p.baseRef || p.baseRef === push.branch));
|
|
17717
|
+
const exact = merged.filter((p) => p.mergeCommitSha === push.sha);
|
|
17718
|
+
if (exact.length === 1) return exact[0] ?? null;
|
|
17719
|
+
return merged.length === 1 ? merged[0] ?? null : null;
|
|
17720
|
+
}
|
|
17721
|
+
function withTimeout(work, ms) {
|
|
17722
|
+
let timer;
|
|
17723
|
+
const expired = new Promise((_, reject) => {
|
|
17724
|
+
timer = setTimeout(() => reject(new Error("timed out")), ms);
|
|
17725
|
+
});
|
|
17726
|
+
return Promise.race([work, expired]).finally(() => clearTimeout(timer));
|
|
17727
|
+
}
|
|
17728
|
+
function githubPrLookup(opts) {
|
|
17729
|
+
const doFetch = opts.fetch ?? fetch;
|
|
17730
|
+
let tokens = null;
|
|
17731
|
+
async function get(path7) {
|
|
17732
|
+
tokens ??= opts.tokens();
|
|
17733
|
+
for (const token of await tokens) {
|
|
17734
|
+
const res = await doFetch(`${GITHUB_API}/repos/${opts.repo}${path7}`, {
|
|
17735
|
+
headers: {
|
|
17736
|
+
Accept: "application/vnd.github+json",
|
|
17737
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
17738
|
+
"User-Agent": "archme",
|
|
17739
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
17740
|
+
}
|
|
17741
|
+
});
|
|
17742
|
+
if (REFUSED.has(res.status)) continue;
|
|
17743
|
+
return res.ok ? await res.json() : null;
|
|
17744
|
+
}
|
|
17745
|
+
return null;
|
|
17746
|
+
}
|
|
17747
|
+
return {
|
|
17748
|
+
async pullTitle(prNumber) {
|
|
17749
|
+
const pr = await get(`/pulls/${prNumber}`);
|
|
17750
|
+
return typeof pr?.title === "string" ? pr.title : null;
|
|
17751
|
+
},
|
|
17752
|
+
async pullsForCommit(sha) {
|
|
17753
|
+
const prs = await get(`/commits/${sha}/pulls`);
|
|
17754
|
+
if (!Array.isArray(prs)) return [];
|
|
17755
|
+
return prs.map((p) => ({
|
|
17756
|
+
number: Number(p.number),
|
|
17757
|
+
title: typeof p.title === "string" ? p.title : null,
|
|
17758
|
+
mergedAt: p.merged_at ?? null,
|
|
17759
|
+
mergeCommitSha: p.merge_commit_sha ?? null,
|
|
17760
|
+
baseRef: p.base?.ref ?? null
|
|
17761
|
+
}));
|
|
17762
|
+
}
|
|
17763
|
+
};
|
|
17764
|
+
}
|
|
17765
|
+
var PUSH_SUBJECT_TIMEOUT_MS, GITHUB_API, REFUSED;
|
|
17766
|
+
var init_pushSubject = __esm({
|
|
17767
|
+
"../shared/pushSubject.ts"() {
|
|
17768
|
+
init_prRefs();
|
|
17769
|
+
PUSH_SUBJECT_TIMEOUT_MS = 3e3;
|
|
17770
|
+
GITHUB_API = "https://api.github.com";
|
|
17771
|
+
REFUSED = /* @__PURE__ */ new Set([401, 403, 404]);
|
|
17772
|
+
}
|
|
17773
|
+
});
|
|
17774
|
+
|
|
17679
17775
|
// src/daemon/localPoller.ts
|
|
17680
17776
|
async function pollRepoOnce(entry, deps) {
|
|
17681
17777
|
const repo = `${entry.repoOwner}/${entry.repoName}`;
|
|
@@ -17849,6 +17945,14 @@ function makePollerDeps(client, log, gateTimeoutMs) {
|
|
|
17849
17945
|
},
|
|
17850
17946
|
async enqueue(entry, row, beforeSha, afterSha) {
|
|
17851
17947
|
const meta = await readCommitMeta(entry.mirrorPath, afterSha);
|
|
17948
|
+
const subject = await resolvePushSubject(
|
|
17949
|
+
meta.message || null,
|
|
17950
|
+
{ sha: afterSha, branch: row.repoBranch },
|
|
17951
|
+
githubPrLookup({
|
|
17952
|
+
repo: `${entry.repoOwner}/${entry.repoName}`,
|
|
17953
|
+
tokens: async () => (await resolveGithubTokens()).map((t) => t.token)
|
|
17954
|
+
})
|
|
17955
|
+
);
|
|
17852
17956
|
const { data, error } = await client.rpc("enqueue_local_archme_job", {
|
|
17853
17957
|
p_watched_repo_id: entry.watchedRepoId,
|
|
17854
17958
|
// From the ROW, not the registry: these decide which lane the job lands
|
|
@@ -17857,7 +17961,7 @@ function makePollerDeps(client, log, gateTimeoutMs) {
|
|
|
17857
17961
|
p_archme_branch: row.archmeBranch,
|
|
17858
17962
|
p_before_sha: beforeSha,
|
|
17859
17963
|
p_after_sha: afterSha,
|
|
17860
|
-
p_commit_message:
|
|
17964
|
+
p_commit_message: subject,
|
|
17861
17965
|
p_head_commit_timestamp: meta.committedAt,
|
|
17862
17966
|
p_author_name: meta.authorName,
|
|
17863
17967
|
// `author_login` is a GitHub concept with no git equivalent. The webhook
|
|
@@ -17884,6 +17988,7 @@ var init_localPoller = __esm({
|
|
|
17884
17988
|
init_branchMarker();
|
|
17885
17989
|
init_localGit();
|
|
17886
17990
|
init_localPrAdapters();
|
|
17991
|
+
init_pushSubject();
|
|
17887
17992
|
DEFAULT_POLL_INTERVAL_MS = 6e4;
|
|
17888
17993
|
DEFAULT_GATE_TIMEOUT_MS = 4 * 60 * 60 * 1e3;
|
|
17889
17994
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archme/cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "Map your codebase into a living architecture diagram: run `archme init` in a repo to scan it, `archme daemon start` to keep it current on every commit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|