Page MenuHomeSealhub

arcanist.mjs
No OneTemporary

arcanist.mjs

import { $ } from "zx";
if (argv.length < 2) {
console.error(`Usage: ${process.argv[1]} <task-id>`);
process.exit(1);
}
const taskId = argv[1];
// helper: run arc conduit call and parse JSON
export async function arcCall(endpoint, payload) {
const { stdout } =
await $`echo ${JSON.stringify(payload)} | arc call-conduit ${endpoint} --`;
return JSON.parse(stdout).response;
}
export async function getTask(task_id) {
task_id = parseInt(task_id.replace("T", ""));
const taskResp = await arcCall("maniphest.search", {
constraints: { ids: [task_id] },
});
if (!taskResp.data?.length) {
throw new Error(`Task ${taskId} not found.`);
}
return taskResp;
}
export async function getReposAndDiffsForTask(task_id) {
const taskResp = await getTask(task_id);
const taskPHID = taskResp.data[0].phid;
// 2. Use edge.search to find edges from the task -> revisions
// We want edges of type "task.revision" or maybe "revision.task" depending on source/destination
const edgeResp = await arcCall("edge.search", {
sourcePHIDs: [taskPHID],
types: ["task.revision"],
// Could also try types: ["revision.task"] or add destinationPHIDs etc
limit: 100,
});
const edges = edgeResp.data;
if (!edges || edges.length === 0) {
console.log(`No revisions edges found for task ${taskId}`);
process.exit(1);
}
// edges are objects with `source`, `destination`, `type`
// For task.revision, `source` is the task, `destination` is the revision PHID
const revisionPHIDs = edges.map((e) => e.destinationPHID);
// 3. For each revision PHID, fetch revision info via differential.revision.search
const revInfo = await arcCall("differential.revision.search", {
constraints: {
phids: revisionPHIDs,
},
});
// Map from revision PHID to {id, repositoryPHID}
const revMap = {};
for (const rev of revInfo.data) {
revMap[rev.phid] = {
id: rev.id,
repositoryPHID: rev.fields.repositoryPHID,
};
}
// 4. Fetch repository names for those repos
// Collect unique repository PHIDs
const repoPHIDs = Array.from(
new Set(
Object.values(revMap)
.map((r) => r.repositoryPHID)
.filter((rphid) => rphid != null),
),
);
let repoMap = {};
if (repoPHIDs.length > 0) {
const repoInfo = await arcCall("diffusion.repository.search", {
constraints: {
phids: repoPHIDs,
},
});
for (const repo of repoInfo.data) {
repoMap[repo.phid] = repo.fields.shortName || repo.fields.name; // shortName preferred
}
}
const ret = [];
for (const edge of edges) {
const revPHID = edge.destinationPHID;
const rev = revMap[revPHID];
if (!rev) {
console.log(` (unknown revision PHID ${revPHID})`);
continue;
}
const repoPHID = rev.repositoryPHID;
const repoName =
repoPHID && repoMap[repoPHID] ? repoMap[repoPHID] : "(unknown repo)";
ret.push({ repository: repoName, revision: `D${rev.id}` });
}
return ret;
}

File Metadata

Mime Type
text/x-java
Expires
Sat, Nov 8, 08:31 (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1034356
Default Alt Text
arcanist.mjs (2 KB)

Event Timeline