@outerlayer/cli 0.20.0 → 0.22.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 +26 -0
- package/README.md +15 -5
- package/dist/{agent-setup-AM42SA2D.js → agent-setup-XAJH6MPW.js} +13 -12
- package/dist/build-GTMEADQD.js +12 -0
- package/dist/build-command-ND2ENDBS.js +50 -0
- package/dist/build-info.json +1 -1
- package/dist/{builder-C4QNTYMS.js → builder-OAUSTZHL.js} +7 -5
- package/dist/{check-BR5D27CX.js → check-3YHMJQ3P.js} +48 -50
- package/dist/{chunk-AD3EYI7P.js → chunk-22DYXLU7.js} +259 -56
- package/dist/{chunk-P53VEAOF.js → chunk-2CMJLYV6.js} +1 -1
- package/dist/{chunk-FBTGMSQF.js → chunk-2HT2XGJX.js} +16 -9
- package/dist/{chunk-S5PCA3SN.js → chunk-2J5JGLW5.js} +1 -1
- package/dist/{chunk-R22NZSGA.js → chunk-34XORKFD.js} +9 -9
- package/dist/{chunk-QOZKPLVJ.js → chunk-3W333NFO.js} +40 -1
- package/dist/{chunk-HOKXGFDR.js → chunk-4JHVPFH6.js} +22 -16
- package/dist/{chunk-AMFWYESY.js → chunk-4NM3I3VV.js} +1 -1
- package/dist/{chunk-PIZRPNKR.js → chunk-4QKLMNI3.js} +5 -5
- package/dist/{chunk-NNLA7LLQ.js → chunk-5OCIHFGE.js} +29 -5
- package/dist/{chunk-PSN33ERW.js → chunk-6IO62VJS.js} +3 -3
- package/dist/{chunk-7YP7T6GV.js → chunk-7V7KG3YM.js} +2 -2
- package/dist/{chunk-QNLX477Q.js → chunk-AEKSX4EY.js} +165 -72
- package/dist/{chunk-JHGEBPLE.js → chunk-ATRIVTRE.js} +3 -3
- package/dist/{chunk-X5H2WYMB.js → chunk-BLW6GPBZ.js} +1 -1
- package/dist/{chunk-MLAAT4S6.js → chunk-C3HKR67W.js} +3 -3
- package/dist/{chunk-XZ4H4X5F.js → chunk-C3OVGKVJ.js} +15 -8
- package/dist/{chunk-BM63HB2M.js → chunk-EAQSOE62.js} +2 -2
- package/dist/{chunk-LW7G5TJB.js → chunk-EXV37PKS.js} +2 -2
- package/dist/{chunk-B6SCN5NY.js → chunk-FGW2774C.js} +175 -44
- package/dist/{chunk-KYS3TQAG.js → chunk-G2WME4RG.js} +4 -4
- package/dist/{chunk-LRG3ZMZD.js → chunk-G6DZCKA6.js} +4 -4
- package/dist/chunk-GISNHSYL.js +41 -0
- package/dist/{chunk-G2YNJIGF.js → chunk-HCVLP7XA.js} +10 -1
- package/dist/{chunk-QEFKA2QD.js → chunk-I66MQDXH.js} +2 -2
- package/dist/{chunk-3CWUOFV6.js → chunk-IRBNIRQJ.js} +12 -7
- package/dist/{chunk-CG36IONK.js → chunk-JRCSET55.js} +2 -2
- package/dist/{chunk-CGGPS7SI.js → chunk-JVB63NIB.js} +5 -5
- package/dist/{chunk-M2ZWWTWZ.js → chunk-KDHYLBRR.js} +1 -1
- package/dist/{chunk-N2PXGQRL.js → chunk-KIGSGZBB.js} +1 -1
- package/dist/{chunk-EAEELQVQ.js → chunk-KOQELWQ6.js} +5 -5
- package/dist/{chunk-MTP2QEVO.js → chunk-KPBQYEND.js} +1 -1
- package/dist/{chunk-VYAL7PUE.js → chunk-LOB2SUM3.js} +1 -1
- package/dist/{chunk-GGOMT6KF.js → chunk-PHHBYAL6.js} +1 -1
- package/dist/{chunk-IF2OSI5T.js → chunk-QOALB6ZD.js} +2 -2
- package/dist/{chunk-ZX4I2MEK.js → chunk-TPKYTORP.js} +1 -1
- package/dist/{chunk-XNGMQ27R.js → chunk-UD3EXMKB.js} +2 -2
- package/dist/{chunk-7UWVLZXD.js → chunk-USWVXQIH.js} +1 -1
- package/dist/{chunk-BQXFBI7T.js → chunk-V7MQKOZY.js} +32 -7
- package/dist/{chunk-6X4SQ5MY.js → chunk-V7SAQ645.js} +1 -1
- package/dist/{chunk-TWF3RICI.js → chunk-VSUXCMMH.js} +110 -11
- package/dist/{chunk-FVMYKL6L.js → chunk-VWLOQ6FI.js} +1 -1
- package/dist/{chunk-3ZR7Y23Y.js → chunk-VX74ND77.js} +650 -70
- package/dist/{chunk-Z7K3L4FC.js → chunk-W3SWJ2TD.js} +2 -2
- package/dist/chunk-WERZMIKA.js +718 -0
- package/dist/{chunk-GEMQLBMW.js → chunk-WMHYIBJW.js} +6 -6
- package/dist/{chunk-5VML45HH.js → chunk-XCRZTXRL.js} +2 -2
- package/dist/{chunk-ECODQ7II.js → chunk-ZFLOGMUC.js} +1 -1
- package/dist/chunk-ZNPE7FW5.js +137 -0
- package/dist/claude-launcher-4BQNXYAF.js +267 -0
- package/dist/{cli-MKF7TU7X.js → cli-NMGVZQPB.js} +161 -120
- package/dist/{command-ZQNEPDS6.js → command-GE62AJZY.js} +32 -34
- package/dist/{config-CLSGABD5.js → config-7Q52COZ3.js} +3 -2
- package/dist/{connect-cmd-UNYKGDAL.js → connect-cmd-ZFOK6HEL.js} +5 -5
- package/dist/{context-cleanup-CHEWNYU6.js → context-cleanup-DSA3HGQU.js} +1 -1
- package/dist/{control-plane-launch-34LNRJWR.js → control-plane-launch-SZTE4TUS.js} +62 -28
- package/dist/{dist-WO7NOJNG.js → dist-7IH56ELA.js} +1 -1
- package/dist/{docker-BFU3AQGY.js → docker-2OVBKVRK.js} +7 -7
- package/dist/{doctor-DHUM5DBB.js → doctor-3SQGZVYP.js} +35 -36
- package/dist/{emit-artifact-cmd-XBHM647X.js → emit-artifact-cmd-R42BE6ID.js} +19 -18
- package/dist/{emit-cmd-W55AEBCA.js → emit-cmd-3W5IO5ET.js} +3 -3
- package/dist/{emit-criteria-cmd-UNMWHOUY.js → emit-criteria-cmd-MQZE7W4Y.js} +13 -12
- package/dist/{emit-finding-cmd-7JHVRYOP.js → emit-finding-cmd-ZS5JEGGM.js} +13 -12
- package/dist/{emit-result-cmd-5NZMLCJK.js → emit-result-cmd-FUE3DXBW.js} +19 -18
- package/dist/{emit-step-cmd-347XNGPQ.js → emit-step-cmd-T7PRA44X.js} +14 -13
- package/dist/{exec-client-7UMESIE2.js → exec-client-YIDTWXMZ.js} +4 -3
- package/dist/{governing-source-HAA4OW57.js → governing-source-TORXL4I4.js} +19 -18
- package/dist/{guest-init-KPBQOFE5.js → guest-init-TO6HAWIT.js} +4 -3
- package/dist/{hook-fast-RL5E5OXE.js → hook-fast-WFB2ZMRB.js} +2 -2
- package/dist/host-key-2LXQDSBO.js +9 -0
- package/dist/{import-capture-cmd-TK4XY7RD.js → import-capture-cmd-Q56DDZVO.js} +1 -1
- package/dist/index.js +5 -5
- package/dist/init-2CRAVIUU.js +52 -0
- package/dist/{init-V6FOMD2V.js → init-AHDZCMDC.js} +32 -33
- package/dist/{init-cmd-Z4O4PPLZ.js → init-cmd-IXDL2ZSL.js} +25 -23
- package/dist/{init-update-7DVAKWW3.js → init-update-YB3PODDH.js} +69 -24
- package/dist/{install-4SEFIIW2.js → install-CZUIW2AF.js} +5 -4
- package/dist/{install-cmd-QDOTR4OM.js → install-cmd-Q7RJGFUO.js} +6 -5
- package/dist/{login-browser-DX35MARZ.js → login-browser-BN5UKPHS.js} +3 -3
- package/dist/{logout-cmd-5V5MMBSY.js → logout-cmd-RZFWTNYD.js} +2 -2
- package/dist/{logs-AMLKC3VP.js → logs-RJPYTVQE.js} +3 -2
- package/dist/loop-ZDW6TRAA.js +75 -0
- package/dist/machine-JCOHLASP.js +47 -0
- package/dist/{mcp-install-cmd-GGWB3JJ2.js → mcp-install-cmd-GD4QUP7Z.js} +2 -2
- package/dist/{mcp-serve-cmd-N3UTY6EE.js → mcp-serve-cmd-IULQPVHL.js} +6 -5
- package/dist/{paths-7XP63OAX.js → paths-N3LU4O2Z.js} +3 -2
- package/dist/pending-GRCV3ZR4.js +9 -0
- package/dist/{pidfile-3DM4OBKO.js → pidfile-IF3TCL5A.js} +4 -3
- package/dist/receive-files-T2BIUBQL.js +254 -0
- package/dist/{record-3WP6V2K5.js → record-73PQE77B.js} +4 -3
- package/dist/relay-PSZ4LGMW.js +210 -0
- package/dist/relay-protocol-K7KP2SPI.js +6 -0
- package/dist/{runner-env-FRZFFHDF.js → runner-env-LDOBJESN.js} +6 -5
- package/dist/runner-identity-RWCBTY2A.js +14 -0
- package/dist/{runner-key-5FOWCW7J.js → runner-key-HMYLP6WN.js} +32 -33
- package/dist/{session-sender-U2BBUWNO.js → session-sender-2G25JYHI.js} +20 -19
- package/dist/{spec-cmd-FVLJOFGC.js → spec-cmd-LBVXM6XS.js} +13 -12
- package/dist/{starter-pack-6LQVLBIA.js → starter-pack-5EQYGSJF.js} +2 -2
- package/dist/{status-BINH7MBG.js → status-QZB2GWXJ.js} +36 -38
- package/dist/{statusline-fast-KN3BX67H.js → statusline-fast-2OK3DVAA.js} +2 -2
- package/dist/{sync-cmd-VXOUFS4I.js → sync-cmd-TQQIR4PN.js} +19 -18
- package/dist/{watch-OH645CV2.js → watch-4JES4PCS.js} +19 -18
- package/dist/{work-claim-cmd-DRQCHCOK.js → work-claim-cmd-XG6O7B63.js} +17 -16
- package/dist/{work-cmd-5I3J2XQQ.js → work-cmd-L6WMPAA2.js} +13 -12
- package/dist/{work-comment-cmd-UCCPWUSR.js → work-comment-cmd-SNTDCPGH.js} +13 -12
- package/dist/{work-logs-cmd-7352CJPG.js → work-logs-cmd-3S7IAVII.js} +13 -12
- package/dist/{work-open-pr-cmd-LSH4VHJM.js → work-open-pr-cmd-E3WMO5XT.js} +15 -14
- package/dist/{work-pr-cmd-H4OQR26N.js → work-pr-cmd-22T6FG4T.js} +14 -13
- package/dist/{work-stop-cmd-CRDHXQVW.js → work-stop-cmd-WR7ESS4Z.js} +13 -12
- package/package.json +2 -2
- package/skill-pack/maintained/outerlayer-build/SKILL.md +347 -0
- package/skill-pack/{template/build → maintained/outerlayer-build}/references/evidence.md +2 -2
- package/skill-pack/{template/build → maintained/outerlayer-build}/references/release.md +4 -4
- package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-loop.md +3 -1
- package/skill-pack/shipped.json +2 -0
- package/skill-pack/template/build/SKILL.md +4 -253
- package/skill-pack/validators/acceptance-criteria.yaml +1 -1
- package/dist/build-TQ6X5PYN.js +0 -12
- package/dist/chunk-3UZTIRLF.js +0 -320
- package/dist/chunk-CX22S5BA.js +0 -45
- package/dist/chunk-LLM3I5YU.js +0 -89
- package/dist/chunk-SADUQSO4.js +0 -50
- package/dist/chunk-VMJPFQNE.js +0 -261
- package/dist/claude-launcher-J5M44PFS.js +0 -115
- package/dist/host-key-U4B5QETR.js +0 -8
- package/dist/init-XG47KCI4.js +0 -53
- package/dist/loop-EAZQMAE2.js +0 -77
- package/dist/machine-TRHBT5NE.js +0 -48
- package/dist/pending-532ABZYC.js +0 -8
- package/dist/relay-L76HDX72.js +0 -46
- package/dist/{chunk-YVZJ6GKF.js → chunk-DIB2WLBL.js} +1 -1
- package/dist/{chunk-GOSFARMS.js → chunk-F35VMF5M.js} +1 -1
- package/dist/{chunk-DSF2FWAZ.js → chunk-IZSVXRDR.js} +1 -1
- /package/skill-pack/{template/build → maintained/outerlayer-build}/references/agent-briefs.md +0 -0
- /package/skill-pack/{template/build → maintained/outerlayer-build}/references/criteria-judge.md +0 -0
- /package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-briefs.md +0 -0
- /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/criterion-citations.mjs +0 -0
- /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/record-criteria.mjs +0 -0
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-SADUQSO4.js';
|
|
5
|
-
import { writePendingUpdate } from './chunk-MTP2QEVO.js';
|
|
6
|
-
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-S5PCA3SN.js';
|
|
3
|
+
import { releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, commandLogOffset, execCommandLine, startSender, startHostServices, finishJob, isContainerTracked, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, AttemptLogBook, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, ALREADY_RELEASED } from './chunk-FGW2774C.js';
|
|
7
4
|
import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
|
|
8
|
-
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
|
|
9
5
|
import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
6
|
+
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
|
|
7
|
+
import { RUNNER_PROTOCOL } from './chunk-TPKYTORP.js';
|
|
8
|
+
import { writePendingUpdate } from './chunk-KPBQYEND.js';
|
|
9
|
+
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-2J5JGLW5.js';
|
|
10
|
+
import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-WMHYIBJW.js';
|
|
12
11
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
13
|
-
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-
|
|
12
|
+
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-4NM3I3VV.js';
|
|
14
13
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-
|
|
18
|
-
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-P53VEAOF.js';
|
|
14
|
+
import { checkFit } from './chunk-I66MQDXH.js';
|
|
15
|
+
import { LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec, measureDisk, setUpRunnerCgroup, createContainerRuntime, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied } from './chunk-VX74ND77.js';
|
|
16
|
+
import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-WERZMIKA.js';
|
|
17
|
+
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-C3OVGKVJ.js';
|
|
18
|
+
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-2HT2XGJX.js';
|
|
19
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-2CMJLYV6.js';
|
|
22
20
|
import { exceedsDisk } from './chunk-7RQ73DLO.js';
|
|
23
|
-
import { claimPidFile, readPidFile, releasePidFile } from './chunk-
|
|
21
|
+
import { claimPidFile, readPidFile, releasePidFile } from './chunk-ZFLOGMUC.js';
|
|
24
22
|
import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
|
|
25
23
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
26
|
-
import { loadHostKey, ensureHostKey, signerFor } from './chunk-
|
|
27
|
-
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, spoolDir,
|
|
28
|
-
import { parseClaimIdentity, parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-
|
|
24
|
+
import { loadHostKey, ensureHostKey, signerFor } from './chunk-KDHYLBRR.js';
|
|
25
|
+
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, rootfsDir } from './chunk-KIGSGZBB.js';
|
|
26
|
+
import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-V7MQKOZY.js';
|
|
27
|
+
import { COMMAND_LOST_REASON, CONTAINER_STOPPED_REASON } from './chunk-GISNHSYL.js';
|
|
29
28
|
import { randomBytes } from 'crypto';
|
|
30
|
-
import { mkdirSync, existsSync, chmodSync, statSync, readdirSync,
|
|
29
|
+
import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync, statSync, readdirSync, readFileSync, rmSync, closeSync, openSync, constants, lstatSync } from 'fs';
|
|
31
30
|
import { join, dirname } from 'path';
|
|
32
31
|
import { totalmem, constants as constants$1 } from 'os';
|
|
33
32
|
|
|
@@ -976,6 +975,7 @@ var QUEUE_ORDER = ["amend", "implement"];
|
|
|
976
975
|
var TRACKER_REPOSITORY_HOSTS = {
|
|
977
976
|
github: "github.com"
|
|
978
977
|
};
|
|
978
|
+
var PROBE_INTERVAL_MS = 3e3;
|
|
979
979
|
var HOUSEKEEPING_INTERVAL_MS = 36e5;
|
|
980
980
|
function logOf(state) {
|
|
981
981
|
state.deps.log ??= createRunnerLog(state.deps.now ?? (() => /* @__PURE__ */ new Date()));
|
|
@@ -1469,7 +1469,7 @@ async function housekeepingPass(state) {
|
|
|
1469
1469
|
state.housekeepingRunning = true;
|
|
1470
1470
|
try {
|
|
1471
1471
|
state.deps.housekeeping ??= {};
|
|
1472
|
-
state.deps.housekeeping.docker ??= createHousekeepingDocker({ runnerId: runnerLabelValue(state.config.configPath), builder: builderName(state.config.configPath) });
|
|
1472
|
+
state.deps.housekeeping.docker ??= createHousekeepingDocker({ run: state.deps.housekeeping.run, runnerId: runnerLabelValue(state.config.configPath), builder: builderName(state.config.configPath) });
|
|
1473
1473
|
const result = await runHousekeeping({
|
|
1474
1474
|
configPath: state.config.configPath,
|
|
1475
1475
|
keepDays: config.jobsKeepDays,
|
|
@@ -1549,10 +1549,10 @@ async function runTick(state) {
|
|
|
1549
1549
|
);
|
|
1550
1550
|
}
|
|
1551
1551
|
var CLAIM_REFUSAL_CODES = new Set(
|
|
1552
|
-
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected branch_claimed_elsewhere".split(" ")
|
|
1552
|
+
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected repository_not_reachable branch_claimed_elsewhere".split(" ")
|
|
1553
1553
|
);
|
|
1554
1554
|
async function tryClaimAndStart(state, item, queue) {
|
|
1555
|
-
const { postJson: postJson2 } = await import('./work-cmd-
|
|
1555
|
+
const { postJson: postJson2 } = await import('./work-cmd-L6WMPAA2.js');
|
|
1556
1556
|
const log = logOf(state);
|
|
1557
1557
|
const hostKey = await loadHostKey(state.config.configPath);
|
|
1558
1558
|
const claim = await retrySend(
|
|
@@ -1656,6 +1656,9 @@ async function tryClaimAndStart(state, item, queue) {
|
|
|
1656
1656
|
return { kind: "unreadable_repositories" };
|
|
1657
1657
|
}
|
|
1658
1658
|
reportRepeating(state, "the repositories", void 0);
|
|
1659
|
+
for (const entry of parseUnreachable(data.unreachable)) {
|
|
1660
|
+
log.line(`#${item.number}: ${entry.repository} is left out of this build because its GitHub App installation is suspended`);
|
|
1661
|
+
}
|
|
1659
1662
|
try {
|
|
1660
1663
|
await startJob(state, item, queue, claimId, itemKey, branch, identity, repositories);
|
|
1661
1664
|
} catch (err) {
|
|
@@ -1786,7 +1789,8 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
1786
1789
|
aborted: () => active.ending,
|
|
1787
1790
|
deadlineMs: startedAt.getTime() + state.config.timeLimitMinutes * 6e4,
|
|
1788
1791
|
fetchImpl: state.deps.fetchImpl,
|
|
1789
|
-
now: state.deps.now
|
|
1792
|
+
now: state.deps.now,
|
|
1793
|
+
leaseExpiryMs: () => leaseExpiresAtMs(active.job)
|
|
1790
1794
|
}).catch((err) => ({ ok: false, reason: `provision failed: ${describeCallFailure(err)}`, aborted: false }));
|
|
1791
1795
|
const provisionTook = formatDuration(nowOf(state).getTime() - provisionStartedMs);
|
|
1792
1796
|
if (active.ending) return;
|
|
@@ -1799,6 +1803,11 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
1799
1803
|
active.job.container = provisioned.state;
|
|
1800
1804
|
active.job.environment = provisioned.environment;
|
|
1801
1805
|
installCommitHooks(active.job, log, tag);
|
|
1806
|
+
const hooksDelivered = await deliverContainerHooks(runtimeOf(state), provisioned.state, dirPath);
|
|
1807
|
+
if (!hooksDelivered.ok) {
|
|
1808
|
+
await endOnProvisionFailure(state, active, tokens, provisionTook, hooksDelivered.reason);
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1802
1811
|
} else if (vmMode) {
|
|
1803
1812
|
const provisioned = await provisionMicroVm({
|
|
1804
1813
|
config: state.config,
|
|
@@ -2030,14 +2039,16 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
2030
2039
|
const composed = microVmCommandLine({ job, cmdline, runtime, config: state.config, cli: join(runtime.cliBuild().distDir, "index.js") });
|
|
2031
2040
|
running = runCommand(composed.line, { ...composed.env, OUTERLAYER_JOB_DIR: dirPath }, dirPath, join(dirPath, "command.log"), state.deps.spawnFn);
|
|
2032
2041
|
} else if (job.container !== void 0) {
|
|
2033
|
-
const
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2042
|
+
const runtime = runtimeOf(state);
|
|
2043
|
+
const exec = containerCommandExec({ job, cmdline, runtime, config: state.config });
|
|
2044
|
+
job.container.tracking = "container";
|
|
2045
|
+
job.container.commandLogBase = commandLogOffset(dirPath, 0);
|
|
2046
|
+
writeJobFile(jobFilePath, job);
|
|
2047
|
+
const started = await runtime.host.execDetached(exec);
|
|
2048
|
+
if (started.status !== 0) {
|
|
2049
|
+
const said = started.stderr.trim().split("\n")[0] ?? "";
|
|
2050
|
+
throw new Error(`docker exec exited ${started.status}${said === "" ? "" : `: ${said}`}`);
|
|
2051
|
+
}
|
|
2041
2052
|
} else {
|
|
2042
2053
|
const build = job.build;
|
|
2043
2054
|
const commandEnv = hostCommandEnvironment(jobEnv(state.config, item.number, itemKey, dirPath, process.env, branch, identity?.author), build, state.config, identity?.hooksPath);
|
|
@@ -2048,12 +2059,13 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
2048
2059
|
await endJob(state, active, "failed", { stage: "command" });
|
|
2049
2060
|
return;
|
|
2050
2061
|
}
|
|
2051
|
-
active.cmd = running;
|
|
2052
|
-
job = { ...job, stage: "command", pid: running.pid, start: running.start ?? void 0 };
|
|
2062
|
+
active.cmd = running ?? null;
|
|
2063
|
+
job = { ...job, stage: "command", ...running === void 0 ? {} : { pid: running.pid, start: running.start ?? void 0 } };
|
|
2053
2064
|
active.job = job;
|
|
2054
2065
|
writeJobFile(jobFilePath, job);
|
|
2055
2066
|
const commandStartedMs = nowOf(state).getTime();
|
|
2056
|
-
|
|
2067
|
+
active.commandStartedMs = commandStartedMs;
|
|
2068
|
+
log.line(running === void 0 ? `${tag} command started \xB7 in container ${job.container.container}` : `${tag} command started \xB7 pid ${running.pid}`);
|
|
2057
2069
|
const sender = await startSender({
|
|
2058
2070
|
config: state.config,
|
|
2059
2071
|
job,
|
|
@@ -2065,6 +2077,10 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
|
|
|
2065
2077
|
active.job = job;
|
|
2066
2078
|
writeJobFile(jobFilePath, job);
|
|
2067
2079
|
}
|
|
2080
|
+
if (running === void 0) {
|
|
2081
|
+
void probeBuild(state, active);
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2068
2084
|
running.onExit.then(({ code, signal, error }) => {
|
|
2069
2085
|
if (active.ending) return;
|
|
2070
2086
|
if (error !== void 0) {
|
|
@@ -2211,12 +2227,84 @@ async function renewLeaseIfDue(state, active, nowMs) {
|
|
|
2211
2227
|
active.job.lastRenewAt = new Date(nowMs).toISOString();
|
|
2212
2228
|
writeJobFile(join(active.dirPath, "job.json"), active.job);
|
|
2213
2229
|
log.line(`${tag} lease renewed \xB7 expires ${formatClock(new Date(nowMs + LEASE_SECONDS * 1e3), new Date(nowMs))}`);
|
|
2230
|
+
if (active.job.container !== void 0) state.containerRuntime?.leases.get(active.job.container.buildId)?.publish();
|
|
2214
2231
|
} else {
|
|
2215
2232
|
log.error(`${tag} renew did not land \xB7 retrying in ${RENEW_INTERVAL_SECONDS / 60}m`);
|
|
2216
2233
|
}
|
|
2217
2234
|
active.lastRenewAtMs = nowMs;
|
|
2218
2235
|
return true;
|
|
2219
2236
|
}
|
|
2237
|
+
var COMMAND_START_GRACE_MS = 3e4;
|
|
2238
|
+
async function endStoppedBuild(state, active, where) {
|
|
2239
|
+
const log = logOf(state);
|
|
2240
|
+
const tag = `#${active.job.item}`;
|
|
2241
|
+
const read = where === "stopped" ? await readStoppedBuild(state, active.dirPath, active.job) : { code: void 0, readable: true };
|
|
2242
|
+
if (active.ending) return;
|
|
2243
|
+
active.job.container.stopped = true;
|
|
2244
|
+
if (read.code !== void 0) {
|
|
2245
|
+
recordCommandExit(state, active, read.code);
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
log.line(
|
|
2249
|
+
`${tag} the build's container ${where === "missing" ? "is gone" : "stopped"} and its volume ${read.readable ? "holds no exit code" : "could not be read"} \xB7 ending job as interrupted`
|
|
2250
|
+
);
|
|
2251
|
+
void endJob(state, active, "interrupted", { stage: "command", reason: COMMAND_LOST_REASON });
|
|
2252
|
+
}
|
|
2253
|
+
async function probeBuild(state, active) {
|
|
2254
|
+
const container = active.job.container;
|
|
2255
|
+
if (container === void 0 || !isContainerTracked(active.job) || active.ending || active.probing) return;
|
|
2256
|
+
active.probing = true;
|
|
2257
|
+
const log = logOf(state);
|
|
2258
|
+
const tag = `#${active.job.item}`;
|
|
2259
|
+
try {
|
|
2260
|
+
const runtime = runtimeOf(state);
|
|
2261
|
+
for (; ; ) {
|
|
2262
|
+
const offset = commandLogOffset(active.dirPath, container.commandLogBase);
|
|
2263
|
+
const probe = await probeCommand(runtime, container, offset);
|
|
2264
|
+
if (active.ending) return;
|
|
2265
|
+
if (probe === void 0) {
|
|
2266
|
+
const where = await runtime.host.state(container.container);
|
|
2267
|
+
if (where === "stopped" || where === "missing") {
|
|
2268
|
+
await endStoppedBuild(state, active, where);
|
|
2269
|
+
} else if (active.probeFailing !== true) {
|
|
2270
|
+
active.probeFailing = true;
|
|
2271
|
+
log.error(`${tag} the build's command could not be read from its container (${where}) \xB7 trying again`);
|
|
2272
|
+
}
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
active.probeFailing = false;
|
|
2276
|
+
appendCommandLog(active.dirPath, probe.bytes);
|
|
2277
|
+
if (probe.bytes.length > 0 && offset + probe.bytes.length < probe.size) continue;
|
|
2278
|
+
const starting = active.commandStartedMs !== void 0 && nowOf(state).getTime() - active.commandStartedMs < COMMAND_START_GRACE_MS;
|
|
2279
|
+
const verdict = starting && probe.exitCode === void 0 && !probe.alive ? { kind: "running" } : judgeProbe(probe, active.commandMissed === true);
|
|
2280
|
+
active.commandMissed = verdict.kind === "recheck";
|
|
2281
|
+
if (verdict.kind === "exited") {
|
|
2282
|
+
recordCommandExit(state, active, verdict.code);
|
|
2283
|
+
} else if (verdict.kind === "lost") {
|
|
2284
|
+
log.line(`${tag} command gone, no exit code recorded \xB7 ending job as interrupted`);
|
|
2285
|
+
void endJob(state, active, "interrupted", { stage: "command", reason: COMMAND_LOST_REASON });
|
|
2286
|
+
}
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
} catch (err) {
|
|
2290
|
+
log.error(`${tag} reading the build's command failed: ${describeCallFailure(err)}`);
|
|
2291
|
+
} finally {
|
|
2292
|
+
active.probing = false;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
function recordCommandExit(state, active, code) {
|
|
2296
|
+
const log = logOf(state);
|
|
2297
|
+
const tag = `#${active.job.item}`;
|
|
2298
|
+
const file = join(active.dirPath, EXIT_CODE_FILE);
|
|
2299
|
+
writeFileSync(`${file}.partial`, `${code}
|
|
2300
|
+
`, { mode: RUNNER_FILE_MODE });
|
|
2301
|
+
renameSync(`${file}.partial`, file);
|
|
2302
|
+
const took = active.commandStartedMs === void 0 ? "" : ` (${formatDuration(nowOf(state).getTime() - active.commandStartedMs)})`;
|
|
2303
|
+
log.line(`${tag} command exited ${code}${took}`);
|
|
2304
|
+
active.job.exitCode = code;
|
|
2305
|
+
active.job.commandEndReason = jobNotEndedByRunnerReason({ code, signal: null }, active.job);
|
|
2306
|
+
void endJob(state, active, code === 0 ? "ok" : "failed");
|
|
2307
|
+
}
|
|
2220
2308
|
async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
2221
2309
|
if (active.ending) {
|
|
2222
2310
|
if (active.job.stage === "checks" || active.job.stage === "judge") await renewLeaseIfDue(state, active, nowMs);
|
|
@@ -2225,6 +2313,7 @@ async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
|
2225
2313
|
const log = logOf(state);
|
|
2226
2314
|
const tag = `#${active.job.item}`;
|
|
2227
2315
|
const pid = active.job.pid;
|
|
2316
|
+
const started = pid !== void 0 || isContainerTracked(active.job);
|
|
2228
2317
|
if (pid !== void 0 && !isGroupAlive(pid)) {
|
|
2229
2318
|
if (active.cmd === null) {
|
|
2230
2319
|
const recorded = outcomeFromExitCode(active.dirPath);
|
|
@@ -2251,16 +2340,22 @@ async function watchTick(state, active, nowMs, logMtimeMs) {
|
|
|
2251
2340
|
}
|
|
2252
2341
|
if (refusal?.kind === "failed") {
|
|
2253
2342
|
log.error(`${tag} a token request was refused: ${refusal.reason} \xB7 ending job as failed`);
|
|
2254
|
-
await endJob(state, active, "failed", { stage:
|
|
2343
|
+
await endJob(state, active, "failed", { stage: started ? "command" : "provision", reason: refusal.reason });
|
|
2255
2344
|
return;
|
|
2256
2345
|
}
|
|
2257
2346
|
}
|
|
2347
|
+
const unreachable = active.job.container === void 0 ? void 0 : runtimeOf(state).relayFatal.get(active.job.container.buildId);
|
|
2348
|
+
if (unreachable !== void 0) {
|
|
2349
|
+
log.error(`${tag} ${unreachable} \xB7 ending job as failed`);
|
|
2350
|
+
await endJob(state, active, "failed", { stage: started ? "command" : "provision", reason: unreachable });
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2258
2353
|
if (isTimedOut(new Date(active.job.startedAt).getTime(), nowMs, state.config.timeLimitMinutes)) {
|
|
2259
2354
|
log.line(`${tag} past the ${state.config.timeLimitMinutes}m time limit \xB7 ending job as timed_out`);
|
|
2260
2355
|
await endJob(state, active, "timed_out");
|
|
2261
2356
|
return;
|
|
2262
2357
|
}
|
|
2263
|
-
if (
|
|
2358
|
+
if (!started) return;
|
|
2264
2359
|
if (active.job.container !== void 0) {
|
|
2265
2360
|
const limit = state.config.build?.disk ?? "40g";
|
|
2266
2361
|
const used = await measureDisk(runtimeOf(state), active.job.container);
|
|
@@ -2308,6 +2403,117 @@ async function probeCredentials(config, fetchImpl = fetch) {
|
|
|
2308
2403
|
return { ok: false, fatal: false, reason: describeCallFailure(err) };
|
|
2309
2404
|
}
|
|
2310
2405
|
}
|
|
2406
|
+
async function rejoinContainerBuild(state, adopted) {
|
|
2407
|
+
const { job, dirPath } = adopted;
|
|
2408
|
+
const config = state.config;
|
|
2409
|
+
const container = job.container;
|
|
2410
|
+
const cores = container.cpuset === void 0 ? void 0 : parseCpuList(container.cpuset);
|
|
2411
|
+
if (cores !== void 0) runtimeOf(state).cpus.hold(container.buildId, cores);
|
|
2412
|
+
const tokens = buildTokensFor(state, adopted, job.item);
|
|
2413
|
+
runtimeOf(state).credentials.set(dirPath, tokens);
|
|
2414
|
+
await ensureTunnel(runtimeOf(state), container, dirPath, config, job.itemKey, job.branch, job.repositories, (line) => logOf(state).line(`#${job.item} ${line}`), () => leaseExpiresAtMs(adopted.job));
|
|
2415
|
+
try {
|
|
2416
|
+
await tokens.token("read");
|
|
2417
|
+
keepGhConfigCurrent(
|
|
2418
|
+
tokens,
|
|
2419
|
+
container.buildDir,
|
|
2420
|
+
(err) => logOf(state).error(`#${job.item} the read token could not be written for gh: ${describeCallFailure(err)}`),
|
|
2421
|
+
filesAreCopied(container) ? {
|
|
2422
|
+
runtime: runtimeOf(state),
|
|
2423
|
+
state: container,
|
|
2424
|
+
secrets: () => tokens.issuedTokens(),
|
|
2425
|
+
onFailure: (reason) => logOf(state).error(`#${job.item} ${reason}`)
|
|
2426
|
+
} : void 0
|
|
2427
|
+
);
|
|
2428
|
+
} catch (err) {
|
|
2429
|
+
logOf(state).error(`#${job.item} could not give the adopted build a read token: ${describeCallFailure(err)}`);
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
async function adoptTrackedBuilds(state, jobsDirPath) {
|
|
2433
|
+
const log = logOf(state);
|
|
2434
|
+
const attemptLogs = attemptLogsOf(state);
|
|
2435
|
+
const runtime = runtimeOf(state);
|
|
2436
|
+
for (const { dirPath, job, known } of listTrackedJobs(jobsDirPath)) {
|
|
2437
|
+
if (!known) continue;
|
|
2438
|
+
const container = job.container;
|
|
2439
|
+
const where = await runtime.host.state(container.container).catch(() => "unknown");
|
|
2440
|
+
if (where === "stopped" || where === "missing") {
|
|
2441
|
+
await finishTrackedWhileAway(state, dirPath, job, where);
|
|
2442
|
+
continue;
|
|
2443
|
+
}
|
|
2444
|
+
const adopted = { job, dirPath, lastRenewAtMs: 0, cmd: null, cpuSample: null, ending: false };
|
|
2445
|
+
state.jobs.set(dirPath, adopted);
|
|
2446
|
+
attemptLogs.open(job.item, dirPath);
|
|
2447
|
+
await rejoinContainerBuild(state, adopted);
|
|
2448
|
+
if (!await renewLeaseIfDue(state, adopted, nowOf(state).getTime())) continue;
|
|
2449
|
+
const sender = await restartSender({ config: state.config, job: adopted.job, jobDir: dirPath, deps: { spawnFn: state.deps.spawnFn, runtime, log, sleep: state.deps.sleep } });
|
|
2450
|
+
adopted.job = sender === void 0 ? { ...adopted.job, sender: void 0 } : { ...adopted.job, sender };
|
|
2451
|
+
writeJobFile(join(dirPath, "job.json"), adopted.job);
|
|
2452
|
+
const line = `adopted job ${job.queue} #${job.item} (claim ${shortClaim(job.claimId)}) \xB7 command tracked in container ${container.container}`;
|
|
2453
|
+
log.line(line);
|
|
2454
|
+
attemptLogs.note(job.item, line);
|
|
2455
|
+
void probeBuild(state, adopted);
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
async function readStoppedBuild(state, dirPath, job) {
|
|
2459
|
+
const runtime = runtimeOf(state);
|
|
2460
|
+
const container = job.container;
|
|
2461
|
+
runtime.leases.get(container.buildId)?.stop();
|
|
2462
|
+
try {
|
|
2463
|
+
for (let attempt = 1; attempt <= STOPPED_READ_ATTEMPTS; attempt++) {
|
|
2464
|
+
const started = await runtime.host.start(container.container);
|
|
2465
|
+
if (started.status === 0) {
|
|
2466
|
+
const code = await readVolumeExitCode(runtime, dirPath, container);
|
|
2467
|
+
if (code !== "unreadable") {
|
|
2468
|
+
await runtime.host.stop(container.container);
|
|
2469
|
+
return { code, readable: true };
|
|
2470
|
+
}
|
|
2471
|
+
await runtime.host.stop(container.container).catch(() => void 0);
|
|
2472
|
+
}
|
|
2473
|
+
if (attempt < STOPPED_READ_ATTEMPTS) await (state.deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))))(STOPPED_READ_RETRY_MS);
|
|
2474
|
+
}
|
|
2475
|
+
logOf(state).error(`#${job.item} the stopped build's volume could not be read after ${STOPPED_READ_ATTEMPTS} tries`);
|
|
2476
|
+
return { code: void 0, readable: false };
|
|
2477
|
+
} catch (err) {
|
|
2478
|
+
logOf(state).error(`#${job.item} the stopped build's volume could not be read: ${describeCallFailure(err)}`);
|
|
2479
|
+
return { code: void 0, readable: false };
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
var STOPPED_READ_ATTEMPTS = 3;
|
|
2483
|
+
var STOPPED_READ_RETRY_MS = 1e3;
|
|
2484
|
+
async function readVolumeExitCode(runtime, dirPath, container) {
|
|
2485
|
+
for (; ; ) {
|
|
2486
|
+
const offset = commandLogOffset(dirPath, container.commandLogBase);
|
|
2487
|
+
const probe = await probeCommand(runtime, container, offset);
|
|
2488
|
+
if (probe === void 0) return "unreadable";
|
|
2489
|
+
appendCommandLog(dirPath, probe.bytes);
|
|
2490
|
+
if (probe.bytes.length > 0 && offset + probe.bytes.length < probe.size) continue;
|
|
2491
|
+
return probe.exitCode;
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
async function finishTrackedWhileAway(state, dirPath, job, where) {
|
|
2495
|
+
const log = logOf(state);
|
|
2496
|
+
const container = job.container;
|
|
2497
|
+
const read = where === "stopped" ? await readStoppedBuild(state, dirPath, job) : { code: void 0, readable: true };
|
|
2498
|
+
const code = read.code;
|
|
2499
|
+
container.stopped = true;
|
|
2500
|
+
let outcome = "interrupted";
|
|
2501
|
+
let ending = { reason: CONTAINER_STOPPED_REASON };
|
|
2502
|
+
if (code !== void 0) {
|
|
2503
|
+
const file = join(dirPath, EXIT_CODE_FILE);
|
|
2504
|
+
writeFileSync(`${file}.partial`, `${code}
|
|
2505
|
+
`, { mode: RUNNER_FILE_MODE });
|
|
2506
|
+
renameSync(`${file}.partial`, file);
|
|
2507
|
+
job.exitCode = code;
|
|
2508
|
+
job.commandEndReason = jobNotEndedByRunnerReason({ code, signal: null }, job);
|
|
2509
|
+
outcome = code === 0 ? "ok" : "failed";
|
|
2510
|
+
ending = void 0;
|
|
2511
|
+
}
|
|
2512
|
+
const finished = await finishJob(job, dirPath, outcome, state.config, finishDepsOf(state), ending);
|
|
2513
|
+
log.line(
|
|
2514
|
+
`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}`}`
|
|
2515
|
+
);
|
|
2516
|
+
}
|
|
2311
2517
|
async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
2312
2518
|
const log = deps.log ??= createRunnerLog(deps.now ?? (() => /* @__PURE__ */ new Date()));
|
|
2313
2519
|
const update = deps.update;
|
|
@@ -2315,7 +2521,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2315
2521
|
const outcome = await onStartUnderMarker({
|
|
2316
2522
|
configPath,
|
|
2317
2523
|
own: ownVersionOf(deps),
|
|
2318
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
2524
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-3YHMJQ3P.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
2319
2525
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
2320
2526
|
log
|
|
2321
2527
|
});
|
|
@@ -2328,6 +2534,12 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2328
2534
|
const hookProblem = checkHooks(config);
|
|
2329
2535
|
if (hookProblem) throw new RunnerStartError(hookProblem);
|
|
2330
2536
|
await ensureHostKey(configPath);
|
|
2537
|
+
if (builtinKind(config.hooks.provision) === "container" || builtinKind(config.hooks.provision) === "vm") {
|
|
2538
|
+
await ensureRunnerIdentity(configPath, {
|
|
2539
|
+
docker: deps.runnerIdentity ?? (deps.container?.host === void 0 ? void 0 : { holdsObjects: async () => false }),
|
|
2540
|
+
log: (line) => log.error(line)
|
|
2541
|
+
}).catch((err) => log.error(`the runner's Docker identity could not be stored: ${describeCallFailure(err)} \xB7 using the names its folder's path gives`));
|
|
2542
|
+
}
|
|
2331
2543
|
const probe = await probeCredentials(config, deps.fetchImpl);
|
|
2332
2544
|
if (!probe.ok && probe.fatal) throw new RunnerStartError(probe.reason);
|
|
2333
2545
|
if (!probe.ok) log.error(`the gateway did not answer at start: ${probe.reason} \xB7 starting anyway`);
|
|
@@ -2358,23 +2570,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2358
2570
|
const adopted = { job, dirPath, lastRenewAtMs: nowMs(), cmd: null, cpuSample: null, ending: false };
|
|
2359
2571
|
state.jobs.set(dirPath, adopted);
|
|
2360
2572
|
attemptLogs.open(job.item, dirPath);
|
|
2361
|
-
if (job.container !== void 0)
|
|
2362
|
-
const cores = job.container.cpuset === void 0 ? void 0 : parseCpuList(job.container.cpuset);
|
|
2363
|
-
if (cores !== void 0) runtimeOf(state).cpus.hold(job.container.buildId, cores);
|
|
2364
|
-
const tokens = buildTokensFor(state, adopted, job.item);
|
|
2365
|
-
runtimeOf(state).credentials.set(dirPath, tokens);
|
|
2366
|
-
await ensureTunnel(runtimeOf(state), job.container, dirPath, config, job.itemKey, job.branch, job.repositories);
|
|
2367
|
-
try {
|
|
2368
|
-
await tokens.token("read");
|
|
2369
|
-
keepGhConfigCurrent(
|
|
2370
|
-
tokens,
|
|
2371
|
-
job.container.buildDir,
|
|
2372
|
-
(err) => logOf(state).error(`#${job.item} the read token could not be written for gh: ${describeCallFailure(err)}`)
|
|
2373
|
-
);
|
|
2374
|
-
} catch (err) {
|
|
2375
|
-
logOf(state).error(`#${job.item} could not give the adopted build a read token: ${describeCallFailure(err)}`);
|
|
2376
|
-
}
|
|
2377
|
-
}
|
|
2573
|
+
if (job.container !== void 0) await rejoinContainerBuild(state, adopted);
|
|
2378
2574
|
if (job.build !== void 0 && !runtimeOf(state).tunnels.has(job.build.buildId)) {
|
|
2379
2575
|
await startHostServices({ runtime: runtimeOf(state), config, build: job.build, jobDir: dirPath, itemKey: job.itemKey, process: job.build.workDir !== void 0 }).catch((err) => {
|
|
2380
2576
|
logOf(state).error(`the tunnel of #${job.item} could not start again: ${describeCallFailure(err)}`);
|
|
@@ -2384,6 +2580,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2384
2580
|
log.line(adoptedLine);
|
|
2385
2581
|
attemptLogs.note(job.item, adoptedLine);
|
|
2386
2582
|
}
|
|
2583
|
+
await adoptTrackedBuilds(state, jobsDir(configPath));
|
|
2387
2584
|
for (const { job, released } of await retryFailedReleases(jobsDir(configPath), config, {
|
|
2388
2585
|
fetchImpl: deps.fetchImpl,
|
|
2389
2586
|
now: deps.now,
|
|
@@ -2425,6 +2622,9 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2425
2622
|
});
|
|
2426
2623
|
}
|
|
2427
2624
|
}, deps.watchIntervalMs ?? 3e4);
|
|
2625
|
+
const probeTimer = setInterval(() => {
|
|
2626
|
+
for (const active of state.jobs.values()) void probeBuild(state, active);
|
|
2627
|
+
}, deps.probeIntervalMs ?? PROBE_INTERVAL_MS);
|
|
2428
2628
|
const onSigterm = () => void drain();
|
|
2429
2629
|
const onSigusr1 = () => void stopNow();
|
|
2430
2630
|
const onSigint = () => {
|
|
@@ -2455,11 +2655,13 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2455
2655
|
closed = true;
|
|
2456
2656
|
clearInterval(pollTimer);
|
|
2457
2657
|
clearInterval(watchTimer);
|
|
2658
|
+
clearInterval(probeTimer);
|
|
2458
2659
|
};
|
|
2459
2660
|
const finish2 = () => {
|
|
2460
2661
|
if (exited) return;
|
|
2461
2662
|
exited = true;
|
|
2462
2663
|
close();
|
|
2664
|
+
for (const relay of state.containerRuntime?.relays.values() ?? []) void relay.close();
|
|
2463
2665
|
releasePidFile(pidFilePath(configPath), self);
|
|
2464
2666
|
log.line("runner exited");
|
|
2465
2667
|
};
|
|
@@ -2489,6 +2691,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2489
2691
|
stopIntake();
|
|
2490
2692
|
clearInterval(pollTimer);
|
|
2491
2693
|
clearInterval(watchTimer);
|
|
2694
|
+
clearInterval(probeTimer);
|
|
2492
2695
|
log.line(`stopping: ending ${state.jobs.size} running job(s) now`);
|
|
2493
2696
|
await Promise.all([...state.jobs.values()].map((active) => endJob(state, active, "stopped")));
|
|
2494
2697
|
finish2();
|
|
@@ -2574,4 +2777,4 @@ function runnerProcessState(configPath) {
|
|
|
2574
2777
|
return isSameProcess(entry.pid, entry.start) ? { state: "running", pid: entry.pid } : { state: "stale", pid: entry.pid };
|
|
2575
2778
|
}
|
|
2576
2779
|
|
|
2577
|
-
export { RunnerStartError, listJobFiles, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick };
|
|
2780
|
+
export { RunnerStartError, listJobFiles, probeBuild, probeCredentials, requestStop, runnerProcessState, start, tick, watchTick };
|
|
@@ -3,7 +3,7 @@ import { createRequire } from 'node:module';
|
|
|
3
3
|
import { MAX_ALLOW_HOSTS, allowHostProblem } from './chunk-UXYLWVTQ.js';
|
|
4
4
|
import { parseSize } from './chunk-7RQ73DLO.js';
|
|
5
5
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
6
|
-
import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-
|
|
6
|
+
import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-V7MQKOZY.js';
|
|
7
7
|
import { existsSync, statSync, accessSync, constants, readFileSync } from 'fs';
|
|
8
8
|
import { hostname } from 'os';
|
|
9
9
|
import { join } from 'path';
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { detectActiveSession, autoConnect } from './chunk-
|
|
4
|
-
import { workPageUrl } from './chunk-
|
|
3
|
+
import { detectActiveSession, autoConnect } from './chunk-QOALB6ZD.js';
|
|
4
|
+
import { workPageUrl } from './chunk-JRCSET55.js';
|
|
5
5
|
import { sanitizeTerminal } from './chunk-G3IJ3N6F.js';
|
|
6
|
-
import {
|
|
7
|
-
import { C } from './chunk-ANPNT6PM.js';
|
|
8
|
-
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
9
|
-
import { defaultFetch } from './chunk-FVMYKL6L.js';
|
|
6
|
+
import { defaultFetch } from './chunk-VWLOQ6FI.js';
|
|
10
7
|
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-NTRCK4NH.js';
|
|
11
8
|
import { readRepoConnection } from './chunk-BJ3KTMDH.js';
|
|
9
|
+
import { resolveRepoIdentity } from './chunk-AEKSX4EY.js';
|
|
10
|
+
import { C } from './chunk-ANPNT6PM.js';
|
|
11
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
12
12
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
13
|
-
import { signRunnerRequest } from './chunk-
|
|
13
|
+
import { signRunnerRequest } from './chunk-KDHYLBRR.js';
|
|
14
14
|
|
|
15
15
|
createRequire(import.meta.url);
|
|
16
16
|
|
|
@@ -378,6 +378,11 @@ async function runWorkBuild(opts) {
|
|
|
378
378
|
const cwd = opts.cwd ?? process.cwd();
|
|
379
379
|
const env = opts.env ?? process.env;
|
|
380
380
|
const home = opts.home ?? homeFromEnv(env);
|
|
381
|
+
if (opts.local && opts.instructions !== void 0) {
|
|
382
|
+
throw new WorkCommandError(
|
|
383
|
+
"--instructions applies to host builds: with --local you build the item yourself, so give your instructions in your own session"
|
|
384
|
+
);
|
|
385
|
+
}
|
|
381
386
|
await connectIfOneFits(opts);
|
|
382
387
|
const { url, apiKey, appId } = resolveCredentials(opts);
|
|
383
388
|
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
@@ -404,9 +409,11 @@ async function runWorkBuild(opts) {
|
|
|
404
409
|
if (!opts.quiet) process.stdout.write(output2 + "\n");
|
|
405
410
|
return { data: data2, output: output2 };
|
|
406
411
|
}
|
|
407
|
-
const
|
|
412
|
+
const instructions = opts.instructions !== void 0 ? { instructions: opts.instructions } : {};
|
|
413
|
+
const body = itemNumber !== void 0 ? { workItemId: String(itemNumber), note: opts.note, ...instructions, ...facts } : {
|
|
408
414
|
subject: resolveWorkSubject({ issue: opts.issue, tracker: opts.tracker, repo: opts.repo, cwd }),
|
|
409
415
|
note: opts.note,
|
|
416
|
+
...instructions,
|
|
410
417
|
...facts
|
|
411
418
|
};
|
|
412
419
|
const { data } = await postJsonWithRetry(url, "/v1/work-items/build", apiKey, appId, body, fetchImpl, retries, sleep);
|
|
@@ -421,7 +428,7 @@ async function runWorkLinkSession(opts) {
|
|
|
421
428
|
return await linkSession(opts);
|
|
422
429
|
} catch (err) {
|
|
423
430
|
if (opts.logFailures) {
|
|
424
|
-
const { logHookError } = await import('./hook-fast-
|
|
431
|
+
const { logHookError } = await import('./hook-fast-WFB2ZMRB.js');
|
|
425
432
|
const reason = err instanceof Error ? err.message : String(err);
|
|
426
433
|
logHookError(opts.home ?? homeFromEnv(opts.env ?? process.env), new Error(`work link-session #${opts.number} failed: ${reason}`));
|
|
427
434
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-
|
|
3
|
+
import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-KIGSGZBB.js';
|
|
4
4
|
import { readFileSync, mkdirSync, writeFileSync, renameSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { uploadSpooledSteps } from './chunk-
|
|
3
|
+
import { uploadSpooledSteps } from './chunk-G2WME4RG.js';
|
|
4
4
|
import { LaunchFilter } from './chunk-ESVW4MJY.js';
|
|
5
5
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
6
6
|
import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-G3IJ3N6F.js';
|
|
7
|
-
import {
|
|
8
|
-
import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
|
|
9
|
-
import { applyReportedCost } from './chunk-BKO6JEZI.js';
|
|
10
|
-
import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-QNLX477Q.js';
|
|
11
|
-
import { C } from './chunk-ANPNT6PM.js';
|
|
12
|
-
import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-T2Q7ISPE.js';
|
|
13
|
-
import { defaultFetch } from './chunk-FVMYKL6L.js';
|
|
7
|
+
import { defaultFetch } from './chunk-VWLOQ6FI.js';
|
|
14
8
|
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-NTRCK4NH.js';
|
|
9
|
+
import { writeSyncStatus, spoolDir } from './chunk-6IO62VJS.js';
|
|
15
10
|
import { readLatestProvenanceForSession, readContextProvenance } from './chunk-ZJSNLVCE.js';
|
|
11
|
+
import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
|
|
12
|
+
import { applyReportedCost } from './chunk-BKO6JEZI.js';
|
|
16
13
|
import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
|
|
14
|
+
import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-AEKSX4EY.js';
|
|
17
15
|
import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
|
|
16
|
+
import { C } from './chunk-ANPNT6PM.js';
|
|
17
|
+
import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-T2Q7ISPE.js';
|
|
18
18
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
19
19
|
import { removeJournalHooks } from './chunk-TUSYOL2O.js';
|
|
20
20
|
import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-7VUK5RFS.js';
|
|
21
21
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
22
|
-
import { signerFor, signRunnerRequest } from './chunk-
|
|
22
|
+
import { signerFor, signRunnerRequest } from './chunk-KDHYLBRR.js';
|
|
23
23
|
import { dirname, basename, join } from 'path';
|
|
24
24
|
import { statSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync, existsSync, rmSync } from 'fs';
|
|
25
25
|
import { execFileSync } from 'child_process';
|