117 lines
3.3 KiB
JavaScript
117 lines
3.3 KiB
JavaScript
import { mkdtemp } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
export function createWorkflowHelpers(run) {
|
|
async function ghJson(args) {
|
|
const { stdout } = await run("gh", args, { capture: true });
|
|
return JSON.parse(stdout);
|
|
}
|
|
|
|
async function getGitHubHttpAuthHeader() {
|
|
const tokenResult = await run("gh", ["auth", "token"], { capture: true });
|
|
const token = tokenResult.stdout.trim();
|
|
if (!token) {
|
|
throw new Error("Unable to read a GitHub token from gh auth.");
|
|
}
|
|
return Buffer.from(`x-access-token:${token}`).toString("base64");
|
|
}
|
|
|
|
async function getRepoInfo() {
|
|
const info = await ghJson(["repo", "view", "--json", "nameWithOwner,defaultBranchRef"]);
|
|
const defaultBranch = info.defaultBranchRef?.name;
|
|
if (!info.nameWithOwner || !defaultBranch) {
|
|
throw new Error("Unable to resolve GitHub repository name/default branch from gh.");
|
|
}
|
|
return {
|
|
nameWithOwner: info.nameWithOwner,
|
|
defaultBranch,
|
|
};
|
|
}
|
|
|
|
async function assertRemoteWorkflowExists(repo, workflowFile, errorMessage) {
|
|
try {
|
|
await run("gh", [
|
|
"api",
|
|
`repos/${repo.nameWithOwner}/contents/${workflowFile}?ref=${repo.defaultBranch}`,
|
|
], { capture: true });
|
|
} catch {
|
|
throw new Error(errorMessage);
|
|
}
|
|
}
|
|
|
|
async function waitForWorkflowRun(repo, workflowName, branchName, timeoutMs) {
|
|
const startedAt = Date.now();
|
|
while (Date.now() - startedAt < timeoutMs) {
|
|
const runs = await ghJson([
|
|
"run",
|
|
"list",
|
|
"--repo",
|
|
repo.nameWithOwner,
|
|
"--workflow",
|
|
workflowName,
|
|
"--branch",
|
|
branchName,
|
|
"--limit",
|
|
"1",
|
|
"--json",
|
|
"databaseId,status,conclusion,url,displayTitle",
|
|
]);
|
|
if (runs.length > 0) {
|
|
return runs[0];
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
}
|
|
throw new Error(`Timed out waiting for workflow ${workflowName} on branch ${branchName}.`);
|
|
}
|
|
|
|
async function waitForWorkflowCompletion(repo, runId, timeoutMs) {
|
|
const startedAt = Date.now();
|
|
while (Date.now() - startedAt < timeoutMs) {
|
|
const runInfo = await ghJson([
|
|
"run",
|
|
"view",
|
|
String(runId),
|
|
"--repo",
|
|
repo.nameWithOwner,
|
|
"--json",
|
|
"status,conclusion,url",
|
|
]);
|
|
if (runInfo.status === "completed") {
|
|
return runInfo;
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, 15000));
|
|
}
|
|
throw new Error(`Timed out waiting for workflow run ${runId} to complete.`);
|
|
}
|
|
|
|
async function downloadRemoteAssets(repo, releaseTag) {
|
|
const downloadRoot = await mkdtemp(join(os.tmpdir(), "agentcompany-transport-"));
|
|
await run("gh", [
|
|
"release",
|
|
"download",
|
|
releaseTag,
|
|
"--repo",
|
|
repo.nameWithOwner,
|
|
"-D",
|
|
downloadRoot,
|
|
]);
|
|
return downloadRoot;
|
|
}
|
|
|
|
async function cleanupRemoteTransportRelease(repo, releaseTag) {
|
|
await run("gh", ["release", "delete", releaseTag, "--repo", repo.nameWithOwner, "--yes"]);
|
|
}
|
|
|
|
return {
|
|
ghJson,
|
|
getGitHubHttpAuthHeader,
|
|
getRepoInfo,
|
|
assertRemoteWorkflowExists,
|
|
waitForWorkflowRun,
|
|
waitForWorkflowCompletion,
|
|
downloadRemoteAssets,
|
|
cleanupRemoteTransportRelease,
|
|
};
|
|
}
|