@outerlayer/cli 0.6.0 → 0.7.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/CHANGELOG.md +18 -0
- package/README.md +10 -0
- package/dist/{agent-setup-USZ2SAXC.js → agent-setup-TXLDY5RV.js} +7 -6
- package/dist/{build-PAEKVYVK.js → build-JF5UOWKJ.js} +2 -1
- package/dist/build-info.json +1 -1
- package/dist/{check-CCVPBN7A.js → check-ASZL5BEO.js} +29 -23
- package/dist/{chunk-ZILGTTY6.js → chunk-2VO25HHO.js} +3 -3
- package/dist/{chunk-OIRNH6UO.js → chunk-5FWNEQNZ.js} +3 -3
- package/dist/{chunk-MXB5VB4Y.js → chunk-6IYLDODX.js} +6 -6
- package/dist/{chunk-4NLKY4WR.js → chunk-6QWV3YDJ.js} +2 -2
- package/dist/{chunk-UMFWVGJO.js → chunk-6ZZHWY2Z.js} +4 -3
- package/dist/{chunk-NQXFAGHU.js → chunk-7FTNIAHS.js} +1 -1
- package/dist/{chunk-EMY4I27X.js → chunk-7ZR5UPMB.js} +555 -5
- package/dist/{chunk-43J3M6KB.js → chunk-AII7CKTH.js} +45 -31
- package/dist/{chunk-VMJ3MMBX.js → chunk-AJKEHABI.js} +312 -18
- package/dist/{chunk-RBOMWNOG.js → chunk-AQ54MKSQ.js} +2 -2
- package/dist/{chunk-Z62HNKEJ.js → chunk-CEBIA5FD.js} +31 -5
- package/dist/{chunk-ANK2B36Y.js → chunk-D6FXM5OW.js} +6182 -28607
- package/dist/{chunk-BNMCXPG7.js → chunk-DGAIVMMN.js} +12 -3
- package/dist/{chunk-3DD6AOWC.js → chunk-DTXOJDEH.js} +26 -2
- package/dist/{chunk-RZSF5B46.js → chunk-E4PIFIC3.js} +100 -15
- package/dist/{chunk-H5NCNVDA.js → chunk-EV3M3EH7.js} +2 -2
- package/dist/chunk-HKMPVPO7.js +55 -0
- package/dist/{chunk-FA2BOX4O.js → chunk-JPR2WHHF.js} +1 -1
- package/dist/{chunk-ZMYPLFG3.js → chunk-M3SQ4YGD.js} +1 -1
- package/dist/{chunk-MIGEDH5P.js → chunk-MQPRB5K7.js} +9 -9
- package/dist/{chunk-AUFG23AA.js → chunk-OD2VTIHN.js} +19 -47
- package/dist/chunk-PUN7LMNS.js +39 -0
- package/dist/{chunk-JWOQNNN2.js → chunk-Q5G2ODUZ.js} +1 -1
- package/dist/{chunk-B2G7JHHB.js → chunk-R7STSBLC.js} +1 -1
- package/dist/{chunk-PMAMOSTP.js → chunk-SSU747O6.js} +85 -25
- package/dist/{chunk-YYYXRJUW.js → chunk-TI7B7UEO.js} +1 -1
- package/dist/{chunk-WO2BXCTQ.js → chunk-VXLJORHL.js} +1 -1
- package/dist/{chunk-CBPPJSAR.js → chunk-WVGSB3Z2.js} +2 -2
- package/dist/{chunk-IASWYRVG.js → chunk-X2FSFU4C.js} +4 -1
- package/dist/chunk-YNJEOGDL.js +22434 -0
- package/dist/{chunk-W4SQCOZU.js → chunk-ZOAEPWGL.js} +1 -1
- package/dist/{chunk-3DEVYTNQ.js → chunk-ZYHKJKSU.js} +1 -1
- package/dist/{chunk-WIOZAJ2W.js → chunk-ZZXLM64C.js} +1 -1
- package/dist/{cli-7WCNPBYC.js → cli-LEVCGAQV.js} +73 -71
- package/dist/{command-ARFK3OYF.js → command-FLSYCGIB.js} +47 -22
- package/dist/config-I3TVFYLH.js +10 -0
- package/dist/{connect-cmd-PCESZLTR.js → connect-cmd-MJMUONDY.js} +4 -4
- package/dist/{context-adopt-G5JAELE7.js → context-adopt-CE4KDXS3.js} +5 -4
- package/dist/{context-materialize-3HLPZAF6.js → context-materialize-QL33HDJN.js} +5 -4
- package/dist/{dist-RDLP4GGJ.js → dist-PXBSA7QX.js} +2 -1
- package/dist/{doctor-VOMYOHQU.js → doctor-FVDT3KJZ.js} +23 -16
- package/dist/{emit-artifact-cmd-TBF46VXZ.js → emit-artifact-cmd-7RPMRSVP.js} +11 -4
- package/dist/{emit-cmd-DCERAU27.js → emit-cmd-2QRMYPYO.js} +4 -3
- package/dist/{emit-criteria-cmd-3427XKFW.js → emit-criteria-cmd-MKI7WETO.js} +10 -1
- package/dist/{emit-finding-cmd-GSI75K36.js → emit-finding-cmd-RMLGZASB.js} +12 -1
- package/dist/{emit-result-cmd-3PRQKB55.js → emit-result-cmd-MTXAZ2GV.js} +13 -6
- package/dist/{exec-client-4XGXV3XN.js → exec-client-NPYNUAF3.js} +4 -3
- package/dist/{guest-init-GENRHNP7.js → guest-init-JWNNAH2H.js} +4 -3
- package/dist/{hook-fast-NJBBZQ5Q.js → hook-fast-XBOZ3N6L.js} +1 -1
- package/dist/{import-capture-cmd-AVZ4VIVJ.js → import-capture-cmd-T4556ELW.js} +3 -2
- package/dist/{import-ruler-cmd-GUHL6IY5.js → import-ruler-cmd-SG3UVGI7.js} +2 -1
- package/dist/index.js +3 -3
- package/dist/{init-WVR4BZQ4.js → init-BACXESVV.js} +21 -14
- package/dist/{init-OHYFIKZD.js → init-VLW7H6RW.js} +22 -15
- package/dist/{init-cmd-HMFNIFPI.js → init-cmd-VJFB5L7X.js} +10 -9
- package/dist/{install-DSUZE2TJ.js → install-NMAPLLBQ.js} +4 -3
- package/dist/{install-cmd-453C7IZT.js → install-cmd-B5SEU3G7.js} +2 -2
- package/dist/{logs-7RYUH5A6.js → logs-H55NWW4H.js} +1 -0
- package/dist/{loop-UAJB34KA.js → loop-D3243JKT.js} +29 -23
- package/dist/{machine-2JOWGRSZ.js → machine-EB3GEVI4.js} +20 -13
- package/dist/{session-sender-ED26V45B.js → session-sender-LMACEJJS.js} +6 -5
- package/dist/{starter-pack-LIZYMKYQ.js → starter-pack-MUXMAU4S.js} +4 -3
- package/dist/{status-6WNXX2O7.js → status-F4THTJJK.js} +24 -18
- package/dist/{sync-cmd-YONVGUYS.js → sync-cmd-M6JA3OEE.js} +5 -4
- package/dist/{watch-HHKAF26L.js → watch-NB5TGPEZ.js} +5 -4
- package/dist/{work-claim-cmd-LXBZTMJA.js → work-claim-cmd-UHMWOS3G.js} +13 -6
- package/dist/{work-cmd-OVNF44FY.js → work-cmd-6UMCFTAW.js} +9 -3
- package/dist/{work-comment-cmd-6DGQNTAH.js → work-comment-cmd-E4LEUIXZ.js} +9 -3
- package/dist/{work-open-pr-cmd-FCZHFHZS.js → work-open-pr-cmd-OPZWGSEQ.js} +10 -4
- package/dist/{work-pr-cmd-QJJVHZDC.js → work-pr-cmd-IDIAFFRU.js} +9 -2
- package/package.json +1 -1
- package/skill-pack/template/build/scripts/record-criteria.mjs +2 -1
- package/dist/chunk-7DBI6SNT.js +0 -55
- package/dist/config-HL2AIR3K.js +0 -9
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-ABIWDUMS.js';
|
|
4
|
-
import { readMarker, currentVersion, removeMarker, writeMarker, entryIn, versionDir, switchCurrent, cleanVersions, isInLayout, startedThroughCurrent, stagingDir } from './chunk-
|
|
5
|
-
import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode,
|
|
4
|
+
import { readMarker, currentVersion, removeMarker, writeMarker, entryIn, versionDir, switchCurrent, cleanVersions, isInLayout, startedThroughCurrent, stagingDir } from './chunk-TI7B7UEO.js';
|
|
5
|
+
import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-AJKEHABI.js';
|
|
6
6
|
import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-T6OIJQRT.js';
|
|
7
7
|
import { RUNNER_PROTOCOL } from './chunk-AIW6GLET.js';
|
|
8
8
|
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
|
|
9
|
-
import { placeholderQueues, placeholderProblem } from './chunk-
|
|
9
|
+
import { placeholderQueues, placeholderProblem } from './chunk-6IYLDODX.js';
|
|
10
10
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
11
11
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
12
12
|
import { checkFit } from './chunk-OUUINEYB.js';
|
|
13
|
-
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode,
|
|
13
|
+
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock, runnerLabelValue, BUILD_LABEL, RUNNER_LABEL } from './chunk-E4PIFIC3.js';
|
|
14
14
|
import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
15
15
|
import { spawnRun } from './chunk-774HEQL6.js';
|
|
16
|
-
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-
|
|
17
|
-
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-
|
|
16
|
+
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-DGAIVMMN.js';
|
|
17
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-DTXOJDEH.js';
|
|
18
18
|
import { exceedsDisk } from './chunk-F6GFZXZ3.js';
|
|
19
|
-
import {
|
|
19
|
+
import { sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-OD2VTIHN.js';
|
|
20
|
+
import { parseClaimIdentity } from './chunk-HKMPVPO7.js';
|
|
20
21
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
21
22
|
import { loadHostKey, ensureHostKey, signerFor } from './chunk-M5POMKKW.js';
|
|
22
23
|
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, spoolDir, RUNNER_FILE_MODE, rootfsDir } from './chunk-ZM2IMMYN.js';
|
|
@@ -690,7 +691,7 @@ function selectJobDirs(entries, nowMs, keepDays) {
|
|
|
690
691
|
function liveBuildIds(jobs) {
|
|
691
692
|
const ids = /* @__PURE__ */ new Set();
|
|
692
693
|
for (const job of jobs) {
|
|
693
|
-
for (const id of [job.container?.buildId, job.microvm?.buildId, job.build?.buildId]) if (id !== void 0) ids.add(id);
|
|
694
|
+
for (const id of [job.container?.buildId, job.microvm?.buildId, job.build?.buildId, job.checkContainer?.buildId]) if (id !== void 0) ids.add(id);
|
|
694
695
|
}
|
|
695
696
|
return ids;
|
|
696
697
|
}
|
|
@@ -1267,7 +1268,7 @@ var CLAIM_REFUSAL_CODES = new Set(
|
|
|
1267
1268
|
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous branch_claimed_elsewhere".split(" ")
|
|
1268
1269
|
);
|
|
1269
1270
|
async function tryClaimAndStart(state, item, queue) {
|
|
1270
|
-
const { postJson: postJson2 } = await import('./work-cmd-
|
|
1271
|
+
const { postJson: postJson2 } = await import('./work-cmd-6UMCFTAW.js');
|
|
1271
1272
|
const log = logOf(state);
|
|
1272
1273
|
const hostKey = await loadHostKey(state.config.configPath);
|
|
1273
1274
|
const claim = await retrySend(
|
|
@@ -1395,6 +1396,7 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity)
|
|
|
1395
1396
|
itemKey,
|
|
1396
1397
|
branch,
|
|
1397
1398
|
commitIdentity: identity,
|
|
1399
|
+
...item.specRepository === void 0 || item.specRepository === null || item.specRepository === "" ? {} : { repository: item.specRepository },
|
|
1398
1400
|
startedAt: startedAt.toISOString()
|
|
1399
1401
|
};
|
|
1400
1402
|
writeJobFile(jobFilePath, job);
|
|
@@ -1864,8 +1866,39 @@ async function endJob(state, active, outcome, ending) {
|
|
|
1864
1866
|
state.jobs.delete(active.dirPath);
|
|
1865
1867
|
}
|
|
1866
1868
|
}
|
|
1869
|
+
async function renewLeaseIfDue(state, active, nowMs) {
|
|
1870
|
+
const log = logOf(state);
|
|
1871
|
+
const tag = `#${active.job.item}`;
|
|
1872
|
+
if (!needsRenew(active.lastRenewAtMs, nowMs)) return true;
|
|
1873
|
+
const renew = await retrySend(() => renewLease(state.config, active.job.item, state.deps.fetchImpl), {
|
|
1874
|
+
now: state.deps.now,
|
|
1875
|
+
sleep: state.deps.sleep
|
|
1876
|
+
});
|
|
1877
|
+
const result = renew.ok ? renew.value : "retry_later";
|
|
1878
|
+
if (result === "lease_lost") {
|
|
1879
|
+
if (active.ending) {
|
|
1880
|
+
log.error(`${tag} lease lost while the checks ran`);
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
log.error(`${tag} lease lost \xB7 ending job as lease_lost`);
|
|
1884
|
+
await endJob(state, active, "lease_lost");
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1887
|
+
if (result === "renewed") {
|
|
1888
|
+
active.job.lastRenewAt = new Date(nowMs).toISOString();
|
|
1889
|
+
writeJobFile(join(active.dirPath, "job.json"), active.job);
|
|
1890
|
+
log.line(`${tag} lease renewed \xB7 expires ${formatClock(new Date(nowMs + LEASE_SECONDS * 1e3), new Date(nowMs))}`);
|
|
1891
|
+
} else {
|
|
1892
|
+
log.error(`${tag} renew did not land \xB7 retrying in ${RENEW_INTERVAL_SECONDS / 60}m`);
|
|
1893
|
+
}
|
|
1894
|
+
active.lastRenewAtMs = nowMs;
|
|
1895
|
+
return true;
|
|
1896
|
+
}
|
|
1867
1897
|
async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
1868
|
-
if (active.ending)
|
|
1898
|
+
if (active.ending) {
|
|
1899
|
+
if (active.job.stage === "checks") await renewLeaseIfDue(state, active, nowMs);
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1869
1902
|
const log = logOf(state);
|
|
1870
1903
|
const tag = `#${active.job.item}`;
|
|
1871
1904
|
const pid = active.job.pid;
|
|
@@ -1883,26 +1916,7 @@ async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
|
1883
1916
|
}
|
|
1884
1917
|
return;
|
|
1885
1918
|
}
|
|
1886
|
-
if (
|
|
1887
|
-
const renew = await retrySend(() => renewLease(state.config, active.job.item, state.deps.fetchImpl), {
|
|
1888
|
-
now: state.deps.now,
|
|
1889
|
-
sleep: state.deps.sleep
|
|
1890
|
-
});
|
|
1891
|
-
const result = renew.ok ? renew.value : "retry_later";
|
|
1892
|
-
if (result === "lease_lost") {
|
|
1893
|
-
log.error(`${tag} lease lost \xB7 ending job as lease_lost`);
|
|
1894
|
-
await endJob(state, active, "lease_lost");
|
|
1895
|
-
return;
|
|
1896
|
-
}
|
|
1897
|
-
if (result === "renewed") {
|
|
1898
|
-
active.job.lastRenewAt = new Date(nowMs).toISOString();
|
|
1899
|
-
writeJobFile(join(active.dirPath, "job.json"), active.job);
|
|
1900
|
-
log.line(`${tag} lease renewed \xB7 expires ${formatClock(new Date(nowMs + LEASE_SECONDS * 1e3), new Date(nowMs))}`);
|
|
1901
|
-
} else {
|
|
1902
|
-
log.error(`${tag} renew did not land \xB7 retrying in ${RENEW_INTERVAL_SECONDS / 60}m`);
|
|
1903
|
-
}
|
|
1904
|
-
active.lastRenewAtMs = nowMs;
|
|
1905
|
-
}
|
|
1919
|
+
if (!await renewLeaseIfDue(state, active, nowMs)) return;
|
|
1906
1920
|
const tokens = active.job.container === void 0 && active.job.microvm === void 0 ? void 0 : runtimeOf(state).credentials.get(active.dirPath);
|
|
1907
1921
|
if (tokens !== void 0) {
|
|
1908
1922
|
await tokens.renewReadIfDue();
|
|
@@ -1978,7 +1992,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
1978
1992
|
const outcome = await onStartUnderMarker({
|
|
1979
1993
|
configPath,
|
|
1980
1994
|
own: ownVersionOf(deps),
|
|
1981
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
1995
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-ASZL5BEO.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
1982
1996
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
1983
1997
|
log
|
|
1984
1998
|
});
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { writeJobFile, readJobFile } from './chunk-T6OIJQRT.js';
|
|
4
|
-
import { senderPidfile } from './chunk-
|
|
5
|
-
import { DOCKERD_LOG } from './chunk-
|
|
6
|
-
import { installScrubContext } from './chunk-
|
|
7
|
-
import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, syncInContainer, formatDuration,
|
|
8
|
-
import { CLAUDE_CODE_VERSION } from './chunk-
|
|
4
|
+
import { senderPidfile } from './chunk-2VO25HHO.js';
|
|
5
|
+
import { DOCKERD_LOG } from './chunk-WVGSB3Z2.js';
|
|
6
|
+
import { installScrubContext } from './chunk-6ZZHWY2Z.js';
|
|
7
|
+
import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, syncInContainer, formatDuration, retrySend, formatClock, containerSenderCommand, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, startCheckContainer, lifecycleSteps, lifecycleFailureReason, deleteBuildDisk, senderSignalScript } from './chunk-E4PIFIC3.js';
|
|
8
|
+
import { CLAUDE_CODE_VERSION, readBranchHead, fetchCommit } from './chunk-CEBIA5FD.js';
|
|
9
9
|
import { isSameProcess, startTimeOf } from './chunk-N5FOE5PS.js';
|
|
10
10
|
import { childEnvironment } from './chunk-774HEQL6.js';
|
|
11
|
-
import { waitForAgent, vmExecArgs } from './chunk-
|
|
12
|
-
import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-
|
|
13
|
-
import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-
|
|
14
|
-
import { planArtifactUpload } from './chunk-
|
|
15
|
-
import { scrubText } from './chunk-
|
|
16
|
-
import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm } from './chunk-
|
|
11
|
+
import { waitForAgent, vmExecArgs } from './chunk-ZOAEPWGL.js';
|
|
12
|
+
import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-R7STSBLC.js';
|
|
13
|
+
import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-DGAIVMMN.js';
|
|
14
|
+
import { planArtifactUpload } from './chunk-ZYHKJKSU.js';
|
|
15
|
+
import { scrubText } from './chunk-D6FXM5OW.js';
|
|
16
|
+
import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-DTXOJDEH.js';
|
|
17
17
|
import { parseSize } from './chunk-F6GFZXZ3.js';
|
|
18
|
-
import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment,
|
|
18
|
+
import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, withTunnelRecord, RELAY_PORT } from './chunk-OD2VTIHN.js';
|
|
19
|
+
import { withHooksPath, authorEnvironment, commitIdentityRecord } from './chunk-HKMPVPO7.js';
|
|
20
|
+
import { parsePolicy } from './chunk-7ZR5UPMB.js';
|
|
19
21
|
import { readCloudConfig } from './chunk-EABW6AJQ.js';
|
|
20
22
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
21
23
|
import { signerFor } from './chunk-M5POMKKW.js';
|
|
22
24
|
import { runnerDir, buildDir, vsockPath, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
23
25
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
24
26
|
import { spawn, spawnSync } from 'child_process';
|
|
25
|
-
import { randomBytes } from 'crypto';
|
|
26
|
-
import { mkdirSync, chmodSync, writeFileSync, appendFileSync, statSync, accessSync, constants, openSync, existsSync, readFileSync, closeSync, rmSync, readdirSync } from 'fs';
|
|
27
|
-
import { join, isAbsolute, dirname, delimiter } from 'path';
|
|
27
|
+
import { randomBytes, createHash } from 'crypto';
|
|
28
|
+
import { mkdirSync, chmodSync, writeFileSync, appendFileSync, statSync, accessSync, constants, openSync, existsSync, readFileSync, closeSync, rmSync, readdirSync, lstatSync, realpathSync } from 'fs';
|
|
29
|
+
import { join, isAbsolute, dirname, delimiter, sep } from 'path';
|
|
28
30
|
|
|
29
31
|
createRequire(import.meta.url);
|
|
30
32
|
var DEFAULT_MEMORY = "8g";
|
|
@@ -143,12 +145,20 @@ async function provisionMicroVm(input) {
|
|
|
143
145
|
};
|
|
144
146
|
input.save(state, environment);
|
|
145
147
|
const bail = async (reason, aborted = false) => {
|
|
148
|
+
let why = reason;
|
|
149
|
+
if (!aborted && state.cgroup !== void 0) {
|
|
150
|
+
try {
|
|
151
|
+
if (runtime.vm.cgroup.oomKills(state.cgroup) > 0) why = outOfMemoryReason(config.build?.memory);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
log.error(`${tag} could not read the build's memory events: ${describeCallFailure(err)} \xB7 continuing`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
146
156
|
try {
|
|
147
157
|
await cleanupMicroVm(runtime, state);
|
|
148
158
|
} catch (err) {
|
|
149
159
|
log.error(`${tag} cleanup failed: ${describeCallFailure(err)}`);
|
|
150
160
|
}
|
|
151
|
-
return aborted ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(
|
|
161
|
+
return aborted ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(why);
|
|
152
162
|
};
|
|
153
163
|
if (input.aborted()) return bail("", true);
|
|
154
164
|
let imageConfig;
|
|
@@ -717,6 +727,266 @@ async function provisionProcess(input) {
|
|
|
717
727
|
function cleanupProcess(runtime, state) {
|
|
718
728
|
return closeHostBuild(runtime, state);
|
|
719
729
|
}
|
|
730
|
+
var MAX_VALIDATOR_FILES = 20;
|
|
731
|
+
var VALIDATORS_DIR = ".outerlayer/validators";
|
|
732
|
+
var POLICY_FILE = ".outerlayer/policy.yaml";
|
|
733
|
+
var LIMIT_KEY_TAIL = " (runner.checks.timeLimitMinutes)";
|
|
734
|
+
function lastLine(text2) {
|
|
735
|
+
return text2.split(/\r\n|\r|\n/).map((line) => line.trim()).filter((line) => line !== "").at(-1);
|
|
736
|
+
}
|
|
737
|
+
function readInside(root, rel) {
|
|
738
|
+
const path = join(root, rel);
|
|
739
|
+
try {
|
|
740
|
+
if (!lstatSync(path).isFile()) return void 0;
|
|
741
|
+
const inside = realpathSync(path);
|
|
742
|
+
const base = realpathSync(root);
|
|
743
|
+
return inside.startsWith(base + sep) ? readFileSync(inside, "utf8") : void 0;
|
|
744
|
+
} catch {
|
|
745
|
+
return void 0;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function validatorFilesIn(root) {
|
|
749
|
+
const dir = join(root, VALIDATORS_DIR);
|
|
750
|
+
let names;
|
|
751
|
+
try {
|
|
752
|
+
if (!lstatSync(dir).isDirectory()) return [];
|
|
753
|
+
names = readdirSync(dir);
|
|
754
|
+
} catch {
|
|
755
|
+
return [];
|
|
756
|
+
}
|
|
757
|
+
const files = [];
|
|
758
|
+
for (const name of names.filter((entry) => /\.ya?ml$/.test(entry)).sort().slice(0, MAX_VALIDATOR_FILES)) {
|
|
759
|
+
const path = `${VALIDATORS_DIR}/${name}`;
|
|
760
|
+
const content = readInside(root, path);
|
|
761
|
+
if (content !== void 0) files.push({ path, content });
|
|
762
|
+
}
|
|
763
|
+
return files;
|
|
764
|
+
}
|
|
765
|
+
function checksIn(root, log, tag) {
|
|
766
|
+
const policy = readInside(root, POLICY_FILE);
|
|
767
|
+
const loaded = parsePolicy(policy === void 0 ? null : { path: POLICY_FILE, content: policy }, validatorFilesIn(root));
|
|
768
|
+
for (const problem of loaded.problems) log.error(`${tag} ${problem.file}: ${problem.problem}`);
|
|
769
|
+
const hostChecks = loaded.customs.filter((def) => def.runWhere === "host" && def.level !== "off" && def.declaresEmit !== null && def.command !== void 0);
|
|
770
|
+
return hostChecks.map((def) => ({ name: def.declaresEmit, command: def.command }));
|
|
771
|
+
}
|
|
772
|
+
async function readDefinitions(input, repository, scratch, token) {
|
|
773
|
+
const { config, job, deps } = input;
|
|
774
|
+
const tag = `#${job.item}`;
|
|
775
|
+
const stage = deps.stage ?? stageGovernedContext;
|
|
776
|
+
const controlPlaneUrl = (controlPlane) => deps.runtime.remoteFor?.(controlPlane) ?? `${deps.runtime.github.gitUrl}/${controlPlane}.git`;
|
|
777
|
+
const staged = await stage({
|
|
778
|
+
config,
|
|
779
|
+
repository,
|
|
780
|
+
buildId: `checks-${randomBytes(4).toString("hex")}`,
|
|
781
|
+
buildDir: scratch,
|
|
782
|
+
fetchImpl: deps.fetchImpl,
|
|
783
|
+
controlPlaneUrl
|
|
784
|
+
});
|
|
785
|
+
if (staged.kind === "refused") return { ok: false, reason: staged.reason };
|
|
786
|
+
if (staged.kind === "staged") {
|
|
787
|
+
try {
|
|
788
|
+
return { ok: true, checks: checksIn(join(staged.dir, "tree"), deps.log, tag) };
|
|
789
|
+
} finally {
|
|
790
|
+
rmSync(staged.dir, { recursive: true, force: true });
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
const repo = join(scratch, "repo");
|
|
794
|
+
const remote = deps.runtime.remoteFor?.(repository) ?? `${deps.runtime.github.gitUrl}/${repository}.git`;
|
|
795
|
+
const commit = job.environment?.recipe?.sourceCommit ?? await deps.runtime.readHead(remote, scratch);
|
|
796
|
+
if (commit === void 0) return { ok: false, reason: "the repository's default branch could not be read" };
|
|
797
|
+
const fetched = await (deps.fetchCommit ?? fetchCommit)({ remote, dir: repo, commit, token });
|
|
798
|
+
if (!fetched.ok) return { ok: false, reason: fetched.reason };
|
|
799
|
+
return { ok: true, checks: checksIn(repo, deps.log, tag) };
|
|
800
|
+
}
|
|
801
|
+
function timeoutAfter(ms, sleep) {
|
|
802
|
+
if (sleep !== void 0) return { done: sleep(ms).then(() => "timeout"), cancel: () => void 0 };
|
|
803
|
+
let timer;
|
|
804
|
+
const done = new Promise((resolve) => {
|
|
805
|
+
timer = setTimeout(() => resolve("timeout"), ms);
|
|
806
|
+
timer.unref();
|
|
807
|
+
});
|
|
808
|
+
return { done, cancel: () => clearTimeout(timer) };
|
|
809
|
+
}
|
|
810
|
+
function noCleanEnvironment(job) {
|
|
811
|
+
const ran = job.microvm !== void 0 ? "builtin:vm" : job.build?.workDir !== void 0 ? "builtin:process" : "a provision hook of the host's own";
|
|
812
|
+
return `the host has no clean environment for checks: this build ran under ${ran}, and checks run only in a new container from a container build's image`;
|
|
813
|
+
}
|
|
814
|
+
async function runHostChecks(input) {
|
|
815
|
+
const { config, job, jobDir, deps } = input;
|
|
816
|
+
const { runtime, log } = deps;
|
|
817
|
+
const tag = `#${job.item}`;
|
|
818
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
819
|
+
const repository = job.repository ?? job.container?.repository;
|
|
820
|
+
if (repository === void 0) return;
|
|
821
|
+
const jobFilePath = join(jobDir, "job.json");
|
|
822
|
+
const tokens = runtime.credentials.get(jobDir);
|
|
823
|
+
let readToken;
|
|
824
|
+
try {
|
|
825
|
+
readToken = await tokens?.token("read");
|
|
826
|
+
} catch (err) {
|
|
827
|
+
log.error(`${tag} no read token for the checks: ${describeCallFailure(err)}`);
|
|
828
|
+
}
|
|
829
|
+
const scratch = join(jobDir, "checks", "definitions");
|
|
830
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
831
|
+
mkdirSync(scratch, { recursive: true });
|
|
832
|
+
let definitions;
|
|
833
|
+
try {
|
|
834
|
+
definitions = await readDefinitions(input, repository, scratch, readToken);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
definitions = { ok: false, reason: describeCallFailure(err) };
|
|
837
|
+
} finally {
|
|
838
|
+
removeStagedContext(scratch);
|
|
839
|
+
}
|
|
840
|
+
if (!definitions.ok) {
|
|
841
|
+
log.line(`${tag} checks not run: the definitions could not be read: ${definitions.reason}`);
|
|
842
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const checks = definitions.checks;
|
|
846
|
+
if (checks.length === 0) {
|
|
847
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
log.line(`${tag} checks started (${checks.map((check) => check.name).join(", ")})`);
|
|
851
|
+
const startedMs = now().getTime();
|
|
852
|
+
let signer;
|
|
853
|
+
const record = async (check, result, sentence, keyTail = "") => {
|
|
854
|
+
signer ??= await signerFor(config.configPath);
|
|
855
|
+
const body = sentence === void 0 ? void 0 : cutReasonLine(`${scrubReason(sentence, config) ?? "check failed"}${keyTail}`);
|
|
856
|
+
const clientEmitId = `host-${createHash("sha256").update(`${job.claimId}:${job.startedAt}:${check.name}`).digest("hex").slice(0, 40)}`;
|
|
857
|
+
const sent = await retrySend(
|
|
858
|
+
() => postJson(
|
|
859
|
+
config.url,
|
|
860
|
+
"/v1/emitted-results",
|
|
861
|
+
config.apiKey,
|
|
862
|
+
config.appId,
|
|
863
|
+
{ schemaVersion: 1, emit: { clientEmitId, name: check.name, result, ...body === void 0 ? {} : { body }, emittedAt: now().toISOString(), item: { number: Number(job.item) } } },
|
|
864
|
+
deps.fetchImpl,
|
|
865
|
+
void 0,
|
|
866
|
+
signer
|
|
867
|
+
),
|
|
868
|
+
{ now: deps.now }
|
|
869
|
+
);
|
|
870
|
+
if (sent.ok) log.line(`${tag} check ${check.name} ${result}${body === void 0 ? "" : `: ${body}`}`);
|
|
871
|
+
else log.error(`${tag} check ${check.name} ${result} could not be recorded: ${sent.reason}`);
|
|
872
|
+
};
|
|
873
|
+
const failAll = async (reason, keyTail = "") => {
|
|
874
|
+
log.error(`${tag} checks failed: ${reason}${keyTail}`);
|
|
875
|
+
for (const check of checks) await record(check, "fail", reason, keyTail);
|
|
876
|
+
};
|
|
877
|
+
let container;
|
|
878
|
+
try {
|
|
879
|
+
if (job.container === void 0) return await failAll(noCleanEnvironment(job));
|
|
880
|
+
if (tokens === void 0) return await failAll("the build's repository tokens are no longer held, so the branch cannot be fetched");
|
|
881
|
+
const branch = job.branch;
|
|
882
|
+
if (branch === void 0) return await failAll("the build pushed no branch: the claim names none");
|
|
883
|
+
const remote = runtime.remoteFor?.(repository) ?? `${runtime.github.gitUrl}/${repository}.git`;
|
|
884
|
+
const read = await (deps.readBranch ?? readBranchHead)({ remote, dir: scratch, branch, token: readToken });
|
|
885
|
+
if (read.kind === "absent") return await failAll(`the build pushed no branch: ${branch} does not exist on ${repository}`);
|
|
886
|
+
if (read.kind === "unreadable") return await failAll(`the branch ${branch} could not be read: ${read.reason}`);
|
|
887
|
+
const limitMinutes = config.checks?.timeLimitMinutes ?? DEFAULT_CHECK_TIME_LIMIT_MINUTES;
|
|
888
|
+
const minutes = `${limitMinutes} ${limitMinutes === 1 ? "minute" : "minutes"}`;
|
|
889
|
+
const environmentLog = join(jobDir, "checks", "environment.log");
|
|
890
|
+
const setup = async () => {
|
|
891
|
+
const started = await startCheckContainer({
|
|
892
|
+
config,
|
|
893
|
+
runtime,
|
|
894
|
+
job,
|
|
895
|
+
jobDir,
|
|
896
|
+
tokens,
|
|
897
|
+
log,
|
|
898
|
+
save: (state) => {
|
|
899
|
+
job.checkContainer = state;
|
|
900
|
+
writeJobFile(jobFilePath, job);
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
if (!started.ok) return `the check environment could not be made: ${started.reason}`;
|
|
904
|
+
container = started.container;
|
|
905
|
+
const made = started.container;
|
|
906
|
+
const steps = [
|
|
907
|
+
{
|
|
908
|
+
argv: ["git", "config", "--global", `url.http://127.0.0.1:${RELAY_PORT}/github.com/.insteadOf`, "https://github.com/"],
|
|
909
|
+
workdir: "/build/work",
|
|
910
|
+
failed: (status) => `configuring git failed (exit ${status})`
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
argv: ["git", "clone", "--filter=blob:none", "--single-branch", "--branch", branch, `https://github.com/${repository}.git`, CHECKOUT_DIR],
|
|
914
|
+
workdir: "/build/work",
|
|
915
|
+
failed: (status) => `the clone of ${branch} failed (exit ${status})`
|
|
916
|
+
}
|
|
917
|
+
];
|
|
918
|
+
for (const step of steps) {
|
|
919
|
+
const ran = await made.exec(step.argv, step.workdir, { logPath: environmentLog });
|
|
920
|
+
if (ran.status !== 0) return `the check environment could not be prepared: ${step.failed(ran.status)}`;
|
|
921
|
+
}
|
|
922
|
+
for (const step of lifecycleSteps(job.container?.lifecycle ?? {})) {
|
|
923
|
+
log.line(`${tag} checks lifecycle ${step.name} (${step.source})`);
|
|
924
|
+
const ran = await made.exec(step.argv, CHECKOUT_DIR, { logPath: environmentLog });
|
|
925
|
+
if (ran.status !== 0) return `the check environment could not be prepared: ${lifecycleFailureReason(step, ran.status)}`;
|
|
926
|
+
}
|
|
927
|
+
return made;
|
|
928
|
+
};
|
|
929
|
+
const setupTimer = timeoutAfter(limitMinutes * 6e4, deps.sleep);
|
|
930
|
+
let settled;
|
|
931
|
+
try {
|
|
932
|
+
const outcome = await Promise.race([setup(), setupTimer.done]);
|
|
933
|
+
if (outcome === "timeout") return await failAll(`the check environment setup ran out of time after ${minutes}`, LIMIT_KEY_TAIL);
|
|
934
|
+
settled = outcome;
|
|
935
|
+
} finally {
|
|
936
|
+
setupTimer.cancel();
|
|
937
|
+
}
|
|
938
|
+
if (typeof settled === "string") return await failAll(settled);
|
|
939
|
+
const ready = settled;
|
|
940
|
+
let usable = true;
|
|
941
|
+
for (const check of checks) {
|
|
942
|
+
if (!usable) {
|
|
943
|
+
await record(check, "fail", "the check environment could not be restarted after an earlier check ran out of time");
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
const checkStartedMs = now().getTime();
|
|
947
|
+
const running = ready.exec(["/bin/sh", "-c", check.command], CHECKOUT_DIR, { logPath: join(jobDir, "checks", `${check.name}.log`) });
|
|
948
|
+
running.catch(() => void 0);
|
|
949
|
+
const timer = timeoutAfter(limitMinutes * 6e4, deps.sleep);
|
|
950
|
+
let outcome;
|
|
951
|
+
try {
|
|
952
|
+
outcome = await Promise.race([running, timer.done]);
|
|
953
|
+
} catch (err) {
|
|
954
|
+
timer.cancel();
|
|
955
|
+
await record(check, "fail", `the command could not be run: ${describeCallFailure(err)}`);
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
timer.cancel();
|
|
959
|
+
if (outcome === "timeout") {
|
|
960
|
+
await record(check, "fail", `ran out of time after ${minutes}`, LIMIT_KEY_TAIL);
|
|
961
|
+
const restarting = ready.restart().catch(() => false);
|
|
962
|
+
const restartTimer = timeoutAfter(limitMinutes * 6e4, deps.sleep);
|
|
963
|
+
usable = await Promise.race([restarting, restartTimer.done]) === true;
|
|
964
|
+
restartTimer.cancel();
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
if (outcome.status === 0) {
|
|
968
|
+
log.line(`${tag} check ${check.name} ran (${formatDuration(now().getTime() - checkStartedMs)})`);
|
|
969
|
+
await record(check, "pass");
|
|
970
|
+
continue;
|
|
971
|
+
}
|
|
972
|
+
const last = lastLine(outcome.stderr) ?? lastLine(outcome.stdout);
|
|
973
|
+
const scrubbed = last === void 0 ? void 0 : scrubReason(last, config);
|
|
974
|
+
await record(check, "fail", `exited ${outcome.status}${scrubbed === void 0 ? " with no output" : `: ${cutReasonLine(scrubbed, 140)}`}`);
|
|
975
|
+
}
|
|
976
|
+
} catch (err) {
|
|
977
|
+
log.error(`${tag} checks stopped: ${describeCallFailure(err)}`);
|
|
978
|
+
} finally {
|
|
979
|
+
if (container !== void 0 || job.checkContainer !== void 0) {
|
|
980
|
+
const state = container?.state ?? job.checkContainer;
|
|
981
|
+
await cleanupContainer(runtime, state).catch((err) => log.error(`${tag} removing the check environment failed: ${describeCallFailure(err)}`));
|
|
982
|
+
delete job.checkContainer;
|
|
983
|
+
writeJobFile(jobFilePath, job);
|
|
984
|
+
}
|
|
985
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
986
|
+
if (existsSync(scratch)) log.error(`${tag} the checks' scratch directory could not be removed`);
|
|
987
|
+
log.line(`${tag} checks done (${formatDuration(now().getTime() - startedMs)})`);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
720
990
|
|
|
721
991
|
// src/runner/job.ts
|
|
722
992
|
var LEASE_SECONDS = 900;
|
|
@@ -1181,7 +1451,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
|
|
|
1181
1451
|
await stopProcessGroup(job.pid);
|
|
1182
1452
|
}
|
|
1183
1453
|
if (outcome !== void 0 && job.endStage === void 0) {
|
|
1184
|
-
const TEARDOWN_STAGES = ["sync", "cleanup", "report"];
|
|
1454
|
+
const TEARDOWN_STAGES = ["checks", "sync", "cleanup", "report"];
|
|
1185
1455
|
const staleTeardownStage = job.stage !== void 0 && TEARDOWN_STAGES.includes(job.stage);
|
|
1186
1456
|
job.endStage = ending?.stage ?? (staleTeardownStage ? job.exitCode !== void 0 ? "command" : void 0 : job.stage);
|
|
1187
1457
|
job.endExitCode = ending?.exitCode ?? (outcome === "ok" || outcome === "failed" ? job.exitCode : void 0);
|
|
@@ -1191,11 +1461,35 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
|
|
|
1191
1461
|
job.reason = scrubReason(ending.reason, config);
|
|
1192
1462
|
writeJobFile(jobFilePath, job);
|
|
1193
1463
|
}
|
|
1464
|
+
if (job.checkContainer !== void 0 && job.checksRan === true) {
|
|
1465
|
+
try {
|
|
1466
|
+
await cleanupContainer(deps.container ?? createContainerRuntime(), job.checkContainer);
|
|
1467
|
+
delete job.checkContainer;
|
|
1468
|
+
writeJobFile(jobFilePath, job);
|
|
1469
|
+
} catch (err) {
|
|
1470
|
+
log.error(`${tag} removing an earlier attempt's check environment failed: ${describeCallFailure(err)} \xB7 continuing`);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
if (outcome === "ok" && !job.cleanupRan && job.checksRan !== true) {
|
|
1474
|
+
setStage(job, jobDirPath, "checks");
|
|
1475
|
+
job.checksRan = true;
|
|
1476
|
+
writeJobFile(jobFilePath, job);
|
|
1477
|
+
try {
|
|
1478
|
+
await runHostChecks({
|
|
1479
|
+
config,
|
|
1480
|
+
job,
|
|
1481
|
+
jobDir: jobDirPath,
|
|
1482
|
+
deps: { fetchImpl: deps.fetchImpl, runtime: deps.container ?? createContainerRuntime(), log, now: deps.now, ...deps.hostChecks }
|
|
1483
|
+
});
|
|
1484
|
+
} catch (err) {
|
|
1485
|
+
log.error(`${tag} the host's checks stopped: ${describeCallFailure(err)} \xB7 continuing`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1194
1488
|
let outOfMemory;
|
|
1195
1489
|
if (vmBuild?.state.cgroup !== void 0 && outcome !== void 0 && outcome !== "ok" && ending?.reason === void 0) {
|
|
1196
1490
|
try {
|
|
1197
1491
|
if (vmBuild.runtime.vm.cgroup.oomKills(vmBuild.state.cgroup) > 0) {
|
|
1198
|
-
outOfMemory =
|
|
1492
|
+
outOfMemory = outOfMemoryReason(config.build?.memory);
|
|
1199
1493
|
}
|
|
1200
1494
|
} catch (err) {
|
|
1201
1495
|
log.error(`${tag} could not read the build's memory events: ${describeCallFailure(err)} \xB7 continuing`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { MIN_ENGINE_MAJOR } from './chunk-
|
|
4
|
-
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-
|
|
3
|
+
import { MIN_ENGINE_MAJOR } from './chunk-E4PIFIC3.js';
|
|
4
|
+
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CEBIA5FD.js';
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
6
|
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|
|
7
7
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { startTimeOf, claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
4
4
|
import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-QOZKPLVJ.js';
|
|
5
|
+
import { withGitConfig } from './chunk-HKMPVPO7.js';
|
|
5
6
|
import { RUNNER_DIR_MODE, repoCacheDir, imagesDir, attemptStamp, runnerDir, rootfsPathFor, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
6
7
|
import { mkdirSync, rmSync, existsSync, mkdtempSync, cpSync, readFileSync, writeFileSync, readdirSync, lstatSync, readlinkSync } from 'fs';
|
|
7
8
|
import { tmpdir } from 'os';
|
|
@@ -20,10 +21,10 @@ function tokenHeader(token) {
|
|
|
20
21
|
return `Authorization: Basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`;
|
|
21
22
|
}
|
|
22
23
|
function tokenSettings(remote, token) {
|
|
23
|
-
return
|
|
24
|
+
return (env) => withGitConfig(env, `http.${remote}.extraHeader`, tokenHeader(token));
|
|
24
25
|
}
|
|
25
|
-
function git(cwd, args, timeoutMs,
|
|
26
|
-
const env =
|
|
26
|
+
function git(cwd, args, timeoutMs, extend = (env) => env) {
|
|
27
|
+
const env = extend(gitEnvironment(process.env));
|
|
27
28
|
return new Promise((resolve, reject) => {
|
|
28
29
|
execFile(
|
|
29
30
|
"git",
|
|
@@ -44,7 +45,7 @@ function defaultBranchOf(lsRemote) {
|
|
|
44
45
|
async function fetchDefaultBranch(opts) {
|
|
45
46
|
const created = !existsSync(opts.dir);
|
|
46
47
|
mkdirSync(opts.dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
47
|
-
const credential = opts.token === void 0 ?
|
|
48
|
+
const credential = opts.token === void 0 ? void 0 : tokenSettings(opts.remote, opts.token);
|
|
48
49
|
const over = (args) => git(opts.dir, args, void 0, credential);
|
|
49
50
|
try {
|
|
50
51
|
const defaultBranch = defaultBranchOf(await over(["ls-remote", "--symref", opts.remote, "HEAD"]));
|
|
@@ -84,6 +85,31 @@ async function readDefaultBranchHead(remote, dir) {
|
|
|
84
85
|
}
|
|
85
86
|
return out.match(/^([0-9a-f]{40}|[0-9a-f]{64})\tHEAD$/m)?.[1];
|
|
86
87
|
}
|
|
88
|
+
async function readBranchHead(input) {
|
|
89
|
+
const credential = input.token === void 0 ? void 0 : tokenSettings(input.remote, input.token);
|
|
90
|
+
mkdirSync(input.dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
91
|
+
let out;
|
|
92
|
+
try {
|
|
93
|
+
out = await git(input.dir, ["ls-remote", "--heads", input.remote, `refs/heads/${input.branch}`], HEAD_TIMEOUT_MS, credential);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
return { kind: "unreadable", reason: (err instanceof Error ? err.message : String(err)).replace(/^git [\w-]+ failed: /, "").split("\n")[0] };
|
|
96
|
+
}
|
|
97
|
+
const sha = out.match(/^([0-9a-f]{40}|[0-9a-f]{64})\trefs\/heads\//m)?.[1];
|
|
98
|
+
return sha === void 0 ? { kind: "absent" } : { kind: "found", sha };
|
|
99
|
+
}
|
|
100
|
+
async function fetchCommit(input) {
|
|
101
|
+
const credential = input.token === void 0 ? void 0 : tokenSettings(input.remote, input.token);
|
|
102
|
+
try {
|
|
103
|
+
mkdirSync(input.dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
104
|
+
await git(input.dir, ["init", "--quiet"]);
|
|
105
|
+
await git(input.dir, ["fetch", "--quiet", "--depth", "1", "--no-tags", input.remote, input.commit], CLONE_TIMEOUT_MS, credential);
|
|
106
|
+
await git(input.dir, ["checkout", "--quiet", "--detach", "--force", "FETCH_HEAD"]);
|
|
107
|
+
return { ok: true };
|
|
108
|
+
} catch (err) {
|
|
109
|
+
const detail = (err instanceof Error ? err.message : String(err)).replace(/^git [\w-]+ failed: /, "").split("\n")[0];
|
|
110
|
+
return { ok: false, reason: `the fetch of ${input.commit.slice(0, 8)} from ${input.remote} failed: ${detail}` };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
87
113
|
var CLONE_TIMEOUT_MS = 6e5;
|
|
88
114
|
async function cloneRepository(remote, dest, timeoutMs = CLONE_TIMEOUT_MS) {
|
|
89
115
|
mkdirSync(dirname(dest), { recursive: true, mode: RUNNER_DIR_MODE });
|
|
@@ -467,4 +493,4 @@ async function prune(host, repository, repoRecords, keep, runnerDirPath) {
|
|
|
467
493
|
return removed;
|
|
468
494
|
}
|
|
469
495
|
|
|
470
|
-
export { CLAUDE_CODE_VERSION, DEFAULT_BASE_IMAGE, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_BASE_URL, GUEST_ASSETS_VERSION, GUEST_HELPER_SHA256, GUEST_KERNEL_SHA256, MICROVM_ARCHES, buildRepositoryImage, cloneRepository, firecrackerArch, guestAssetsPinned, readDefaultBranchHead };
|
|
496
|
+
export { CLAUDE_CODE_VERSION, DEFAULT_BASE_IMAGE, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_BASE_URL, GUEST_ASSETS_VERSION, GUEST_HELPER_SHA256, GUEST_KERNEL_SHA256, MICROVM_ARCHES, buildRepositoryImage, cloneRepository, fetchCommit, firecrackerArch, guestAssetsPinned, readBranchHead, readDefaultBranchHead };
|