@outerlayer/cli 0.26.3 → 0.27.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 +25 -0
- package/README.md +12 -9
- package/dist/{agent-setup-PZYQWN4H.js → agent-setup-UW36TAQM.js} +13 -13
- package/dist/{bridge-5KZ36YDG.js → bridge-B5VJVECY.js} +2 -2
- package/dist/build-TNM7HYCA.js +12 -0
- package/dist/build-info.json +1 -1
- package/dist/{builder-WEGLC2F2.js → builder-LDJGS2JC.js} +6 -6
- package/dist/{check-WJJ325EQ.js → check-JVBAWIN6.js} +44 -43
- package/dist/{chunk-7LVF4E5V.js → chunk-24ID7EQ2.js} +7 -4
- package/dist/{chunk-HXFRJKMU.js → chunk-2F762IXY.js} +2 -2
- package/dist/{chunk-2K3TCQHW.js → chunk-2I3LIRZP.js} +26 -8
- package/dist/{chunk-UKCNOAO6.js → chunk-55GNQPO6.js} +17 -6
- package/dist/{chunk-XSPA5ODY.js → chunk-6BLXUD56.js} +4 -3
- package/dist/{chunk-MWPBF2XG.js → chunk-6KKM7VGZ.js} +32 -4
- package/dist/{chunk-VPEGE3QZ.js → chunk-6TRNCUM4.js} +1 -1
- package/dist/{chunk-MLD2NA7N.js → chunk-7AQ5AM7U.js} +12 -5
- package/dist/{chunk-HBISTTG3.js → chunk-7OUOLGUV.js} +20 -5
- package/dist/{chunk-6FAP657M.js → chunk-ABXQBEYK.js} +1 -1
- package/dist/{chunk-TSW4DGV2.js → chunk-B6K7R5UY.js} +2 -2
- package/dist/chunk-BM7EC3OZ.js +181 -0
- package/dist/{chunk-W3NVHOCS.js → chunk-BPKO76QR.js} +4 -4
- package/dist/{chunk-QRZLUUNN.js → chunk-BWH36FOC.js} +8 -3
- package/dist/{chunk-PYSKSROG.js → chunk-D7ECMB7B.js} +4 -4
- package/dist/{chunk-FO7F6QSV.js → chunk-DJHNEGNM.js} +27 -3
- package/dist/{chunk-TPAF24PK.js → chunk-E5IJ5533.js} +2 -2
- package/dist/{chunk-JWRX5ZTT.js → chunk-EPPIISRD.js} +2 -2
- package/dist/{chunk-6M4LNO22.js → chunk-FP23SVDD.js} +6 -6
- package/dist/{chunk-GOSFARMS.js → chunk-G2JWZDFA.js} +9 -2
- package/dist/{chunk-XFGL53GU.js → chunk-G3EZA6MK.js} +56 -8
- package/dist/{chunk-5PMQDQFV.js → chunk-GFUE5TKO.js} +3 -3
- package/dist/{chunk-XLC7KEUV.js → chunk-GLUKDQS4.js} +1 -1
- package/dist/{chunk-ZLEXMZFW.js → chunk-JH2GQU5T.js} +5 -5
- package/dist/{chunk-YVZJ6GKF.js → chunk-KT4CN6OU.js} +1 -1
- package/dist/{chunk-JKNYTNYD.js → chunk-LOKSLO25.js} +1 -1
- package/dist/{chunk-665QWBNW.js → chunk-M3MHHIUW.js} +1 -1
- package/dist/{chunk-4IFKLYMM.js → chunk-MATUHHN4.js} +1 -1
- package/dist/{chunk-MQ743JX3.js → chunk-MHX7YX7Y.js} +1 -1
- package/dist/{chunk-TEVO3RUV.js → chunk-N4D5TMVU.js} +4 -4
- package/dist/{chunk-EORWWFPA.js → chunk-O2IJTY7L.js} +2 -2
- package/dist/{chunk-EABW6AJQ.js → chunk-PJDQPF5N.js} +18 -5
- package/dist/{chunk-KDDFI5MR.js → chunk-QHH4OSD4.js} +1 -1
- package/dist/{chunk-W7LGHNXT.js → chunk-QIVOTQOQ.js} +5 -5
- package/dist/{chunk-JF572PM5.js → chunk-QKIQ2R7F.js} +3 -3
- package/dist/{chunk-L4CW6LZQ.js → chunk-RHAGBUL5.js} +5 -2
- package/dist/{chunk-TKL74NLB.js → chunk-RHGF73IU.js} +1 -1
- package/dist/{chunk-SKZG7SAN.js → chunk-RK7FWC6B.js} +206 -42
- package/dist/{chunk-6MZSX4M7.js → chunk-STSLH5EJ.js} +3 -1
- package/dist/{chunk-K7FCZCLQ.js → chunk-TXHJ7BGR.js} +13 -13
- package/dist/{chunk-364XDGOK.js → chunk-UQYBCJ2L.js} +3 -3
- package/dist/{chunk-2AKDF6C2.js → chunk-VS27BP3E.js} +5 -5
- package/dist/{chunk-J7BXZLSO.js → chunk-WSYXLLA5.js} +29 -8
- package/dist/{chunk-WX2WEERU.js → chunk-WUL2OP5A.js} +3 -3
- package/dist/{chunk-ZPXI7LMG.js → chunk-WVDP6HVZ.js} +6 -6
- package/dist/{chunk-MXTN35XN.js → chunk-XBPUTQ7E.js} +1 -1
- package/dist/{chunk-UNF7MWEL.js → chunk-XS3FDWSZ.js} +1 -1
- package/dist/{chunk-VJBFQP3H.js → chunk-XZ6Q6ZNR.js} +9 -5
- package/dist/{chunk-F6DIHHBS.js → chunk-Y4OKEFAX.js} +1 -1
- package/dist/{chunk-XDHYZWEK.js → chunk-Y7ZCHBYB.js} +2 -2
- package/dist/chunk-YB3CSYXX.js +95 -0
- package/dist/{chunk-VHVFU6QU.js → chunk-YF56R4DV.js} +86 -31
- package/dist/chunk-YJLHUKYS.js +38 -0
- package/dist/{chunk-XF77SNB4.js → chunk-ZXRWMOJ3.js} +287 -51
- package/dist/{claude-launcher-O2U6P6ZD.js → claude-launcher-TKX4WCUN.js} +8 -4
- package/dist/{cli-2UUJM3AE.js → cli-XVXQDKZT.js} +141 -135
- package/dist/{command-GQBHC53U.js → command-B2T7VR77.js} +33 -32
- package/dist/{config-JJ3EO7SB.js → config-TWS5VZEN.js} +3 -3
- package/dist/{connect-cmd-2JHSLBXK.js → connect-cmd-HGS7YPA2.js} +10 -10
- package/dist/{container-start-AUJHF2BC.js → container-start-JE7HTKZG.js} +32 -31
- package/dist/{control-plane-launch-654RV5PO.js → control-plane-launch-DBQA3KLJ.js} +9 -9
- package/dist/{docker-NYAIIX2F.js → docker-MJEEHUUA.js} +6 -6
- package/dist/{doctor-NV2PUERZ.js → doctor-6ZIF2BRZ.js} +184 -37
- package/dist/{emit-artifact-cmd-XXTCHP6V.js → emit-artifact-cmd-ALDK55Y2.js} +14 -14
- package/dist/{emit-cmd-WQH2NK7H.js → emit-cmd-VAQHRWJR.js} +4 -4
- package/dist/{emit-criteria-cmd-VMZIRJCQ.js → emit-criteria-cmd-Q7SM6VP2.js} +11 -11
- package/dist/{emit-finding-cmd-KMJNYQI7.js → emit-finding-cmd-2NBAPDSV.js} +11 -11
- package/dist/{emit-result-cmd-HRTXGZLK.js → emit-result-cmd-KUSL56RI.js} +14 -14
- package/dist/{emit-step-cmd-AUHA3EXY.js → emit-step-cmd-KD4AKEAT.js} +12 -12
- package/dist/{exec-client-J6L5FDRR.js → exec-client-6WVS7DRZ.js} +3 -3
- package/dist/{governing-source-PTJ6EAA3.js → governing-source-VVUA5TKB.js} +16 -16
- package/dist/{guest-init-CXIHA5VI.js → guest-init-H5K2RW3P.js} +4 -4
- package/dist/{hook-fast-SDFXJEAW.js → hook-fast-3SUJM765.js} +1 -1
- package/dist/{host-key-5TKBNUZ4.js → host-key-XNKZCWTS.js} +3 -3
- package/dist/{image-tag-5SJ6ZKT7.js → image-tag-R34J4O3F.js} +3 -3
- package/dist/index.js +4 -4
- package/dist/init-ETKGFCXR.js +55 -0
- package/dist/{init-UZWRJMPZ.js → init-Q2RPUUVP.js} +33 -32
- package/dist/{init-cmd-SQKWPACS.js → init-cmd-M6MQRGOU.js} +19 -18
- package/dist/{init-update-FJDKY4SJ.js → init-update-N4HTZGVS.js} +59 -30
- package/dist/{inspect-6UYAAXH7.js → inspect-IPFA7AAT.js} +1 -1
- package/dist/{install-QSTTBUHX.js → install-6OIY3KHZ.js} +6 -5
- package/dist/{install-cmd-3DXJJUAA.js → install-cmd-JMT67P35.js} +5 -5
- package/dist/{layout-UOJQGEPW.js → layout-XNFDTOET.js} +2 -2
- package/dist/{login-browser-4OMZFP3U.js → login-browser-EWXSGHM7.js} +3 -3
- package/dist/{logout-cmd-5V5MMBSY.js → logout-cmd-5WE2N5B5.js} +2 -2
- package/dist/{logs-VN2HKDSH.js → logs-XHAS6LMZ.js} +2 -2
- package/dist/loop-2Y4CUFNP.js +79 -0
- package/dist/machine-Z2S47JW7.js +50 -0
- package/dist/machine-skills-RRF4HLAD.js +11 -0
- package/dist/{mcp-install-cmd-GGWB3JJ2.js → mcp-install-cmd-LD7KYAOP.js} +2 -2
- package/dist/{mcp-serve-cmd-U5N5DK3H.js → mcp-serve-cmd-LY5A3CE7.js} +5 -5
- package/dist/{paths-ZC6BMWMT.js → paths-LHSPNORF.js} +2 -2
- package/dist/{pending-54HC7MM3.js → pending-3YZCSKON.js} +3 -3
- package/dist/{pidfile-BY5Z6YH7.js → pidfile-DKMYYXLH.js} +3 -3
- package/dist/{record-K23IN6QN.js → record-3LPTY3G5.js} +3 -3
- package/dist/{runner-env-2D7MPOIJ.js → runner-env-YRRNRKF4.js} +8 -7
- package/dist/{runner-identity-YYENYKDH.js → runner-identity-EX7HXPUE.js} +6 -6
- package/dist/{runner-key-AZVXBQIB.js → runner-key-GO277GW2.js} +32 -31
- package/dist/{session-sender-VH2EKAT5.js → session-sender-SC5PSU2G.js} +15 -15
- package/dist/{spec-cmd-BOUPLX7X.js → spec-cmd-JGYHHJ4P.js} +12 -12
- package/dist/{starter-pack-55EFILC5.js → starter-pack-GPU4X6B7.js} +2 -2
- package/dist/{status-3WC2IGVI.js → status-CJCE2FHD.js} +34 -33
- package/dist/{sync-cmd-GT2WTQRA.js → sync-cmd-ATXJVS7S.js} +14 -14
- package/dist/{watch-JED7SYAA.js → watch-M7NR3DOW.js} +14 -14
- package/dist/{work-claim-cmd-MY4N74HA.js → work-claim-cmd-DNUDZKJA.js} +16 -16
- package/dist/{work-cmd-UQ45HDM4.js → work-cmd-VECTYST6.js} +12 -12
- package/dist/{work-comment-cmd-I7NNSNDP.js → work-comment-cmd-F3NRWKPZ.js} +12 -12
- package/dist/{work-logs-cmd-YIQJVENH.js → work-logs-cmd-QF6P32FE.js} +12 -12
- package/dist/{work-open-pr-cmd-VP5NNTCW.js → work-open-pr-cmd-XE23JA3R.js} +13 -13
- package/dist/{work-pr-cmd-DKTBEFHO.js → work-pr-cmd-BH56GUKN.js} +12 -12
- package/dist/{work-stop-cmd-GN2WX73C.js → work-stop-cmd-C3F5HNUO.js} +12 -12
- package/package.json +1 -1
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +6 -5
- package/skill-pack/shipped.json +1 -0
- package/skill-pack/template/build/SKILL.md +1 -1
- package/dist/build-EBQYXL7Y.js +0 -12
- package/dist/chunk-7RQ73DLO.js +0 -23
- package/dist/init-KIGYMLDM.js +0 -54
- package/dist/loop-OE32U2IZ.js +0 -78
- package/dist/machine-L7INJ4JN.js +0 -49
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand,
|
|
4
|
-
import { writePendingUpdate } from './chunk-
|
|
3
|
+
import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-RK7FWC6B.js';
|
|
4
|
+
import { writePendingUpdate } from './chunk-RHGF73IU.js';
|
|
5
5
|
import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
|
|
6
|
-
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-
|
|
6
|
+
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-ABXQBEYK.js';
|
|
7
7
|
import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
|
|
8
8
|
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
|
|
9
9
|
import { RUNNER_PROTOCOL } from './chunk-TPKYTORP.js';
|
|
10
|
-
import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-
|
|
11
|
-
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-
|
|
10
|
+
import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-WVDP6HVZ.js';
|
|
11
|
+
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-MATUHHN4.js';
|
|
12
12
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
13
13
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
14
|
-
import { leaseTimeLeftMs, LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec,
|
|
15
|
-
import {
|
|
14
|
+
import { leaseTimeLeftMs, LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec, setUpRunnerCgroup, createContainerRuntime, measureDisk, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied, gitRemoteFor, startServicesFor, createLeaseChannel } from './chunk-YF56R4DV.js';
|
|
15
|
+
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-WSYXLLA5.js';
|
|
16
|
+
import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-M3MHHIUW.js';
|
|
16
17
|
import { isVersion, compareVersions, satisfiesRange } from './chunk-TQMI335S.js';
|
|
17
|
-
import { checkFit } from './chunk-
|
|
18
|
-
import {
|
|
18
|
+
import { checkFit } from './chunk-7AQ5AM7U.js';
|
|
19
|
+
import { fdName } from './chunk-YB3CSYXX.js';
|
|
20
|
+
import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-D7ECMB7B.js';
|
|
19
21
|
import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
|
|
20
|
-
import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { exceedsDisk } from './chunk-7RQ73DLO.js';
|
|
22
|
+
import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-JH2GQU5T.js';
|
|
23
|
+
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-55GNQPO6.js';
|
|
24
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-EPPIISRD.js';
|
|
25
|
+
import { exceedsDisk } from './chunk-YJLHUKYS.js';
|
|
25
26
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
26
|
-
import { loadHostKey, ensureHostKey, signerFor } from './chunk-
|
|
27
|
-
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, rootfsDir } from './chunk-
|
|
28
|
-
import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-
|
|
27
|
+
import { loadHostKey, ensureHostKey, signerFor } from './chunk-Y4OKEFAX.js';
|
|
28
|
+
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, rootfsDir } from './chunk-RHAGBUL5.js';
|
|
29
|
+
import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-2I3LIRZP.js';
|
|
29
30
|
import { COMMAND_LOST_REASON, CONTAINER_STOPPED_REASON } from './chunk-JGD5TWQ2.js';
|
|
30
31
|
import { randomBytes } from 'crypto';
|
|
31
|
-
import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync, statSync, readdirSync, readFileSync,
|
|
32
|
+
import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync, statSync, readdirSync, readFileSync, closeSync, rmSync, openSync, constants, lstatSync } from 'fs';
|
|
32
33
|
import { join, dirname } from 'path';
|
|
33
34
|
import { totalmem, constants as constants$1 } from 'os';
|
|
34
35
|
|
|
@@ -272,8 +273,11 @@ function stageReason(job) {
|
|
|
272
273
|
}
|
|
273
274
|
}
|
|
274
275
|
function ownReason({ job, ending }) {
|
|
275
|
-
if (job.microvm !== void 0)
|
|
276
|
-
|
|
276
|
+
if (job.microvm !== void 0) {
|
|
277
|
+
if (!isMicroVmTracked(job)) return "is a microVM build that a restarted runner cannot adopt";
|
|
278
|
+
} else if (!isContainerTracked(job)) {
|
|
279
|
+
return "is not a container build tracked inside its container";
|
|
280
|
+
}
|
|
277
281
|
if (ending) return "is being ended";
|
|
278
282
|
return stageReason(job);
|
|
279
283
|
}
|
|
@@ -986,6 +990,30 @@ function writeCommitHooks(buildDir2, coAuthor) {
|
|
|
986
990
|
chmodSync(data, 420);
|
|
987
991
|
return dir;
|
|
988
992
|
}
|
|
993
|
+
|
|
994
|
+
// src/runner/microvm/adopt.ts
|
|
995
|
+
var MICROVM_STOPPED_REASON = "the build's microVM stopped while no runner was managing it";
|
|
996
|
+
var MICROVM_SOCKETS_LOST_REASON = "the build's sockets did not survive the runner's restart";
|
|
997
|
+
var MICROVM_HELPER_UNREACHABLE_REASON = "the runner could not ask its helper about the build's microVM when it started";
|
|
998
|
+
async function judgeMicroVmAdoption(input) {
|
|
999
|
+
const { job, runtime } = input;
|
|
1000
|
+
const state = job.microvm;
|
|
1001
|
+
if (state === void 0 || !isMicroVmTracked(job)) return "unservable";
|
|
1002
|
+
const probe = await runtime.vm.helper.probe();
|
|
1003
|
+
if (probe.ok) {
|
|
1004
|
+
const unit = await probe.client.state(state.buildId).catch((err) => {
|
|
1005
|
+
input.onError?.(`the state of the unit of build ${state.buildId} could not be read: ${describeCallFailure(err)}`);
|
|
1006
|
+
return { active: true, oomKills: 0 };
|
|
1007
|
+
});
|
|
1008
|
+
if (!unit.active) return "stopped";
|
|
1009
|
+
} else {
|
|
1010
|
+
input.onError?.(`the unit of build ${state.buildId} could not be asked about, because there is no helper to ask: ${probe.detail}`);
|
|
1011
|
+
return probe.unreachable === true ? "unasked" : "unservable";
|
|
1012
|
+
}
|
|
1013
|
+
const inherited = runtime.vm.fdStore.inherited();
|
|
1014
|
+
const names = state.fdStore ?? [];
|
|
1015
|
+
return names.length > 0 && names.every((name) => inherited.has(name)) ? "adopt" : "unservable";
|
|
1016
|
+
}
|
|
989
1017
|
function linuxSignalName(number) {
|
|
990
1018
|
const names = {
|
|
991
1019
|
1: "SIGHUP",
|
|
@@ -1749,7 +1777,7 @@ var CLAIM_REFUSAL_CODES = new Set(
|
|
|
1749
1777
|
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected repository_not_reachable branch_claimed_elsewhere".split(" ")
|
|
1750
1778
|
);
|
|
1751
1779
|
async function tryClaimAndStart(state, item, queue) {
|
|
1752
|
-
const { postJson: postJson2 } = await import('./work-cmd-
|
|
1780
|
+
const { postJson: postJson2 } = await import('./work-cmd-VECTYST6.js');
|
|
1753
1781
|
const log = logOf(state);
|
|
1754
1782
|
const hostKey = await loadHostKey(state.config.configPath);
|
|
1755
1783
|
const claim = await retrySend(
|
|
@@ -1933,11 +1961,16 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
1933
1961
|
writeJobFile(jobFilePath, active.job);
|
|
1934
1962
|
tokens = buildTokensFor(state, active, item.number);
|
|
1935
1963
|
runtimeOf(state).credentials.set(dirPath, tokens);
|
|
1964
|
+
let asking;
|
|
1936
1965
|
try {
|
|
1937
1966
|
await tokens.token("read");
|
|
1967
|
+
for (const entry of repositories) {
|
|
1968
|
+
asking = entry.repository;
|
|
1969
|
+
await tokens.token("read", entry.repository);
|
|
1970
|
+
}
|
|
1938
1971
|
} catch (err) {
|
|
1939
1972
|
if (active.ending) return;
|
|
1940
|
-
await endOnTokenRefusal(state, active, err);
|
|
1973
|
+
await endOnTokenRefusal(state, active, err, asking);
|
|
1941
1974
|
return;
|
|
1942
1975
|
}
|
|
1943
1976
|
if (active.ending) return;
|
|
@@ -2242,8 +2275,16 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
2242
2275
|
try {
|
|
2243
2276
|
if (job.microvm !== void 0) {
|
|
2244
2277
|
const runtime = runtimeOf(state);
|
|
2245
|
-
|
|
2246
|
-
|
|
2278
|
+
if (job.microvm.jailed !== void 0 && (job.microvm.fdStore?.length ?? 0) > 0) {
|
|
2279
|
+
job.microvm.tracking = "microvm";
|
|
2280
|
+
job.microvm.commandDir = MICROVM_COMMAND_DIR;
|
|
2281
|
+
job.microvm.commandLogBase = commandLogOffset(dirPath, 0);
|
|
2282
|
+
writeJobFile(jobFilePath, job);
|
|
2283
|
+
await startMicroVmCommand({ job, cmdline, runtime, config: state.config });
|
|
2284
|
+
} else {
|
|
2285
|
+
const composed = microVmCommandLine({ job, cmdline, runtime, config: state.config, cli: join(runtime.cliBuild().distDir, "index.js") });
|
|
2286
|
+
running = runCommand(composed.line, { ...composed.env, OUTERLAYER_JOB_DIR: dirPath }, dirPath, join(dirPath, "command.log"), state.deps.spawnFn);
|
|
2287
|
+
}
|
|
2247
2288
|
} else if (job.container !== void 0) {
|
|
2248
2289
|
const runtime = runtimeOf(state);
|
|
2249
2290
|
const exec = containerCommandExec({ job, cmdline, runtime, config: state.config });
|
|
@@ -2271,7 +2312,9 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
2271
2312
|
writeJobFile(jobFilePath, job);
|
|
2272
2313
|
const commandStartedMs = nowOf(state).getTime();
|
|
2273
2314
|
active.commandStartedMs = commandStartedMs;
|
|
2274
|
-
log.line(
|
|
2315
|
+
log.line(
|
|
2316
|
+
running !== void 0 ? `${tag} command started \xB7 pid ${running.pid}` : job.container !== void 0 ? `${tag} command started \xB7 in container ${job.container.container}` : `${tag} command started \xB7 in microVM build ${job.microvm.buildId}`
|
|
2317
|
+
);
|
|
2275
2318
|
const sender = await startSender({
|
|
2276
2319
|
config: state.config,
|
|
2277
2320
|
job,
|
|
@@ -2323,19 +2366,21 @@ function buildTokensFor(state, active, item) {
|
|
|
2323
2366
|
}
|
|
2324
2367
|
});
|
|
2325
2368
|
}
|
|
2326
|
-
async function endOnTokenRefusal(state, active, err) {
|
|
2369
|
+
async function endOnTokenRefusal(state, active, err, repository) {
|
|
2327
2370
|
const log = logOf(state);
|
|
2328
2371
|
const tag = `#${active.job.item}`;
|
|
2329
2372
|
const refusal = classifyRefusal(err);
|
|
2373
|
+
const which = repository === void 0 ? "the build's read token" : `the build's read token for ${repository}`;
|
|
2330
2374
|
if (refusal.kind === "retry") {
|
|
2331
|
-
log.error(`${tag}
|
|
2375
|
+
log.error(`${tag} ${which} could not be had (${describeCallFailure(err)}) \xB7 releasing the claim to try again`);
|
|
2332
2376
|
await endJob(state, active, void 0);
|
|
2333
2377
|
} else if (refusal.kind === "lease_lost") {
|
|
2334
|
-
log.error(`${tag}
|
|
2378
|
+
log.error(`${tag} ${which} was refused: ${refusalCode(err)} \xB7 ending job as lease_lost`);
|
|
2335
2379
|
await endJob(state, active, "lease_lost");
|
|
2336
2380
|
} else {
|
|
2337
|
-
|
|
2338
|
-
|
|
2381
|
+
const reason = repository === void 0 ? refusal.reason : `${which} could not be had: ${refusal.reason}`;
|
|
2382
|
+
log.error(`${tag} ${which} was refused: ${refusal.reason} \xB7 ending job as failed`);
|
|
2383
|
+
await endJob(state, active, "failed", { stage: "provision", reason });
|
|
2339
2384
|
}
|
|
2340
2385
|
}
|
|
2341
2386
|
async function endOnProvisionFailure(state, active, tokens, took, reason) {
|
|
@@ -2457,19 +2502,67 @@ async function endStoppedBuild(state, active, where) {
|
|
|
2457
2502
|
);
|
|
2458
2503
|
void endJob(state, active, "interrupted", { stage: "command", reason: COMMAND_LOST_REASON });
|
|
2459
2504
|
}
|
|
2505
|
+
var DISK_FAILURES_LIMIT = 2;
|
|
2506
|
+
async function checkDisk(state, active, container, tag) {
|
|
2507
|
+
const log = logOf(state);
|
|
2508
|
+
const limit = state.config.build?.disk ?? "40g";
|
|
2509
|
+
const runtime = runtimeOf(state);
|
|
2510
|
+
const reading = await measureDisk(runtime, container);
|
|
2511
|
+
if (active.ending) return false;
|
|
2512
|
+
if (exceedsDisk(reading.kib ?? 0, limit)) {
|
|
2513
|
+
log.line(`${tag} the build's volume holds ${reading.kib} KiB, past ${limit} \xB7 ending job as failed`);
|
|
2514
|
+
await endJob(state, active, "failed", { stage: "command", reason: "disk_limit_exceeded" });
|
|
2515
|
+
return true;
|
|
2516
|
+
}
|
|
2517
|
+
if (reading.failure === void 0) {
|
|
2518
|
+
active.diskFailures = 0;
|
|
2519
|
+
return false;
|
|
2520
|
+
}
|
|
2521
|
+
if (await runtime.host.state(container.container) !== "running" || active.ending) return false;
|
|
2522
|
+
active.diskFailures = (active.diskFailures ?? 0) + 1;
|
|
2523
|
+
if (active.diskFailures < DISK_FAILURES_LIMIT) {
|
|
2524
|
+
log.error(`${tag} disk check failed (${active.diskFailures} of ${DISK_FAILURES_LIMIT}): ${reading.failure} \xB7 checking again`);
|
|
2525
|
+
return false;
|
|
2526
|
+
}
|
|
2527
|
+
log.error(`${tag} disk check failed (${active.diskFailures} of ${DISK_FAILURES_LIMIT}): ${reading.failure} \xB7 ending job as failed`);
|
|
2528
|
+
await endJob(state, active, "failed", { stage: "command", reason: "disk_check_failed" });
|
|
2529
|
+
return true;
|
|
2530
|
+
}
|
|
2531
|
+
async function endOrWaitForMicroVm(state, active) {
|
|
2532
|
+
const log = logOf(state);
|
|
2533
|
+
const tag = `#${active.job.item}`;
|
|
2534
|
+
const microvm = active.job.microvm;
|
|
2535
|
+
const runtime = runtimeOf(state);
|
|
2536
|
+
const helper = await runtime.vm.helper.probe();
|
|
2537
|
+
const unit = helper.ok ? await helper.client.state(microvm.buildId).catch(() => void 0) : void 0;
|
|
2538
|
+
if (active.ending) return;
|
|
2539
|
+
if (unit?.active === false) {
|
|
2540
|
+
const killed = await microVmOomKills(runtime, microvm).catch(() => 0);
|
|
2541
|
+
log.line(`${tag} the build's microVM stopped \xB7 ending job as interrupted`);
|
|
2542
|
+
void endJob(state, active, "interrupted", killed > 0 ? { stage: "command" } : { stage: "command", reason: MICROVM_STOPPED_REASON });
|
|
2543
|
+
} else if (active.probeFailing !== true) {
|
|
2544
|
+
active.probeFailing = true;
|
|
2545
|
+
log.error(`${tag} the build's command could not be read from its microVM \xB7 trying again`);
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2460
2548
|
async function probeBuild(state, active) {
|
|
2461
2549
|
const container = active.job.container;
|
|
2462
|
-
|
|
2550
|
+
const tracked = container !== void 0 && isContainerTracked(active.job) ? container : isMicroVmTracked(active.job) ? active.job.microvm : void 0;
|
|
2551
|
+
if (tracked === void 0 || active.ending || active.probing) return;
|
|
2463
2552
|
active.probing = true;
|
|
2464
2553
|
const log = logOf(state);
|
|
2465
2554
|
const tag = `#${active.job.item}`;
|
|
2466
2555
|
try {
|
|
2467
2556
|
const runtime = runtimeOf(state);
|
|
2468
2557
|
for (; ; ) {
|
|
2469
|
-
const offset = commandLogOffset(active.dirPath,
|
|
2470
|
-
const probe = await probeCommand(runtime, container, offset);
|
|
2558
|
+
const offset = commandLogOffset(active.dirPath, tracked.commandLogBase);
|
|
2559
|
+
const probe = container === void 0 ? await probeMicroVmCommand(runtime, active.job.microvm, offset) : await probeCommand(runtime, container, offset);
|
|
2471
2560
|
if (active.ending) return;
|
|
2472
2561
|
if (probe === void 0) {
|
|
2562
|
+
if (container === void 0) {
|
|
2563
|
+
await endOrWaitForMicroVm(state, active);
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2473
2566
|
const where = await runtime.host.state(container.container);
|
|
2474
2567
|
if (where === "stopped" || where === "missing") {
|
|
2475
2568
|
await endStoppedBuild(state, active, where);
|
|
@@ -2520,7 +2613,7 @@ async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
|
2520
2613
|
const log = logOf(state);
|
|
2521
2614
|
const tag = `#${active.job.item}`;
|
|
2522
2615
|
const pid = active.job.pid;
|
|
2523
|
-
const started = pid !== void 0 ||
|
|
2616
|
+
const started = pid !== void 0 || isTracked(active.job);
|
|
2524
2617
|
if (pid !== void 0 && !isGroupAlive(pid)) {
|
|
2525
2618
|
if (active.cmd === null) {
|
|
2526
2619
|
const recorded = outcomeFromExitCode(active.dirPath);
|
|
@@ -2563,13 +2656,12 @@ async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
|
2563
2656
|
return;
|
|
2564
2657
|
}
|
|
2565
2658
|
if (!started) return;
|
|
2566
|
-
if (active.job.container !== void 0) {
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
return;
|
|
2659
|
+
if (active.job.container !== void 0 && active.diskChecking !== true) {
|
|
2660
|
+
active.diskChecking = true;
|
|
2661
|
+
try {
|
|
2662
|
+
if (await checkDisk(state, active, active.job.container, tag)) return;
|
|
2663
|
+
} finally {
|
|
2664
|
+
active.diskChecking = false;
|
|
2573
2665
|
}
|
|
2574
2666
|
}
|
|
2575
2667
|
let cpuUsecPerMinute = null;
|
|
@@ -2641,7 +2733,7 @@ async function adoptTrackedBuilds(state, jobsDirPath) {
|
|
|
2641
2733
|
const attemptLogs = attemptLogsOf(state);
|
|
2642
2734
|
const runtime = runtimeOf(state);
|
|
2643
2735
|
for (const { dirPath, job, known } of listTrackedJobs(jobsDirPath)) {
|
|
2644
|
-
if (!known) continue;
|
|
2736
|
+
if (!known || job.container === void 0) continue;
|
|
2645
2737
|
const container = job.container;
|
|
2646
2738
|
const where = await runtime.host.state(container.container).catch(() => "unknown");
|
|
2647
2739
|
if (where === "stopped" || where === "missing") {
|
|
@@ -2662,6 +2754,116 @@ async function adoptTrackedBuilds(state, jobsDirPath) {
|
|
|
2662
2754
|
void probeBuild(state, adopted);
|
|
2663
2755
|
}
|
|
2664
2756
|
}
|
|
2757
|
+
async function planMicroVmAdoption(state, jobsDirPath) {
|
|
2758
|
+
const plan = { adopt: [], away: [], unservable: [], unasked: [] };
|
|
2759
|
+
for (const { dirPath, job, known } of listTrackedJobs(jobsDirPath)) {
|
|
2760
|
+
if (!known || !isMicroVmTracked(job)) continue;
|
|
2761
|
+
const verdict = await judgeMicroVmAdoption({ job, runtime: runtimeOf(state), onError: (line) => logOf(state).error(line) });
|
|
2762
|
+
plan[verdict === "adopt" ? "adopt" : verdict === "stopped" ? "away" : verdict === "unasked" ? "unasked" : "unservable"].push({ dirPath, job });
|
|
2763
|
+
}
|
|
2764
|
+
return plan;
|
|
2765
|
+
}
|
|
2766
|
+
async function rejoinMicroVmBuild(state, adopted) {
|
|
2767
|
+
const { job, dirPath } = adopted;
|
|
2768
|
+
const config = state.config;
|
|
2769
|
+
const microvm = job.microvm;
|
|
2770
|
+
const runtime = runtimeOf(state);
|
|
2771
|
+
const tag = `#${job.item}`;
|
|
2772
|
+
const log = logOf(state);
|
|
2773
|
+
const inherited = runtime.vm.fdStore.inherited();
|
|
2774
|
+
const inherit = (socket) => {
|
|
2775
|
+
const fd = inherited.get(fdName(microvm.buildId, socket.replace(/\.sock$/, "")));
|
|
2776
|
+
return fd === void 0 ? void 0 : (server) => runtime.vm.fdStore.listenOn(server, fd);
|
|
2777
|
+
};
|
|
2778
|
+
const tokens = buildTokensFor(state, adopted, job.item);
|
|
2779
|
+
runtime.credentials.set(dirPath, tokens);
|
|
2780
|
+
let servicesServed = false;
|
|
2781
|
+
let leaseServed = false;
|
|
2782
|
+
try {
|
|
2783
|
+
const repositories = repositoriesOf({ repositories: job.repositories, repository: microvm.repository, branch: job.branch });
|
|
2784
|
+
const gitRemote = repositories.length === 0 ? void 0 : gitRemoteFor(runtime, { repositories, tokens, buildDir: microvm.buildDir, log: (line) => log.line(`${tag} ${line}`) });
|
|
2785
|
+
runtime.tunnels.set(microvm.buildId, await startServicesFor(runtime, config, microvm.buildDir, dirPath, job.itemKey, microvm.builtIns === true, gitRemote, "socket", void 0, inherit));
|
|
2786
|
+
servicesServed = true;
|
|
2787
|
+
} catch (err) {
|
|
2788
|
+
log.error(`${tag} the adopted build's services could not be served again: ${describeCallFailure(err)}`);
|
|
2789
|
+
}
|
|
2790
|
+
try {
|
|
2791
|
+
const channel = createLeaseChannel(leaseTimeLeftFor(state, adopted));
|
|
2792
|
+
const served = await serveLease(join(microvm.buildDir, "lease.sock"), { ...channel, accept: (stream) => runtime.leases.get(microvm.buildId)?.accept(stream) }, void 0, inherit("lease.sock"));
|
|
2793
|
+
runtime.leases.set(microvm.buildId, { ...channel, close: served.close });
|
|
2794
|
+
leaseServed = true;
|
|
2795
|
+
} catch (err) {
|
|
2796
|
+
log.error(`${tag} the adopted build's lease stream could not be served again: ${describeCallFailure(err)}`);
|
|
2797
|
+
}
|
|
2798
|
+
try {
|
|
2799
|
+
await tokens.token("read");
|
|
2800
|
+
} catch (err) {
|
|
2801
|
+
log.error(`${tag} could not give the adopted build a read token: ${describeCallFailure(err)}`);
|
|
2802
|
+
}
|
|
2803
|
+
let pushes = Promise.resolve();
|
|
2804
|
+
tokens.onRead((token) => {
|
|
2805
|
+
pushes = pushes.then(async () => {
|
|
2806
|
+
if (vmAlive(runtime, microvm)) await writeGuestGhConfig(runtime, microvm, token);
|
|
2807
|
+
}).catch((err) => log.error(`${tag} the read token could not be written for gh in the guest: ${describeCallFailure(err)}`));
|
|
2808
|
+
});
|
|
2809
|
+
await pushes;
|
|
2810
|
+
return servicesServed && leaseServed;
|
|
2811
|
+
}
|
|
2812
|
+
async function adoptTrackedMicroVms(state, plan) {
|
|
2813
|
+
const log = logOf(state);
|
|
2814
|
+
const attemptLogs = attemptLogsOf(state);
|
|
2815
|
+
const runtime = runtimeOf(state);
|
|
2816
|
+
for (const { dirPath, job } of plan.away) await finishMicroVmWhileAway(state, dirPath, job, MICROVM_STOPPED_REASON, "its unit stopped");
|
|
2817
|
+
for (const { dirPath, job } of plan.unservable) await finishMicroVmWhileAway(state, dirPath, job, MICROVM_SOCKETS_LOST_REASON, "the sockets it reaches the runner on are gone");
|
|
2818
|
+
for (const { dirPath, job } of plan.unasked) await finishMicroVmWhileAway(state, dirPath, job, MICROVM_HELPER_UNREACHABLE_REASON, "the helper did not answer about its unit");
|
|
2819
|
+
for (const { dirPath, job } of plan.adopt) {
|
|
2820
|
+
const adopted = { job, dirPath, lastRenewAtMs: 0, cmd: null, cpuSample: null, ending: false };
|
|
2821
|
+
state.jobs.set(dirPath, adopted);
|
|
2822
|
+
attemptLogs.open(job.item, dirPath);
|
|
2823
|
+
if (!await rejoinMicroVmBuild(state, adopted)) {
|
|
2824
|
+
state.jobs.delete(dirPath);
|
|
2825
|
+
await finishMicroVmWhileAway(state, dirPath, job, MICROVM_SOCKETS_LOST_REASON, "the sockets it reaches the runner on could not be served again");
|
|
2826
|
+
continue;
|
|
2827
|
+
}
|
|
2828
|
+
if (!await renewLeaseIfDue(state, adopted, nowOf(state).getTime())) continue;
|
|
2829
|
+
const sender = await restartSender({ config: state.config, job: adopted.job, jobDir: dirPath, deps: { spawnFn: state.deps.spawnFn, runtime, log, sleep: state.deps.sleep } });
|
|
2830
|
+
adopted.job = sender === void 0 ? { ...adopted.job, sender: void 0 } : { ...adopted.job, sender };
|
|
2831
|
+
writeJobFile(join(dirPath, "job.json"), adopted.job);
|
|
2832
|
+
const line = `adopted job ${job.queue} #${job.item} (claim ${shortClaim(job.claimId)}) \xB7 command tracked in microVM build ${job.microvm.buildId}`;
|
|
2833
|
+
log.line(line);
|
|
2834
|
+
attemptLogs.note(job.item, line);
|
|
2835
|
+
void probeBuild(state, adopted);
|
|
2836
|
+
}
|
|
2837
|
+
await removeUnadoptedSockets(state, new Set(plan.adopt.map(({ job }) => job.microvm.buildId)));
|
|
2838
|
+
}
|
|
2839
|
+
async function removeUnadoptedSockets(state, adopted) {
|
|
2840
|
+
const store = runtimeOf(state).vm.fdStore;
|
|
2841
|
+
for (const [name, fd] of store.inherited()) {
|
|
2842
|
+
const buildId = /^ol-([0-9a-f]+)-/.exec(name)?.[1];
|
|
2843
|
+
if (buildId === void 0 || adopted.has(buildId)) continue;
|
|
2844
|
+
await store.remove(name).catch((err) => logOf(state).error(`the descriptor ${name} could not be taken out of the store: ${describeCallFailure(err)}`));
|
|
2845
|
+
try {
|
|
2846
|
+
closeSync(fd);
|
|
2847
|
+
} catch {
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
async function finishMicroVmWhileAway(state, dirPath, job, reason, why) {
|
|
2852
|
+
const log = logOf(state);
|
|
2853
|
+
const recorded = outcomeFromExitCode(dirPath);
|
|
2854
|
+
let outcome = "interrupted";
|
|
2855
|
+
let ending = { reason };
|
|
2856
|
+
if (recorded !== void 0) {
|
|
2857
|
+
job.exitCode = recorded.code;
|
|
2858
|
+
job.commandEndReason = jobNotEndedByRunnerReason({ code: recorded.code, signal: null }, job);
|
|
2859
|
+
outcome = recorded.outcome === "ok" ? "ok" : "failed";
|
|
2860
|
+
ending = void 0;
|
|
2861
|
+
}
|
|
2862
|
+
const finished = await finishJob(job, dirPath, outcome, state.config, finishDepsOf(state), ending);
|
|
2863
|
+
log.line(
|
|
2864
|
+
`recovered job ${finished.queue} #${finished.item} (claim ${shortClaim(finished.claimId)}) as ${outcome}: ${recorded === void 0 ? `${why}, and no exit code had been read` : `its command recorded exit ${recorded.code}`}`
|
|
2865
|
+
);
|
|
2866
|
+
}
|
|
2665
2867
|
async function readStoppedBuild(state, dirPath, job) {
|
|
2666
2868
|
const runtime = runtimeOf(state);
|
|
2667
2869
|
const container = job.container;
|
|
@@ -2721,6 +2923,11 @@ async function finishTrackedWhileAway(state, dirPath, job, where) {
|
|
|
2721
2923
|
`recovered job ${finished.queue} #${finished.item} (claim ${shortClaim(finished.claimId)}) as ${outcome}: ${code === void 0 ? `its container ${where === "missing" ? "is gone" : "stopped"} and its volume ${read.readable ? "holds no exit code" : "could not be read"}` : `its command recorded exit ${code}`}`
|
|
2722
2924
|
);
|
|
2723
2925
|
}
|
|
2926
|
+
async function canLeaveBuilds(state) {
|
|
2927
|
+
if (state.deps.leave === void 0 || state.deps.image !== void 0 || !isBuiltinVm(state.config.hooks.provision)) return false;
|
|
2928
|
+
const runtime = runtimeOf(state);
|
|
2929
|
+
return (await runtime.vm.helper.probe()).ok && (await runtime.vm.fdStore.status()).ok;
|
|
2930
|
+
}
|
|
2724
2931
|
async function logUnusableHelper(config, runtime, log) {
|
|
2725
2932
|
if (!isBuiltinVm(config.hooks.provision)) return;
|
|
2726
2933
|
const helper = await runtime.vm.helper.probe();
|
|
@@ -2735,7 +2942,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2735
2942
|
const outcome = await onStartUnderMarker({
|
|
2736
2943
|
configPath,
|
|
2737
2944
|
own: ownVersionOf(deps),
|
|
2738
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
2945
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-JVBAWIN6.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
2739
2946
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
2740
2947
|
log
|
|
2741
2948
|
});
|
|
@@ -2773,9 +2980,29 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2773
2980
|
}
|
|
2774
2981
|
const state = { config, jobs: /* @__PURE__ */ new Map(), deps, configMtimeMs };
|
|
2775
2982
|
log.line(`runner ${config.host} started \xB7 config ${configPath} \xB7 ${describeConfig(config)}`);
|
|
2983
|
+
const leavesBuilds = await canLeaveBuilds(state);
|
|
2984
|
+
let sigusr2Target;
|
|
2985
|
+
let sigusr2Early = false;
|
|
2986
|
+
const forwardSigusr2 = () => {
|
|
2987
|
+
if (sigusr2Target === void 0) sigusr2Early = true;
|
|
2988
|
+
else sigusr2Target();
|
|
2989
|
+
};
|
|
2990
|
+
if (leavesBuilds) {
|
|
2991
|
+
process.on("SIGUSR2", forwardSigusr2);
|
|
2992
|
+
writePidFile(pidFilePath(configPath), { ...self, leaves: true });
|
|
2993
|
+
}
|
|
2776
2994
|
const nowMs = () => deps.now ? deps.now().getTime() : Date.now();
|
|
2777
2995
|
await logUnusableHelper(config, runtimeOf(state), log);
|
|
2778
|
-
const
|
|
2996
|
+
const microVmPlan = await planMicroVmAdoption(state, jobsDir(configPath)).catch((err) => {
|
|
2997
|
+
log.error(`the microVM builds an earlier runner left could not be told apart: ${describeCallFailure(err)}`);
|
|
2998
|
+
return { adopt: [], away: [], unservable: [], unasked: [] };
|
|
2999
|
+
});
|
|
3000
|
+
const runningMicroVms = await stopOrphanedMicroVms({
|
|
3001
|
+
jobs: unfinishedJobs(jobsDir(configPath)),
|
|
3002
|
+
runtime: runtimeOf(state),
|
|
3003
|
+
onError: (line) => log.error(line),
|
|
3004
|
+
keep: new Set(microVmPlan.adopt.map(({ job }) => job.microvm.buildId))
|
|
3005
|
+
}).catch((err) => {
|
|
2779
3006
|
log.error(`a microVM an earlier runner left could not be stopped: ${describeCallFailure(err)}`);
|
|
2780
3007
|
return [];
|
|
2781
3008
|
});
|
|
@@ -2799,6 +3026,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2799
3026
|
attemptLogs.note(job.item, adoptedLine);
|
|
2800
3027
|
}
|
|
2801
3028
|
await adoptTrackedBuilds(state, jobsDir(configPath));
|
|
3029
|
+
await adoptTrackedMicroVms(state, microVmPlan);
|
|
2802
3030
|
for (const { job, released } of await retryFailedReleases(jobsDir(configPath), config, {
|
|
2803
3031
|
fetchImpl: deps.fetchImpl,
|
|
2804
3032
|
now: deps.now,
|
|
@@ -2843,9 +3071,13 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2843
3071
|
const probeTimer = setInterval(() => {
|
|
2844
3072
|
for (const active of state.jobs.values()) void probeBuild(state, active);
|
|
2845
3073
|
}, deps.probeIntervalMs ?? PROBE_INTERVAL_MS);
|
|
2846
|
-
const onSigterm = () =>
|
|
3074
|
+
const onSigterm = () => {
|
|
3075
|
+
if (deps.image !== void 0) leave();
|
|
3076
|
+
else if (leavesBuilds && buildBlockers(runningBuilds(state)).length === 0) leave();
|
|
3077
|
+
else void drain();
|
|
3078
|
+
};
|
|
2847
3079
|
const onSigusr1 = () => void stopNow();
|
|
2848
|
-
const onSigusr2 = () => drainKeepingUp();
|
|
3080
|
+
const onSigusr2 = () => deps.image === void 0 ? void drain() : drainKeepingUp();
|
|
2849
3081
|
const onSigint = () => {
|
|
2850
3082
|
interrupts++;
|
|
2851
3083
|
if (interrupts === 1) {
|
|
@@ -2859,6 +3091,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2859
3091
|
process.off("SIGTERM", onSigterm);
|
|
2860
3092
|
process.off("SIGUSR1", onSigusr1);
|
|
2861
3093
|
process.off("SIGUSR2", onSigusr2);
|
|
3094
|
+
process.off("SIGUSR2", forwardSigusr2);
|
|
2862
3095
|
process.off("SIGINT", onSigint);
|
|
2863
3096
|
};
|
|
2864
3097
|
const stopIntake = () => {
|
|
@@ -2916,7 +3149,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2916
3149
|
log.line(`stopping: leaving ${state.jobs.size} running build(s) for the next runner to adopt`);
|
|
2917
3150
|
state.draining = true;
|
|
2918
3151
|
finish2();
|
|
2919
|
-
deps.image?.exit?.(0);
|
|
3152
|
+
(deps.image?.exit ?? deps.leave?.exit)?.(0);
|
|
2920
3153
|
};
|
|
2921
3154
|
const stopNow = async () => {
|
|
2922
3155
|
if (stopping) return;
|
|
@@ -2938,7 +3171,10 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2938
3171
|
const handle = { state, drain, stopNow, close };
|
|
2939
3172
|
process.on("SIGTERM", onSigterm);
|
|
2940
3173
|
process.on("SIGUSR1", onSigusr1);
|
|
2941
|
-
if (
|
|
3174
|
+
if (leavesBuilds) {
|
|
3175
|
+
sigusr2Target = onSigusr2;
|
|
3176
|
+
if (sigusr2Early) onSigusr2();
|
|
3177
|
+
} else if (deps.image !== void 0) process.on("SIGUSR2", onSigusr2);
|
|
2942
3178
|
process.on("SIGINT", onSigint);
|
|
2943
3179
|
deps.onReady?.();
|
|
2944
3180
|
await tick(state);
|
|
@@ -2964,7 +3200,7 @@ async function requestStop(configPath, stopNow = false, pollMs = 5e3, options =
|
|
|
2964
3200
|
`);
|
|
2965
3201
|
return;
|
|
2966
3202
|
}
|
|
2967
|
-
const signal = stopNow ? "SIGUSR1" : options.image === true ? "SIGUSR2" : "SIGTERM";
|
|
3203
|
+
const signal = stopNow ? "SIGUSR1" : options.image === true || entry.leaves === true ? "SIGUSR2" : "SIGTERM";
|
|
2968
3204
|
try {
|
|
2969
3205
|
kill(entry.pid, signal);
|
|
2970
3206
|
} catch (err) {
|
|
@@ -2979,7 +3215,7 @@ async function requestStop(configPath, stopNow = false, pollMs = 5e3, options =
|
|
|
2979
3215
|
`);
|
|
2980
3216
|
return;
|
|
2981
3217
|
}
|
|
2982
|
-
if (signal === "SIGUSR2") {
|
|
3218
|
+
if (signal === "SIGUSR2" && entry.leaves !== true) {
|
|
2983
3219
|
process.stdout.write(
|
|
2984
3220
|
`sent SIGUSR2 to runner pid ${entry.pid}: it takes no more work and keeps managing its builds.
|
|
2985
3221
|
The container stays up. Run \`outerlayer runner status\` to see what is left, then \`docker stop\` the container once nothing is.
|
|
@@ -2989,7 +3225,7 @@ The container stays up. Run \`outerlayer runner status\` to see what is left, th
|
|
|
2989
3225
|
}
|
|
2990
3226
|
process.stdout.write(
|
|
2991
3227
|
stopNow ? `sent SIGUSR1 to runner pid ${entry.pid}, stopping now
|
|
2992
|
-
` : `sent
|
|
3228
|
+
` : `sent ${signal} to runner pid ${entry.pid}, draining
|
|
2993
3229
|
`
|
|
2994
3230
|
);
|
|
2995
3231
|
while (isSameProcess(entry.pid, entry.start)) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { sharedSkillNames } from './chunk-
|
|
3
|
+
import { sharedSkillNames } from './chunk-6TRNCUM4.js';
|
|
4
4
|
import { GOVERNANCE_VARIABLE, versionAtLeast, MINIMUM_CLAUDE_VERSION, SHIM_SCRIPT, CONTROL_PLANE_DIR_VARIABLE } from './chunk-HCVLP7XA.js';
|
|
5
5
|
export { MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
|
|
6
6
|
import { findGitDirs } from './chunk-BJ3KTMDH.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import { setupMachineSkills } from './chunk-BM7EC3OZ.js';
|
|
8
|
+
import './chunk-7OUOLGUV.js';
|
|
8
9
|
import './chunk-RKOTJQVG.js';
|
|
9
10
|
import './chunk-QZBXLLTV.js';
|
|
10
11
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
@@ -210,12 +211,15 @@ async function runClaudeLauncher(args, deps = {}) {
|
|
|
210
211
|
const cwd = deps.cwd ?? process.cwd();
|
|
211
212
|
const env = deps.env ?? process.env;
|
|
212
213
|
const stderr = deps.stderr ?? ((text) => void process.stderr.write(text));
|
|
214
|
+
const home = homeFromEnv(env);
|
|
215
|
+
const installed = setupMachineSkills(home);
|
|
216
|
+
for (const failure of installed.failures) stderr(`outerlayer claude: could not write a maintained skill: ${failure}
|
|
217
|
+
`);
|
|
213
218
|
const claude = findClaude(env.PATH);
|
|
214
219
|
if (claude === void 0) {
|
|
215
220
|
stderr("outerlayer claude: no claude program found on PATH\n");
|
|
216
221
|
return 127;
|
|
217
222
|
}
|
|
218
|
-
const home = homeFromEnv(env);
|
|
219
223
|
try {
|
|
220
224
|
removeStaleOwnSkillsDirs(home);
|
|
221
225
|
} catch {
|
|
@@ -236,7 +240,7 @@ async function runClaudeLauncher(args, deps = {}) {
|
|
|
236
240
|
return 1;
|
|
237
241
|
}
|
|
238
242
|
} else {
|
|
239
|
-
const { resolveLaunchPlane } = await import('./control-plane-launch-
|
|
243
|
+
const { resolveLaunchPlane } = await import('./control-plane-launch-DBQA3KLJ.js');
|
|
240
244
|
const plane = env[GOVERNANCE_VARIABLE] === "self" ? { kind: "none" } : await resolveLaunchPlane({ cwd, env, home, fetchImpl: deps.fetchImpl, stderr });
|
|
241
245
|
if (plane.kind === "none") {
|
|
242
246
|
const own2 = ownSkillsDirFor(cwd, home, [], stderr);
|