@outerlayer/cli 0.34.0-next.20261027193835 → 0.34.0-next.20261028010245
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/dist/{agent-setup-THDNZ5ME.js → agent-setup-6FPE6EYN.js} +6 -6
- package/dist/{bridge-MLB57JP6.js → bridge-JGIHPGMY.js} +2 -2
- package/dist/{build-25GDCEZ7.js → build-AAQ4PVP2.js} +9 -9
- package/dist/{build-disk-NFMQCZM3.js → build-disk-L7JRQA22.js} +7 -7
- package/dist/build-info.json +1 -1
- package/dist/{builder-OWDGC3VQ.js → builder-LMLAVVVF.js} +6 -6
- package/dist/{check-IFHLERRX.js → check-C7UKLYZQ.js} +38 -38
- package/dist/{chunk-JO4SAEHH.js → chunk-23XAA7YD.js} +2 -2
- package/dist/{chunk-7SJNVGVC.js → chunk-32FAPJFD.js} +5 -5
- package/dist/{chunk-4HA4S3U2.js → chunk-3E7QAXUW.js} +152 -7
- package/dist/{chunk-3FTIUB7I.js → chunk-3X6OSXSB.js} +1 -1
- package/dist/{chunk-3RRYEZAC.js → chunk-3XOLOV5A.js} +3 -3
- package/dist/{chunk-PMIW6OGQ.js → chunk-4A5OJOCR.js} +9 -9
- package/dist/{chunk-NO6E72RM.js → chunk-4J5GRWAY.js} +1 -1
- package/dist/{chunk-4QQJTJUN.js → chunk-57WFXHCB.js} +1 -1
- package/dist/{chunk-36M4KVBT.js → chunk-5IUC2B6J.js} +2 -2
- package/dist/{chunk-7TLGRE5F.js → chunk-5LUN7TTR.js} +2 -2
- package/dist/{chunk-OP2L7OXA.js → chunk-6LS62EO4.js} +3 -3
- package/dist/{chunk-FVVHQIZR.js → chunk-6OLXDSQ6.js} +1 -1
- package/dist/{chunk-AV5T7HV3.js → chunk-6Q7O4MRI.js} +1 -1
- package/dist/{chunk-UZIAZXXO.js → chunk-77D5ENBA.js} +1 -1
- package/dist/{chunk-FLHBUQ2W.js → chunk-AHWMY3MS.js} +155 -10
- package/dist/{chunk-3VJYDWFV.js → chunk-AJTGTSNA.js} +1 -1
- package/dist/{chunk-5FHBVV25.js → chunk-BQ4C47K2.js} +7 -7
- package/dist/{chunk-EYJRVHBN.js → chunk-BTDBDTUY.js} +2 -2
- package/dist/{chunk-X7M73LKT.js → chunk-CM4J53WZ.js} +1 -1
- package/dist/{chunk-WX2HW2G2.js → chunk-D3CT6XQ4.js} +10 -3
- package/dist/{chunk-HJCNWEQK.js → chunk-D6SH7DWA.js} +2 -2
- package/dist/{chunk-LYX2RRSF.js → chunk-EGJY6MBC.js} +2 -2
- package/dist/{chunk-T6ALNN3H.js → chunk-F3BGTGQC.js} +1 -1
- package/dist/{chunk-BS3OYFAD.js → chunk-G4SOMWXL.js} +1 -1
- package/dist/{chunk-BS4CZMT6.js → chunk-GET5HKLM.js} +1 -1
- package/dist/{chunk-6IMQXBTZ.js → chunk-GJYGOFF3.js} +5 -5
- package/dist/{chunk-Y4WJ4BLX.js → chunk-GMEXR6PY.js} +6 -6
- package/dist/{chunk-JWMJMQRF.js → chunk-GXMMILQ4.js} +4 -4
- package/dist/{chunk-S5U6RKQX.js → chunk-HFMK2R7O.js} +99 -179
- package/dist/{chunk-WR2GRWK3.js → chunk-I4YOWQH7.js} +1 -1
- package/dist/{chunk-QRIE4JZE.js → chunk-JXY66VYX.js} +2 -2
- package/dist/{chunk-CMMEJJTL.js → chunk-KTVZ7TZY.js} +2 -2
- package/dist/{chunk-GMKDAF37.js → chunk-L2OARQKP.js} +17 -98
- package/dist/{chunk-CFJOONWM.js → chunk-LBKCYEJT.js} +1 -1
- package/dist/{chunk-OHTMTMFX.js → chunk-NBETYM32.js} +4 -4
- package/dist/{chunk-MXAYUZJF.js → chunk-NCKH3KCM.js} +5 -5
- package/dist/{chunk-RCAMBC3H.js → chunk-NOEJGR4X.js} +2 -2
- package/dist/{chunk-62URQYCB.js → chunk-PAGB3DCI.js} +1 -1
- package/dist/{chunk-Y7MF32DM.js → chunk-PBI4CM4M.js} +67 -60
- package/dist/{chunk-JVNQNKHV.js → chunk-PHIQHIRJ.js} +1 -1
- package/dist/{chunk-7Q7GQELE.js → chunk-PPQTTJSW.js} +5 -5
- package/dist/{chunk-GPO7F757.js → chunk-QJ2SNBHL.js} +1 -1
- package/dist/{chunk-W246VXU4.js → chunk-QNF7LT7W.js} +2 -2
- package/dist/{chunk-Z4LFCJT6.js → chunk-SWCOWG2C.js} +2 -2
- package/dist/{chunk-SKAML7GB.js → chunk-SYMBXSAT.js} +3 -3
- package/dist/{chunk-5ARXP3BP.js → chunk-UEDRRWZ3.js} +3 -3
- package/dist/{chunk-LSFP57LI.js → chunk-VB4QD4WN.js} +273 -122
- package/dist/{chunk-RJZZFAXS.js → chunk-VKYU4HHW.js} +1 -1
- package/dist/{chunk-2YPOSVC7.js → chunk-WEQMLC7P.js} +3 -3
- package/dist/{chunk-ANFNZCXZ.js → chunk-WSVE5QGL.js} +4 -4
- package/dist/{claude-launcher-LYGS66AC.js → claude-launcher-GGZEWVYJ.js} +1 -1
- package/dist/{cli-7S4PEKAV.js → cli-IG52447Q.js} +110 -110
- package/dist/{command-GQVFZHJ2.js → command-NSTOWAZ6.js} +26 -26
- package/dist/{config-5NWSCHIO.js → config-YPUOOZB6.js} +8 -8
- package/dist/{connect-cmd-HB3K3AHE.js → connect-cmd-RPEEANNE.js} +5 -5
- package/dist/{container-start-WRD3YZQR.js → container-start-OOBTGHWF.js} +32 -32
- package/dist/{context-show-cmd-RJIQS2KF.js → context-show-cmd-R5WCECOT.js} +6 -6
- package/dist/{control-plane-launch-TS4DFJF4.js → control-plane-launch-55CJGYBK.js} +5 -5
- package/dist/{demo-record-cmd-VVZGUCWB.js → demo-record-cmd-SFOWQPL7.js} +4 -4
- package/dist/{demo-voice-cmd-3ADGIWK6.js → demo-voice-cmd-ZOBRVHOK.js} +12 -12
- package/dist/{docker-5VGCFZV2.js → docker-VPJW5LXB.js} +6 -6
- package/dist/{doctor-N4I6IEKP.js → doctor-O2EJAPZB.js} +70 -27
- package/dist/{emit-artifact-cmd-WJT7AXTZ.js → emit-artifact-cmd-HBFYBXJR.js} +10 -10
- package/dist/{emit-criteria-cmd-45IYB535.js → emit-criteria-cmd-TPUL7M2R.js} +7 -7
- package/dist/{emit-demo-cmd-AIIQNPXS.js → emit-demo-cmd-5CUT7W3R.js} +12 -12
- package/dist/{emit-finding-cmd-6YTJK2NA.js → emit-finding-cmd-IKHGMACP.js} +7 -7
- package/dist/{emit-result-cmd-TZGFY743.js → emit-result-cmd-F7CI6SNZ.js} +9 -9
- package/dist/{emit-step-cmd-LGBTIAXC.js → emit-step-cmd-DVEKGHK7.js} +7 -7
- package/dist/{exec-client-LR67CA24.js → exec-client-H2JG36OS.js} +3 -3
- package/dist/find-unit-ACTOZVVS.js +19 -0
- package/dist/{findings-cmd-ETJXUDQI.js → findings-cmd-ODKZ462L.js} +7 -7
- package/dist/{fleet-readiness-MYIMDBF7.js → fleet-readiness-UHCBNW6A.js} +5 -5
- package/dist/{governing-source-GBJTVMK2.js → governing-source-SRECHKPR.js} +9 -9
- package/dist/{guest-init-GXPOW53F.js → guest-init-6FUC4XZX.js} +4 -4
- package/dist/{hook-fast-5WOGLR7V.js → hook-fast-WM6YZVBJ.js} +1 -1
- package/dist/{host-checks-33ZTDTSH.js → host-checks-FLIHLR35.js} +30 -30
- package/dist/{pending-6DDSCXUD.js → host-key-OSWPVMIA.js} +3 -3
- package/dist/{image-tag-OYHGRHVV.js → image-tag-LF3NEGSL.js} +3 -3
- package/dist/index.js +4 -4
- package/dist/{init-OXCOPKHP.js → init-LPD75DCX.js} +23 -23
- package/dist/{init-2YOAKLDN.js → init-OX677NNB.js} +23 -23
- package/dist/{init-cmd-BUWWUQKM.js → init-cmd-ZCLVC5RR.js} +10 -10
- package/dist/{init-update-TXQHBY3H.js → init-update-POKSLQDQ.js} +8 -8
- package/dist/{install-cmd-VZGXSS73.js → install-cmd-6SQVZEXL.js} +5 -5
- package/dist/{logs-42QPBCMC.js → logs-QHXZTSKZ.js} +2 -2
- package/dist/{loop-M3XDFD6O.js → loop-ELTO36MN.js} +37 -37
- package/dist/{machine-3BI2SGAK.js → machine-7VPFAC6L.js} +23 -23
- package/dist/{mcp-serve-cmd-LYJQO6U4.js → mcp-serve-cmd-J32K42HM.js} +4 -4
- package/dist/{paths-QLFRPIKS.js → paths-4ZGWWNTG.js} +2 -2
- package/dist/{host-key-GAZM4EOH.js → pending-CRXJKKKI.js} +3 -3
- package/dist/{pidfile-WLZ427QQ.js → pidfile-VLZPRIBZ.js} +3 -3
- package/dist/{record-WGCMQLQS.js → record-4ZJPJTWO.js} +3 -3
- package/dist/{runner-env-6FSJOSWS.js → runner-env-W53VDVOK.js} +10 -10
- package/dist/{runner-identity-XODZ7YBP.js → runner-identity-BH42S2MU.js} +6 -6
- package/dist/{runner-key-KMTC4NCQ.js → runner-key-ESAZRV3A.js} +23 -23
- package/dist/{session-sender-U54EQJNR.js → session-sender-UB45MUKV.js} +10 -10
- package/dist/{spec-cmd-EM24GTAM.js → spec-cmd-H5B55O5L.js} +8 -8
- package/dist/{status-WVCQCBDQ.js → status-L2OYAZHY.js} +30 -30
- package/dist/{sync-cmd-Y5RKWVF7.js → sync-cmd-IWA5ZTI2.js} +9 -9
- package/dist/{update-steps-2D4YQAW2.js → update-steps-FWQ5ASZ6.js} +31 -31
- package/dist/{watch-X5VYY4LH.js → watch-NOEBVS6U.js} +9 -9
- package/dist/{work-claim-cmd-IU3YJQKR.js → work-claim-cmd-7P7U3OQ6.js} +14 -14
- package/dist/{work-cmd-LUKJHAMH.js → work-cmd-77GUT7LY.js} +7 -7
- package/dist/{work-comment-cmd-BDNFAVKL.js → work-comment-cmd-VS3BSPGM.js} +8 -8
- package/dist/{work-demo-cmd-GPDJHU6F.js → work-demo-cmd-S3GXBYIA.js} +7 -7
- package/dist/{work-logs-cmd-B6EX4RPE.js → work-logs-cmd-6BXIINCM.js} +7 -7
- package/dist/{work-open-pr-cmd-TRXDCMSG.js → work-open-pr-cmd-EPOFWJDC.js} +8 -8
- package/dist/{work-pr-cmd-5GUR5SIU.js → work-pr-cmd-DYSYOP74.js} +7 -7
- package/dist/{work-proofs-cmd-5BYAAW3H.js → work-proofs-cmd-DS2VX4E4.js} +8 -8
- package/dist/{work-proofs-record-USD4JWFP.js → work-proofs-record-LIQGUDWH.js} +15 -15
- package/dist/{work-stop-cmd-J47GZB2N.js → work-stop-cmd-HYQTDNUY.js} +7 -7
- package/package.json +1 -1
- package/dist/find-unit-YGDFVHVU.js +0 -19
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { sha256OfFile, downloadPinned, VoiceDownloadError } from './chunk-2PGI6RDE.js';
|
|
4
|
-
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, SHARED_OWNER, SHARED_NAME, metadataFromLabels, writeRecord } from './chunk-
|
|
5
|
-
import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-
|
|
4
|
+
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, SHARED_OWNER, SHARED_NAME, metadataFromLabels, writeRecord } from './chunk-BQ4C47K2.js';
|
|
5
|
+
import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-KTVZ7TZY.js';
|
|
6
6
|
import { currentCliBuild } from './chunk-OGFGZQA3.js';
|
|
7
|
-
import { runExec, execCapture, waitForAgent } from './chunk-
|
|
8
|
-
import { GUEST_CID, linkVsockSockets } from './chunk-
|
|
9
|
-
import { retrySend, describeCallFailure, keepStagedContext, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-
|
|
10
|
-
import { runnerImageVersion } from './chunk-
|
|
11
|
-
import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-
|
|
12
|
-
import { optionalEgress, runnerCredentialProblem, builtinKind, allowHostProblem, systemClock, emptyEgressCounts, hostAllowed } from './chunk-
|
|
13
|
-
import { formatBytes, allocatedBytes } from './chunk-
|
|
14
|
-
import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, spawnRun } from './chunk-
|
|
15
|
-
import { RecipeError, DOCKER_FEATURE, universalImagePending, writeSanitizedRecipe, classifyProperties } from './chunk-
|
|
16
|
-
import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, universalImagePinned, UNIVERSAL_IMAGE, UNIVERSAL_IMAGE_DIGEST, UNIVERSAL_IMAGE_REPOSITORY, UNIVERSAL_IMAGE_SOURCE, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-
|
|
7
|
+
import { runExec, execCapture, waitForAgent } from './chunk-PHIQHIRJ.js';
|
|
8
|
+
import { GUEST_CID, linkVsockSockets } from './chunk-G4SOMWXL.js';
|
|
9
|
+
import { retrySend, describeCallFailure, keepStagedContext, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-PPQTTJSW.js';
|
|
10
|
+
import { runnerImageVersion } from './chunk-LBKCYEJT.js';
|
|
11
|
+
import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-6LS62EO4.js';
|
|
12
|
+
import { optionalEgress, runnerCredentialProblem, builtinKind, allowHostProblem, systemClock, emptyEgressCounts, hostAllowed } from './chunk-GXMMILQ4.js';
|
|
13
|
+
import { formatBytes, allocatedBytes } from './chunk-EGJY6MBC.js';
|
|
14
|
+
import { NETWORK_HELPER_MEMORY, createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, networkHelperName, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, mountableHome, homeCopyRunArgs, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, NETWORK_READY_FILE, spawnRun, identityRunArgs, parseIdentity, networkHelperRunArgs } from './chunk-AHWMY3MS.js';
|
|
15
|
+
import { RecipeError, DOCKER_FEATURE, universalImagePending, writeSanitizedRecipe, classifyProperties } from './chunk-CM4J53WZ.js';
|
|
16
|
+
import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, networkHelperPinned, NETWORK_HELPER_SHA256, universalImagePinned, UNIVERSAL_IMAGE, UNIVERSAL_IMAGE_DIGEST, UNIVERSAL_IMAGE_REPOSITORY, UNIVERSAL_IMAGE_SOURCE, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-D3CT6XQ4.js';
|
|
17
17
|
import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
|
|
18
|
-
import { postJson, WorkCommandError, getJson } from './chunk-
|
|
18
|
+
import { postJson, WorkCommandError, getJson } from './chunk-GJYGOFF3.js';
|
|
19
19
|
import { sanitizeTerminal } from './chunk-IXPH4EXK.js';
|
|
20
|
-
import { signerFor } from './chunk-
|
|
20
|
+
import { signerFor } from './chunk-VKYU4HHW.js';
|
|
21
21
|
import { sharedSkillNames, skillConflictMessage } from './chunk-FGF52V4V.js';
|
|
22
22
|
import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
|
|
23
23
|
import { MIN_SCRUBBED_LITERAL, setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-A6PJSNP6.js';
|
|
24
24
|
import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-XFJ7YOPD.js';
|
|
25
25
|
import { downconvertSession } from './chunk-DINRXUQA.js';
|
|
26
|
-
import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-
|
|
27
|
-
import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment,
|
|
26
|
+
import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-AJTGTSNA.js';
|
|
27
|
+
import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT, realFdStorePort } from './chunk-L2OARQKP.js';
|
|
28
28
|
import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, DOCKER_DESKTOP_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, JOIN_WAIT_MS, MAX_OPEN_STREAMS, STREAM_RESET_RATE, STREAM_RESET_BURST, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-MESOOLF4.js';
|
|
29
29
|
import { spawn, spawnSync } from 'child_process';
|
|
30
30
|
import { mkdirSync, existsSync, readFileSync, mkdtempSync, rmSync, chmodSync, truncateSync, statSync, accessSync, constants, readdirSync, writeFileSync, lstatSync, copyFileSync, renameSync, rmdirSync, unlinkSync, linkSync, openSync, closeSync, cpSync, writeSync, appendFileSync, createWriteStream, createReadStream } from 'fs';
|
|
@@ -166,9 +166,10 @@ function builderDiskPin(arch) {
|
|
|
166
166
|
return { url: `${BUILDER_DISK_BASE_URL}/builder-rootfs-${arch}.ext4`, sha256: BUILDER_DISK_SHA256[arch] };
|
|
167
167
|
}
|
|
168
168
|
var sha256Of = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
169
|
-
|
|
169
|
+
var MICROVM_STOPS = "no microVM build starts";
|
|
170
|
+
function pinProblem(file, expected, actual, where, stops = MICROVM_STOPS) {
|
|
170
171
|
const release = file.startsWith("vmlinux-") || file.startsWith("outerlayer-guest-") ? ` (guest assets release ${GUEST_ASSETS_VERSION})` : file.startsWith("builder-rootfs-") ? ` (builder root disk release ${BUILDER_DISK_VERSION})` : "";
|
|
171
|
-
return new AssetError(file, `${file} ${where} has sha256 ${actual}, not the ${expected} this release pins${release}, so
|
|
172
|
+
return new AssetError(file, `${file} ${where} has sha256 ${actual}, not the ${expected} this release pins${release}, so ${stops}`);
|
|
172
173
|
}
|
|
173
174
|
function writeAtomic(path, bytes, mode) {
|
|
174
175
|
const temp = `${path}.${process.pid}.tmp`;
|
|
@@ -189,16 +190,16 @@ function keptPath(dir, sha256, name) {
|
|
|
189
190
|
mkdirSync(join(dir, sha256), { recursive: true, mode: RUNNER_DIR_MODE });
|
|
190
191
|
return join(dir, sha256, name);
|
|
191
192
|
}
|
|
192
|
-
async function ensureFile(dir, file, pin, fetchImpl, mode) {
|
|
193
|
+
async function ensureFile(dir, file, pin, fetchImpl, mode, stops = MICROVM_STOPS) {
|
|
193
194
|
const path = keptPath(dir, pin.sha256, file);
|
|
194
195
|
if (existsSync(path)) {
|
|
195
196
|
const actual2 = sha256Of(readFileSync(path));
|
|
196
|
-
if (actual2 !== pin.sha256) throw pinProblem(file, pin.sha256, actual2, `at ${path}
|
|
197
|
+
if (actual2 !== pin.sha256) throw pinProblem(file, pin.sha256, actual2, `at ${path}`, stops);
|
|
197
198
|
return path;
|
|
198
199
|
}
|
|
199
200
|
const bytes = await download(file, pin.url, fetchImpl);
|
|
200
201
|
const actual = sha256Of(bytes);
|
|
201
|
-
if (actual !== pin.sha256) throw pinProblem(file, pin.sha256, actual, `downloaded from ${pin.url}
|
|
202
|
+
if (actual !== pin.sha256) throw pinProblem(file, pin.sha256, actual, `downloaded from ${pin.url}`, stops);
|
|
202
203
|
writeAtomic(path, bytes, mode);
|
|
203
204
|
return path;
|
|
204
205
|
}
|
|
@@ -282,6 +283,17 @@ async function ensureJailer(options) {
|
|
|
282
283
|
}
|
|
283
284
|
return jailer;
|
|
284
285
|
}
|
|
286
|
+
async function ensureNetworkHelper(options) {
|
|
287
|
+
const arch = options.arch ?? firecrackerArch(process.arch);
|
|
288
|
+
const file = `outerlayer-guest-${arch}`;
|
|
289
|
+
if (options.pin === void 0 && !networkHelperPinned(arch)) {
|
|
290
|
+
throw new AssetError(file, `no network helper is pinned for ${arch} in this release of the CLI, so container builds cannot start on this host`);
|
|
291
|
+
}
|
|
292
|
+
const pin = options.pin ?? { url: `${GUEST_ASSETS_BASE_URL}/${file}`, sha256: NETWORK_HELPER_SHA256[arch] };
|
|
293
|
+
const dir = vmAssetsDir(options.runnerDir);
|
|
294
|
+
mkdirSync(dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
295
|
+
return { path: await ensureFile(dir, file, pin, options.fetchImpl ?? fetch, 493, "no container build starts"), sha256: pin.sha256 };
|
|
296
|
+
}
|
|
285
297
|
async function ensureBuilderDisk(options) {
|
|
286
298
|
const arch = options.arch ?? firecrackerArch(process.arch);
|
|
287
299
|
if (!MICROVM_ARCHES.includes(arch)) throw new AssetError("builder-rootfs", `no builder root disk is pinned for ${arch}, so microVM image builds run on ${MICROVM_ARCHES.join(" or ")} hosts only`);
|
|
@@ -315,6 +327,10 @@ function createContainerHost(deps = {}) {
|
|
|
315
327
|
const result = await run("docker", ["info", "--format", "{{.OperatingSystem}}"]);
|
|
316
328
|
return result.status === 0 && result.stdout.trim() !== "" ? result.stdout.trim() : null;
|
|
317
329
|
},
|
|
330
|
+
async architecture() {
|
|
331
|
+
const result = await run("docker", ["version", "--format", "{{.Server.Arch}}"]);
|
|
332
|
+
return result.status === 0 && result.stdout.trim() !== "" ? result.stdout.trim() : null;
|
|
333
|
+
},
|
|
318
334
|
async imageConfig(imageId) {
|
|
319
335
|
const result = await run("docker", ["image", "inspect", "--format", "{{json .Config}}", imageId]);
|
|
320
336
|
return result.status === 0 ? parseImageConfig(result.stdout) : { user: "", env: {} };
|
|
@@ -369,6 +385,13 @@ function createContainerHost(deps = {}) {
|
|
|
369
385
|
},
|
|
370
386
|
remove(container) {
|
|
371
387
|
return run("docker", ["rm", "--force", "--volumes", container]);
|
|
388
|
+
},
|
|
389
|
+
logs(container, lines) {
|
|
390
|
+
return run("docker", ["logs", "--tail", String(lines), container]);
|
|
391
|
+
},
|
|
392
|
+
async oomKilled(container) {
|
|
393
|
+
const result = await run("docker", ["inspect", "--format", "{{.State.OOMKilled}}", container]);
|
|
394
|
+
return result.status === 0 && result.stdout.trim() === "true";
|
|
372
395
|
}
|
|
373
396
|
};
|
|
374
397
|
}
|
|
@@ -1279,6 +1302,7 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1279
1302
|
} else {
|
|
1280
1303
|
refusalKeys.add(key);
|
|
1281
1304
|
refusals.push({ host, address, range });
|
|
1305
|
+
if (range !== CONNECTION_RATE_RANGE && range !== OPEN_CONNECTIONS_RANGE) opts.log?.(`tunnel refused ${host} (${range === NOT_ALLOWED_RANGE ? "not in runner.build.allowHosts" : range})`);
|
|
1282
1306
|
}
|
|
1283
1307
|
persist();
|
|
1284
1308
|
};
|
|
@@ -1604,6 +1628,55 @@ ${body}`);
|
|
|
1604
1628
|
})
|
|
1605
1629
|
};
|
|
1606
1630
|
}
|
|
1631
|
+
var MAVEN_DIR = "maven";
|
|
1632
|
+
var MAVEN_SETTINGS_FILE = "settings.xml";
|
|
1633
|
+
var MAVEN_NO_PROXY_NOTE = "MAVEN_ARGS names its own global settings file, so the build's Maven gets no proxy from the runner";
|
|
1634
|
+
var MAVEN_SPACE_NOTE = "the build's directory has whitespace in its path, which Maven cannot read from MAVEN_ARGS, so its Maven gets no proxy from the runner";
|
|
1635
|
+
function namesGlobalSettings(args) {
|
|
1636
|
+
return args.split(/\s+/).some((token) => token === "--global-settings" || token.startsWith("--global-settings=") || token === "-gs" || token.startsWith("-gs="));
|
|
1637
|
+
}
|
|
1638
|
+
function escapeXml(text) {
|
|
1639
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1640
|
+
}
|
|
1641
|
+
function mavenSettingsXml(proxyUrl, noProxy) {
|
|
1642
|
+
const url = new URL(proxyUrl);
|
|
1643
|
+
const host = escapeXml(url.hostname.replace(/^\[|\]$/g, ""));
|
|
1644
|
+
const nonProxyHosts = escapeXml(noProxy.split(",").filter((entry) => entry !== "").join("|"));
|
|
1645
|
+
const proxy = (protocol) => [
|
|
1646
|
+
" <proxy>",
|
|
1647
|
+
` <id>outerlayer-${protocol}</id>`,
|
|
1648
|
+
" <active>true</active>",
|
|
1649
|
+
` <protocol>${protocol}</protocol>`,
|
|
1650
|
+
` <host>${host}</host>`,
|
|
1651
|
+
` <port>${url.port}</port>`,
|
|
1652
|
+
` <nonProxyHosts>${nonProxyHosts}</nonProxyHosts>`,
|
|
1653
|
+
" </proxy>"
|
|
1654
|
+
].join("\n");
|
|
1655
|
+
return [
|
|
1656
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
1657
|
+
'<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0">',
|
|
1658
|
+
" <proxies>",
|
|
1659
|
+
proxy("http"),
|
|
1660
|
+
proxy("https"),
|
|
1661
|
+
" </proxies>",
|
|
1662
|
+
"</settings>",
|
|
1663
|
+
""
|
|
1664
|
+
].join("\n");
|
|
1665
|
+
}
|
|
1666
|
+
function writeMavenSettings(buildDir2, proxyUrl, noProxy) {
|
|
1667
|
+
const dir = join(buildDir2, MAVEN_DIR);
|
|
1668
|
+
mkdirSync(dir, { recursive: true });
|
|
1669
|
+
const file = join(dir, MAVEN_SETTINGS_FILE);
|
|
1670
|
+
writeFileSync(file, mavenSettingsXml(proxyUrl, noProxy));
|
|
1671
|
+
return file;
|
|
1672
|
+
}
|
|
1673
|
+
function mavenArgs(settingsFile, team) {
|
|
1674
|
+
const own = team?.trim() ?? "";
|
|
1675
|
+
if (own !== "" && namesGlobalSettings(own)) return { value: team, skipped: true };
|
|
1676
|
+
return { value: own === "" ? `--global-settings ${settingsFile}` : `--global-settings ${settingsFile} ${own}`, skipped: false };
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
// src/runner/host-hooks.ts
|
|
1607
1680
|
function provisionEnvironment(base, input) {
|
|
1608
1681
|
return {
|
|
1609
1682
|
...base,
|
|
@@ -1764,8 +1837,8 @@ async function deliverMavenSettings(build, workdir, base, run, timeoutMs = MAVEN
|
|
|
1764
1837
|
const env = { ...base, ...execProxyEnvironment(build) };
|
|
1765
1838
|
const ran = await run(build.exec, execArgv(workdir, ["/bin/sh", "-c", WRITE_MAVEN_SETTINGS, "sh", mavenSettingsXml(env.HTTPS_PROXY, env.NO_PROXY)]), env, timeoutMs);
|
|
1766
1839
|
if (ran.error !== void 0) return { reason: describeCallFailure(ran.error) };
|
|
1767
|
-
const
|
|
1768
|
-
if (ran.status !== 0) return { reason: `the write exited ${ran.status ?? ran.signal}${
|
|
1840
|
+
const said2 = ran.stderr.trim().split("\n")[0];
|
|
1841
|
+
if (ran.status !== 0) return { reason: `the write exited ${ran.status ?? ran.signal}${said2 === "" ? "" : `: ${said2}`}` };
|
|
1769
1842
|
const lines = ran.stdout.trim().split("\n");
|
|
1770
1843
|
const path = lines[lines.length - 1].trim();
|
|
1771
1844
|
if (!isAbsolute(path)) return { reason: "the write did not report an absolute path" };
|
|
@@ -2894,6 +2967,15 @@ function lifecycleFailureReason(step, exitCode) {
|
|
|
2894
2967
|
return `lifecycle command ${step.name} (${step.source}) exited ${exitCode}`;
|
|
2895
2968
|
}
|
|
2896
2969
|
|
|
2970
|
+
// src/runner/command-output.ts
|
|
2971
|
+
function firstLine4(text) {
|
|
2972
|
+
return text.trim().split("\n")[0] ?? "";
|
|
2973
|
+
}
|
|
2974
|
+
function said(output) {
|
|
2975
|
+
const line2 = firstLine4(output);
|
|
2976
|
+
return line2 === "" ? "" : `: ${line2}`;
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2897
2979
|
// src/runner/runtimes.ts
|
|
2898
2980
|
var RUNTIMES = ["node", "python", "go", "rust", "ruby", "java"];
|
|
2899
2981
|
var MANIFESTS = {
|
|
@@ -2910,10 +2992,6 @@ var MANIFESTS = {
|
|
|
2910
2992
|
var IMAGE_CONFIG = "/etc/mise/config.toml";
|
|
2911
2993
|
var RUST_PIN_FILES = ["rust-toolchain.toml", "rust-toolchain"];
|
|
2912
2994
|
var REFUSALS_NAMED2 = 3;
|
|
2913
|
-
var PLAIN = { withoutProxyWarning: true };
|
|
2914
|
-
function firstLine4(text) {
|
|
2915
|
-
return text.trim().split("\n")[0] ?? "";
|
|
2916
|
-
}
|
|
2917
2995
|
function toolFailure(stderr) {
|
|
2918
2996
|
for (const l of stderr.split("\n")) {
|
|
2919
2997
|
if (/^\S+@\S+: /.test(l)) return l;
|
|
@@ -2939,7 +3017,7 @@ function parseListing(stdout) {
|
|
|
2939
3017
|
}
|
|
2940
3018
|
}
|
|
2941
3019
|
async function listing(context) {
|
|
2942
|
-
const ran = await context.input.exec(["mise", "ls", "--current", "--json"], context.path, { quiet: true
|
|
3020
|
+
const ran = await context.input.exec(["mise", "ls", "--current", "--json"], context.path, { quiet: true });
|
|
2943
3021
|
return ran.status === 0 ? parseListing(ran.stdout) : void 0;
|
|
2944
3022
|
}
|
|
2945
3023
|
function refusalNote(context) {
|
|
@@ -2952,10 +3030,10 @@ function line(context, text) {
|
|
|
2952
3030
|
var installWithMise = async (context) => {
|
|
2953
3031
|
const { input, entry, path } = context;
|
|
2954
3032
|
context.before = await listing(context) ?? [];
|
|
2955
|
-
const installed = await input.exec(["mise", "install"], path
|
|
3033
|
+
const installed = await input.exec(["mise", "install"], path);
|
|
2956
3034
|
if (installed.status !== 0) {
|
|
2957
3035
|
const missing = context.before.filter((r) => !r.installed).map((r) => `${r.tool} ${r.version} (from ${describeSource(r.source, path)})`);
|
|
2958
|
-
const what = missing.length === 0 ? `mise install failed in ${entry.repository} (exit ${installed.status})${
|
|
3036
|
+
const what = missing.length === 0 ? `mise install failed in ${entry.repository} (exit ${installed.status})${said(installed.stderr)}` : `mise could not install ${missing.join(", ")} in ${entry.repository} (exit ${installed.status})${toolFailure(installed.stderr) === "" ? "" : `: ${toolFailure(installed.stderr)}`}`;
|
|
2959
3037
|
return `runtime_install_failed: ${what}${refusalNote(context)}`;
|
|
2960
3038
|
}
|
|
2961
3039
|
const after = await listing(context);
|
|
@@ -2967,7 +3045,7 @@ var installWithMise = async (context) => {
|
|
|
2967
3045
|
var goToolchain = async (context) => {
|
|
2968
3046
|
if (!context.files.has("go.mod")) return void 0;
|
|
2969
3047
|
const ran = await context.input.exec(["go", "version"], context.path);
|
|
2970
|
-
if (ran.status !== 0) return `runtime_install_failed: go version failed in ${context.entry.repository} (exit ${ran.status})${
|
|
3048
|
+
if (ran.status !== 0) return `runtime_install_failed: go version failed in ${context.entry.repository} (exit ${ran.status})${said(ran.stderr)}${refusalNote(context)}`;
|
|
2971
3049
|
const version = /\bgo(\d+\.\d+(?:\.\d+)?\S*)/.exec(ran.stdout)?.[1];
|
|
2972
3050
|
line(context, `go ${version ?? firstLine4(ran.stdout)} from go.mod`);
|
|
2973
3051
|
return void 0;
|
|
@@ -2976,7 +3054,7 @@ var rustToolchain = async (context) => {
|
|
|
2976
3054
|
const pin = RUST_PIN_FILES.find((file) => context.files.has(file));
|
|
2977
3055
|
if (pin === void 0) return void 0;
|
|
2978
3056
|
const ran = await context.input.exec(["rustc", "--version"], context.path);
|
|
2979
|
-
if (ran.status !== 0) return `runtime_install_failed: rustc --version failed in ${context.entry.repository} (exit ${ran.status})${
|
|
3057
|
+
if (ran.status !== 0) return `runtime_install_failed: rustc --version failed in ${context.entry.repository} (exit ${ran.status})${said(ran.stderr)}${refusalNote(context)}`;
|
|
2980
3058
|
const version = /\brustc (\S+)/.exec(ran.stdout)?.[1];
|
|
2981
3059
|
line(context, `rust ${version ?? firstLine4(ran.stdout)} from ${pin}`);
|
|
2982
3060
|
return void 0;
|
|
@@ -2991,7 +3069,6 @@ function unpinnedIn(context) {
|
|
|
2991
3069
|
}
|
|
2992
3070
|
async function provisionRuntimes(input) {
|
|
2993
3071
|
const unpinned = {};
|
|
2994
|
-
let dropProxyWarning = false;
|
|
2995
3072
|
for (const entry of input.repositories) {
|
|
2996
3073
|
if (input.aborted?.() === true) return { ok: false, reason: "", aborted: true };
|
|
2997
3074
|
const path = checkoutPath(entry);
|
|
@@ -3010,13 +3087,8 @@ async function provisionRuntimes(input) {
|
|
|
3010
3087
|
if (reason !== void 0) return { ok: false, reason };
|
|
3011
3088
|
}
|
|
3012
3089
|
unpinned[entry.repository] = unpinnedIn(context);
|
|
3013
|
-
const old = context.resolved.find((r) => r.tool === "node" && !nodeAcceptsProxyWarningFlag(r.version));
|
|
3014
|
-
if (old !== void 0) {
|
|
3015
|
-
dropProxyWarning = true;
|
|
3016
|
-
line(context, `leaving ${PROXY_WARNING_FLAG} out of NODE_OPTIONS because node ${old.version} does not accept it`);
|
|
3017
|
-
}
|
|
3018
3090
|
}
|
|
3019
|
-
return { ok: true, unpinned
|
|
3091
|
+
return { ok: true, unpinned };
|
|
3020
3092
|
}
|
|
3021
3093
|
function runtimeStepInput(report, services) {
|
|
3022
3094
|
return report.base === void 0 ? {} : { runtimes: { refusals: () => services.record().refusals } };
|
|
@@ -3027,20 +3099,6 @@ function keepUnpinnedRuntimes(state, steps) {
|
|
|
3027
3099
|
|
|
3028
3100
|
// src/runner/build-steps.ts
|
|
3029
3101
|
var aborted = () => ({ ok: false, reason: "", aborted: true });
|
|
3030
|
-
function firstLine5(text) {
|
|
3031
|
-
return text.trim().split("\n")[0] ?? "";
|
|
3032
|
-
}
|
|
3033
|
-
async function nodeRejectsProxyWarningFlag(repositories, exec, log, tag) {
|
|
3034
|
-
for (const entry of repositories) {
|
|
3035
|
-
const ran = await exec(["node", "--version"], checkoutPath(entry), { quiet: true, withoutProxyWarning: true });
|
|
3036
|
-
if (ran.status !== 0) continue;
|
|
3037
|
-
const version = firstLine5(ran.stdout);
|
|
3038
|
-
if (nodeAcceptsProxyWarningFlag(version)) continue;
|
|
3039
|
-
log.line(`${tag} ${entry.repository}: leaving ${PROXY_WARNING_FLAG} out of NODE_OPTIONS because node ${version} does not accept it`);
|
|
3040
|
-
return true;
|
|
3041
|
-
}
|
|
3042
|
-
return false;
|
|
3043
|
-
}
|
|
3044
3102
|
function gitErrorLine(text) {
|
|
3045
3103
|
const lines = text.split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
3046
3104
|
return lines.find((line2) => /^(fatal|error):/.test(line2)) ?? lines.at(-1) ?? "";
|
|
@@ -3059,7 +3117,7 @@ var DELIVER_SCRIPT = [
|
|
|
3059
3117
|
var RECORD_SCRIPT = 'd="$(git rev-parse --git-common-dir)" && mkdir -p "$d/outerlayer" && printf "%s" "$1" > "$d/outerlayer/delivery.json"';
|
|
3060
3118
|
var WRITE_SHIM_SCRIPT = 'mkdir -p "$1" && printf "%s" "$2" > "$1/claude" && chmod 755 "$1/claude"';
|
|
3061
3119
|
function failure(what, result) {
|
|
3062
|
-
return `context_delivery_failed: ${what} (exit ${result.status})${
|
|
3120
|
+
return `context_delivery_failed: ${what} (exit ${result.status})${said(result.stderr)}`;
|
|
3063
3121
|
}
|
|
3064
3122
|
async function repositorySkills(input, folder) {
|
|
3065
3123
|
const listed = await input.exec(["ls", "-1", folder], CHECKOUT_DIR, { quiet: true });
|
|
@@ -3162,14 +3220,11 @@ async function runBuildSteps(input) {
|
|
|
3162
3220
|
}
|
|
3163
3221
|
if (input.governing !== void 0) await noteIgnoredDevcontainers(input, repositories, input.governing.repository);
|
|
3164
3222
|
let unpinnedRuntimes;
|
|
3165
|
-
const ordered = [{ ...primary, primary: true }, ...repositories.filter((candidate) => candidate.repository !== primary.repository).map((entry) => ({ ...entry, primary: false }))];
|
|
3166
3223
|
if (input.runtimes !== void 0) {
|
|
3224
|
+
const ordered = [{ ...primary, primary: true }, ...repositories.filter((candidate) => candidate.repository !== primary.repository).map((entry) => ({ ...entry, primary: false }))];
|
|
3167
3225
|
const chosen = await provisionRuntimes({ repositories: ordered, exec, log, tag, refusals: input.runtimes.refusals, aborted: input.aborted });
|
|
3168
3226
|
if (!chosen.ok) return chosen.aborted === true ? aborted() : { ok: false, reason: chosen.reason };
|
|
3169
3227
|
unpinnedRuntimes = chosen.unpinned;
|
|
3170
|
-
if (chosen.dropProxyWarning) input.dropProxyWarning?.();
|
|
3171
|
-
} else if (input.dropProxyWarning !== void 0 && await nodeRejectsProxyWarningFlag(ordered, exec, log, tag)) {
|
|
3172
|
-
input.dropProxyWarning();
|
|
3173
3228
|
}
|
|
3174
3229
|
const lifecycleDir = lifecycleWorkdir(repositories, input.governing?.repository);
|
|
3175
3230
|
for (const step of lifecycleSteps(input.lifecycle)) {
|
|
@@ -3224,7 +3279,7 @@ var MAX_TRANSCRIPTS = 500;
|
|
|
3224
3279
|
var MAX_TOTAL_TRANSCRIPT_BYTES = 64 * 1024 * 1024;
|
|
3225
3280
|
var TRANSCRIPT_COPY_MS = 2 * 60 * 1e3;
|
|
3226
3281
|
var BUILD_HOME = "/build/home";
|
|
3227
|
-
function
|
|
3282
|
+
function firstLine5(text) {
|
|
3228
3283
|
return text.trim().split("\n")[0] ?? "";
|
|
3229
3284
|
}
|
|
3230
3285
|
async function copyTranscripts(run, now = Date.now) {
|
|
@@ -3236,7 +3291,7 @@ async function copyTranscripts(run, now = Date.now) {
|
|
|
3236
3291
|
return { ok: false, reason: describeCallFailure(err) };
|
|
3237
3292
|
}
|
|
3238
3293
|
if (listed.status !== 0 && !/No such file or directory/.test(listed.stderr)) {
|
|
3239
|
-
return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${
|
|
3294
|
+
return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${firstLine5(listed.stderr) === "" ? "" : `: ${firstLine5(listed.stderr)}`}` };
|
|
3240
3295
|
}
|
|
3241
3296
|
const paths = listed.stdout.split("\0").filter((entry) => entry.startsWith(`${TRANSCRIPT_ROOT}/`) && !entry.includes("\n") && !entry.slice(TRANSCRIPT_ROOT.length + 1).split("/").includes("..")).map((entry) => entry.slice(TRANSCRIPT_ROOT.length + 1)).sort();
|
|
3242
3297
|
const copied = [];
|
|
@@ -3253,7 +3308,7 @@ async function copyTranscripts(run, now = Date.now) {
|
|
|
3253
3308
|
}
|
|
3254
3309
|
try {
|
|
3255
3310
|
const read = await run(["head", "-c", String(MAX_TRANSCRIPT_BYTES + 1), `${TRANSCRIPT_ROOT}/${path}`]);
|
|
3256
|
-
if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${
|
|
3311
|
+
if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${firstLine5(read.stderr) === "" ? "" : `: ${firstLine5(read.stderr)}`}` });
|
|
3257
3312
|
else if (Buffer.byteLength(read.stdout) > MAX_TRANSCRIPT_BYTES) missed.push({ path, reason: `it is larger than ${MAX_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
|
|
3258
3313
|
else if (total + Buffer.byteLength(read.stdout) > MAX_TOTAL_TRANSCRIPT_BYTES) missed.push({ path, reason: `copying it would take the transcripts past ${MAX_TOTAL_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
|
|
3259
3314
|
else {
|
|
@@ -3708,7 +3763,6 @@ var RECEIVE_ARGV = ["/opt/outerlayer/bin/node", "/opt/outerlayer/cli/dist/index.
|
|
|
3708
3763
|
var REASON_LINE_MAX = 240;
|
|
3709
3764
|
var STEPS = {
|
|
3710
3765
|
gh: "the build's gh configuration",
|
|
3711
|
-
maven: "the build's Maven settings",
|
|
3712
3766
|
"git-hooks": "the commit hooks",
|
|
3713
3767
|
context: "the staged context",
|
|
3714
3768
|
"eval-input": "the checks' input"
|
|
@@ -4359,6 +4413,67 @@ function createCpuAllocator(cores) {
|
|
|
4359
4413
|
}
|
|
4360
4414
|
};
|
|
4361
4415
|
}
|
|
4416
|
+
var NETWORK_READY_ATTEMPTS = 60;
|
|
4417
|
+
var NETWORK_READY_PAUSE_MS = 500;
|
|
4418
|
+
var LOG_LINES = 20;
|
|
4419
|
+
async function helperReason(runtime, name) {
|
|
4420
|
+
const logs = await runtime.host.logs(name, LOG_LINES);
|
|
4421
|
+
const lines = `${logs.stdout}
|
|
4422
|
+
${logs.stderr}`.split("\n").map((line2) => line2.trim());
|
|
4423
|
+
return lines.filter((line2) => line2.startsWith("net: ")).at(-1) ?? lines.filter((line2) => line2 !== "").at(-1) ?? "";
|
|
4424
|
+
}
|
|
4425
|
+
async function waitForNetwork(runtime, name) {
|
|
4426
|
+
for (let attempt = 0; attempt < NETWORK_READY_ATTEMPTS; attempt++) {
|
|
4427
|
+
const probe = await runtime.host.exec({ container: name, user: "0:0", env: { literals: {}, passed: {} }, argv: ["cat", NETWORK_READY_FILE] });
|
|
4428
|
+
if (probe.status === 0) return void 0;
|
|
4429
|
+
const state = await runtime.host.state(name);
|
|
4430
|
+
if (state === "stopped" || state === "missing") {
|
|
4431
|
+
return `the build's network helper container stopped before its network was ready${said(await helperReason(runtime, name))}`;
|
|
4432
|
+
}
|
|
4433
|
+
await runtime.sleep(NETWORK_READY_PAUSE_MS);
|
|
4434
|
+
}
|
|
4435
|
+
return `the build's network helper container was not ready within ${NETWORK_READY_ATTEMPTS * NETWORK_READY_PAUSE_MS / 1e3} seconds${said(await helperReason(runtime, name))}`;
|
|
4436
|
+
}
|
|
4437
|
+
async function startNetworkHelper(runtime, input, logPath) {
|
|
4438
|
+
const started = await runtime.host.run(networkHelperRunArgs(input), { logPath });
|
|
4439
|
+
if (started.status !== 0) {
|
|
4440
|
+
return `starting the build's network helper container failed (exit ${started.status})${said(started.stderr)}`;
|
|
4441
|
+
}
|
|
4442
|
+
return waitForNetwork(runtime, input.name);
|
|
4443
|
+
}
|
|
4444
|
+
async function ensureNetworkReady(runtime, state) {
|
|
4445
|
+
if (state.network === void 0) return void 0;
|
|
4446
|
+
const current = await runtime.host.state(state.network);
|
|
4447
|
+
if (current === "running") return void 0;
|
|
4448
|
+
if (current === "missing") return `the build's network helper container ${state.network} is gone`;
|
|
4449
|
+
const started = await runtime.host.start(state.network);
|
|
4450
|
+
if (started.status !== 0) {
|
|
4451
|
+
return `starting the build's network helper container again failed (exit ${started.status})${said(started.stderr)}`;
|
|
4452
|
+
}
|
|
4453
|
+
return waitForNetwork(runtime, state.network);
|
|
4454
|
+
}
|
|
4455
|
+
async function stoppedHelperReason(runtime, name) {
|
|
4456
|
+
if (await runtime.host.oomKilled(name)) return `the build's network helper container ran out of memory (${NETWORK_HELPER_MEMORY})`;
|
|
4457
|
+
return `the build's network helper container stopped${said(await helperReason(runtime, name))}`;
|
|
4458
|
+
}
|
|
4459
|
+
async function removeNetworkHelper(runtime, state) {
|
|
4460
|
+
if (state.network === void 0) return void 0;
|
|
4461
|
+
const removed = await runtime.host.remove(state.network);
|
|
4462
|
+
if (removed.status !== 0 && !/no such container/i.test(removed.stderr)) return `container ${state.network} was not removed: ${removed.stderr.trim()}`;
|
|
4463
|
+
return void 0;
|
|
4464
|
+
}
|
|
4465
|
+
function kernelHasIpv6(exists = existsSync, platform = process.platform) {
|
|
4466
|
+
return platform !== "linux" || exists("/proc/sys/net/ipv6");
|
|
4467
|
+
}
|
|
4468
|
+
function helperArchOf(engineArch) {
|
|
4469
|
+
if (engineArch === "amd64") return "x86_64";
|
|
4470
|
+
if (engineArch === "arm64") return "aarch64";
|
|
4471
|
+
return engineArch;
|
|
4472
|
+
}
|
|
4473
|
+
async function engineNetworkHelper(host, runnerDir2, ensure = ensureNetworkHelper) {
|
|
4474
|
+
const engine = await host.architecture();
|
|
4475
|
+
return ensure({ runnerDir: runnerDir2, ...engine === null ? {} : { arch: helperArchOf(engine) } });
|
|
4476
|
+
}
|
|
4362
4477
|
|
|
4363
4478
|
// src/runner/container/lease-channel.ts
|
|
4364
4479
|
var LEASE_SECONDS = 900;
|
|
@@ -4409,8 +4524,9 @@ function createContainerRuntime(opts = {}) {
|
|
|
4409
4524
|
const { cli, remoteFor } = opts;
|
|
4410
4525
|
const vm = createMicroVmPorts(opts.vm);
|
|
4411
4526
|
const sleep = opts.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
4527
|
+
const host = opts.host ?? createContainerHost();
|
|
4412
4528
|
return {
|
|
4413
|
-
host
|
|
4529
|
+
host,
|
|
4414
4530
|
cpus: opts.cpus ?? createCpuAllocator(usableCpus()),
|
|
4415
4531
|
tunnels: opts.tunnels ?? /* @__PURE__ */ new Map(),
|
|
4416
4532
|
relays: opts.relays ?? /* @__PURE__ */ new Map(),
|
|
@@ -4446,7 +4562,9 @@ function createContainerRuntime(opts = {}) {
|
|
|
4446
4562
|
destinationOptions: opts.destinationOptions,
|
|
4447
4563
|
claudeUpstream: opts.claudeUpstream,
|
|
4448
4564
|
vm,
|
|
4449
|
-
cliBuild: () => cli ?? currentCliBuild()
|
|
4565
|
+
cliBuild: () => cli ?? currentCliBuild(),
|
|
4566
|
+
networkHelper: opts.networkHelper ?? ((dir) => engineNetworkHelper(host, dir)),
|
|
4567
|
+
ipv6: opts.ipv6 ?? kernelHasIpv6()
|
|
4450
4568
|
};
|
|
4451
4569
|
}
|
|
4452
4570
|
var REPORT_READ_TIMEOUT_MS = 6e4;
|
|
@@ -4509,9 +4627,6 @@ function gitRemoteFor(runtime, input) {
|
|
|
4509
4627
|
...input.readOnly === true ? { readOnly: true } : {}
|
|
4510
4628
|
});
|
|
4511
4629
|
}
|
|
4512
|
-
function firstLine7(text) {
|
|
4513
|
-
return text.trim().split("\n")[0] ?? "";
|
|
4514
|
-
}
|
|
4515
4630
|
var NO_ENV = { literals: {}, passed: {} };
|
|
4516
4631
|
function transportOf(state) {
|
|
4517
4632
|
const recorded = state.transport;
|
|
@@ -4640,6 +4755,12 @@ async function provisionContainer(input) {
|
|
|
4640
4755
|
if (unfetched !== void 0) return fail(unfetched);
|
|
4641
4756
|
}
|
|
4642
4757
|
const imageRepository = governingSource.kind === "governed" ? governingSource.repository : repository;
|
|
4758
|
+
let networkHelper;
|
|
4759
|
+
try {
|
|
4760
|
+
networkHelper = await runtime.networkHelper(runnerDir(config.configPath));
|
|
4761
|
+
} catch (err) {
|
|
4762
|
+
return fail(err instanceof AssetError ? err.message : `the network helper could not be had: ${describeCallFailure(err)}`);
|
|
4763
|
+
}
|
|
4643
4764
|
const obtained = await obtainImage({
|
|
4644
4765
|
config,
|
|
4645
4766
|
runtime,
|
|
@@ -4651,7 +4772,8 @@ async function provisionContainer(input) {
|
|
|
4651
4772
|
log,
|
|
4652
4773
|
aborted: input.aborted,
|
|
4653
4774
|
deadlineMs: input.deadlineMs,
|
|
4654
|
-
now: input.now
|
|
4775
|
+
now: input.now,
|
|
4776
|
+
guestHelper: networkHelper
|
|
4655
4777
|
});
|
|
4656
4778
|
if (!obtained.ok) return obtained.aborted === true ? { ok: false, reason: obtained.reason, aborted: true } : fail(obtained.reason);
|
|
4657
4779
|
const built = obtained.built;
|
|
@@ -4711,7 +4833,7 @@ async function provisionContainer(input) {
|
|
|
4711
4833
|
}
|
|
4712
4834
|
return aborted2 ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(reason);
|
|
4713
4835
|
};
|
|
4714
|
-
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${
|
|
4836
|
+
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${said(result.stderr)}`);
|
|
4715
4837
|
if (input.aborted()) return bail("", true);
|
|
4716
4838
|
mkdirSync(buildDir2, { recursive: true });
|
|
4717
4839
|
const ghDir = ghConfigDir(buildDir2);
|
|
@@ -4724,11 +4846,6 @@ async function provisionContainer(input) {
|
|
|
4724
4846
|
err instanceof WorkCommandError ? `the build's read token could not be had: ${refusalCode(err)}` : `the build's gh configuration could not be written: ${describeCallFailure(err)}`
|
|
4725
4847
|
);
|
|
4726
4848
|
}
|
|
4727
|
-
try {
|
|
4728
|
-
writeBuildMavenSettings(buildDir2);
|
|
4729
|
-
} catch (err) {
|
|
4730
|
-
return bail(`the build's Maven settings could not be written: ${describeCallFailure(err)}`);
|
|
4731
|
-
}
|
|
4732
4849
|
for (const entry of repositories) {
|
|
4733
4850
|
if (entry.repository === primary.repository) continue;
|
|
4734
4851
|
try {
|
|
@@ -4768,12 +4885,23 @@ async function provisionContainer(input) {
|
|
|
4768
4885
|
};
|
|
4769
4886
|
const prepared = await host.run(prepareRunArgs(runInput), { logPath });
|
|
4770
4887
|
if (prepared.status !== 0) return dockerFailed("preparing the build's volume", prepared);
|
|
4771
|
-
const
|
|
4888
|
+
const imageConfig = await host.imageConfig(report.imageId);
|
|
4889
|
+
const resolved = await resolveBuildUser(runtime, runInput, { remoteUser: report.apply.remoteUser, imageUser: imageConfig.user }, logPath);
|
|
4890
|
+
if (!resolved.ok) return bail(resolved.reason);
|
|
4891
|
+
state.agentUser = resolved.user;
|
|
4892
|
+
if (resolved.home !== void 0) state.home = resolved.home;
|
|
4893
|
+
const agentUser = resolved.user;
|
|
4894
|
+
state.network = networkHelperName(name);
|
|
4895
|
+
input.save(state, environment);
|
|
4896
|
+
const notReady = await startNetworkHelper(runtime, { name: state.network, buildId, runnerId, image: report.imageId, limits: limits2, ipv6: runtime.ipv6 }, logPath);
|
|
4897
|
+
if (notReady !== void 0) return bail(notReady);
|
|
4898
|
+
if (input.aborted()) return bail("", true);
|
|
4899
|
+
const started = await host.run(containerRunArgs({ ...runInput, network: state.network, home: state.home }), { logPath });
|
|
4772
4900
|
if (started.status !== 0) return dockerFailed("starting the build's container", started);
|
|
4773
4901
|
joinBuild(runtime, state, services, (line2) => log.line(`${tag} ${line2}`));
|
|
4774
4902
|
if (input.aborted()) return bail("", true);
|
|
4775
4903
|
if (!await waitForRelay(runtime, state)) return bail("the relay in the build's container did not start");
|
|
4776
|
-
const ghDelivered = await deliverJobFiles(runtime, state, ["gh"
|
|
4904
|
+
const ghDelivered = await deliverJobFiles(runtime, state, ["gh"], secrets);
|
|
4777
4905
|
if (!ghDelivered.ok) return bail(ghDelivered.reason);
|
|
4778
4906
|
keepGhConfigCurrent(tokens, buildDir2, (err) => log.error(`${tag} the read token could not be written for gh: ${describeCallFailure(err)}`), {
|
|
4779
4907
|
runtime,
|
|
@@ -4782,24 +4910,6 @@ async function provisionContainer(input) {
|
|
|
4782
4910
|
delivered: readToken,
|
|
4783
4911
|
onFailure: (reason) => log.error(`${tag} ${reason}`)
|
|
4784
4912
|
});
|
|
4785
|
-
const imageConfig = await host.imageConfig(report.imageId);
|
|
4786
|
-
state.imageEnv = imageConfig.env;
|
|
4787
|
-
let agentUser;
|
|
4788
|
-
try {
|
|
4789
|
-
agentUser = await resolveAgentUser({
|
|
4790
|
-
remoteUser: report.apply.remoteUser,
|
|
4791
|
-
imageUser: imageConfig.user,
|
|
4792
|
-
probe: async (user) => {
|
|
4793
|
-
const probe = await host.exec({ container: name, user: ADDED_USER, env: NO_ENV, argv: ["id", "-u", user] });
|
|
4794
|
-
const uid = Number(probe.stdout);
|
|
4795
|
-
return probe.status === 0 && Number.isInteger(uid) ? uid : null;
|
|
4796
|
-
}
|
|
4797
|
-
});
|
|
4798
|
-
} catch (err) {
|
|
4799
|
-
if (err instanceof AgentUserError) return bail(err.message);
|
|
4800
|
-
throw err;
|
|
4801
|
-
}
|
|
4802
|
-
state.agentUser = agentUser;
|
|
4803
4913
|
const tools = await host.exec({ container: name, user: ADDED_USER, env: NO_ENV, argv: ["cat", "/opt/outerlayer/tools.json"] });
|
|
4804
4914
|
const agentVersion = agentVersionOf(tools.status === 0 ? tools.stdout : "");
|
|
4805
4915
|
environment.agentVersion = agentVersion;
|
|
@@ -4807,10 +4917,7 @@ async function provisionContainer(input) {
|
|
|
4807
4917
|
const hashed = program.status === 0 ? parseProgramHash(program.stdout) : void 0;
|
|
4808
4918
|
if (hashed !== void 0) state.judgeProgram = { path: JUDGE_PROGRAM, sha256: hashed };
|
|
4809
4919
|
input.save(state, environment);
|
|
4810
|
-
|
|
4811
|
-
for (const notice of execEnv.notices) log.line(`${tag} ${notice}`);
|
|
4812
|
-
const plainEnv = buildEnvironment({ ...envInput, imageEnv: state.imageEnv, proxyWarning: false });
|
|
4813
|
-
const exec = (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env: opts?.withoutProxyWarning === true ? plainEnv : execEnv, argv }, opts?.quiet === true ? void 0 : { logPath });
|
|
4920
|
+
const exec = (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env, argv }, opts?.quiet === true ? void 0 : { logPath });
|
|
4814
4921
|
const steps = await runBuildSteps({
|
|
4815
4922
|
repository,
|
|
4816
4923
|
branch: primary.branch,
|
|
@@ -4843,11 +4950,7 @@ async function provisionContainer(input) {
|
|
|
4843
4950
|
keepIn: jobDir,
|
|
4844
4951
|
...input.requireBuildSkill === true ? { requireBuildSkill: true } : {},
|
|
4845
4952
|
// A repository with no devcontainer file builds on the universal image, whose runtimes the build chooses and installs.
|
|
4846
|
-
...runtimeStepInput(report, services)
|
|
4847
|
-
dropProxyWarning: () => {
|
|
4848
|
-
state.proxyWarningDropped = true;
|
|
4849
|
-
execEnv = plainEnv;
|
|
4850
|
-
}
|
|
4953
|
+
...runtimeStepInput(report, services)
|
|
4851
4954
|
});
|
|
4852
4955
|
if (!steps.ok) return bail(steps.reason, steps.aborted === true);
|
|
4853
4956
|
state.startCommit = steps.startCommit;
|
|
@@ -4855,6 +4958,37 @@ async function provisionContainer(input) {
|
|
|
4855
4958
|
if (steps.controlPlane !== void 0) environment.controlPlane = steps.controlPlane;
|
|
4856
4959
|
return { ok: true, workdir: CHECKOUT_DIR, state, environment };
|
|
4857
4960
|
}
|
|
4961
|
+
async function resolveBuildUser(runtime, runInput, named, logPath) {
|
|
4962
|
+
const lookups = /* @__PURE__ */ new Map();
|
|
4963
|
+
const lookup2 = async (user2) => {
|
|
4964
|
+
const known = lookups.get(user2);
|
|
4965
|
+
if (known !== void 0) return known;
|
|
4966
|
+
const ran = await runtime.host.run(identityRunArgs({ ...runInput, user: ADDED_USER }, user2));
|
|
4967
|
+
const found = parseIdentity(ran.stdout);
|
|
4968
|
+
if (ran.status !== 0 || found === void 0) {
|
|
4969
|
+
throw new AgentUserError(`reading the build's user from the image failed (exit ${ran.status})${said(ran.stderr)}`);
|
|
4970
|
+
}
|
|
4971
|
+
lookups.set(user2, found);
|
|
4972
|
+
return found;
|
|
4973
|
+
};
|
|
4974
|
+
let user;
|
|
4975
|
+
let home;
|
|
4976
|
+
try {
|
|
4977
|
+
user = await resolveAgentUser({ ...named, probe: async (name) => (await lookup2(name))?.uid ?? null });
|
|
4978
|
+
home = user === ADDED_USER ? void 0 : mountableHome((await lookup2(user))?.home);
|
|
4979
|
+
} catch (err) {
|
|
4980
|
+
if (err instanceof AgentUserError) return { ok: false, reason: err.message };
|
|
4981
|
+
throw err;
|
|
4982
|
+
}
|
|
4983
|
+
if (home === void 0) return { ok: true, user };
|
|
4984
|
+
const copied = await copyBuildHome(runtime, { ...runInput, user }, home, logPath);
|
|
4985
|
+
return copied === void 0 ? { ok: true, user, home } : { ok: false, reason: copied };
|
|
4986
|
+
}
|
|
4987
|
+
async function copyBuildHome(runtime, runInput, home, logPath) {
|
|
4988
|
+
const copied = await runtime.host.run(homeCopyRunArgs(runInput, home), { logPath });
|
|
4989
|
+
if (copied.status === 0) return void 0;
|
|
4990
|
+
return `copying ${home} into the build's home failed (exit ${copied.status})${said(copied.stderr)}`;
|
|
4991
|
+
}
|
|
4858
4992
|
function agentVersionOf(toolsJson) {
|
|
4859
4993
|
try {
|
|
4860
4994
|
const version = JSON.parse(toolsJson).claudeCodeVersion;
|
|
@@ -4879,9 +5013,7 @@ function containerCommandExec(input) {
|
|
|
4879
5013
|
containerEnv: state.containerEnv ?? {},
|
|
4880
5014
|
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
4881
5015
|
builtIns: state.builtIns === true,
|
|
4882
|
-
identity: input.job.commitIdentity
|
|
4883
|
-
imageEnv: state.imageEnv,
|
|
4884
|
-
proxyWarning: state.proxyWarningDropped !== true
|
|
5016
|
+
identity: input.job.commitIdentity
|
|
4885
5017
|
});
|
|
4886
5018
|
return {
|
|
4887
5019
|
container: state.container,
|
|
@@ -4905,9 +5037,7 @@ function containerSenderCommand(input) {
|
|
|
4905
5037
|
containerEnv: state.containerEnv ?? {},
|
|
4906
5038
|
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
4907
5039
|
builtIns: state.builtIns === true,
|
|
4908
|
-
identity: input.job.commitIdentity
|
|
4909
|
-
imageEnv: state.imageEnv,
|
|
4910
|
-
proxyWarning: state.proxyWarningDropped !== true
|
|
5040
|
+
identity: input.job.commitIdentity
|
|
4911
5041
|
});
|
|
4912
5042
|
const args = containerExecArgs({
|
|
4913
5043
|
container: state.container,
|
|
@@ -5007,7 +5137,7 @@ async function ensureTunnel(runtime, state, jobDir, config, itemKey, branch, rep
|
|
|
5007
5137
|
}
|
|
5008
5138
|
async function redeliver(runtime, state, jobDir) {
|
|
5009
5139
|
if (!filesAreCopied(state)) return { ok: true };
|
|
5010
|
-
const parts = ["gh", "
|
|
5140
|
+
const parts = ["gh", "git-hooks", "context"];
|
|
5011
5141
|
return deliverJobFiles(runtime, state, parts, secretsOf(runtime, jobDir));
|
|
5012
5142
|
}
|
|
5013
5143
|
async function deliverContainerHooks(runtime, state, jobDir) {
|
|
@@ -5020,6 +5150,8 @@ async function syncInContainer(input) {
|
|
|
5020
5150
|
try {
|
|
5021
5151
|
await ensureTunnel(runtime, state, input.jobDir, input.config, job.itemKey, job.branch, job.repositories, input.log, () => leaseExpiresAtMs(job));
|
|
5022
5152
|
if (state.stopped) {
|
|
5153
|
+
const network = await ensureNetworkReady(runtime, state);
|
|
5154
|
+
if (network !== void 0) return { ok: false, reason: network };
|
|
5023
5155
|
await runtime.host.start(state.container);
|
|
5024
5156
|
state.stopped = false;
|
|
5025
5157
|
if (!await waitForRelay(runtime, state)) return { ok: false, reason: "the relay did not start again" };
|
|
@@ -5038,9 +5170,7 @@ async function syncInContainer(input) {
|
|
|
5038
5170
|
containerEnv: state.containerEnv ?? {},
|
|
5039
5171
|
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
5040
5172
|
builtIns: state.builtIns === true,
|
|
5041
|
-
identity: job.commitIdentity
|
|
5042
|
-
imageEnv: state.imageEnv,
|
|
5043
|
-
proxyWarning: state.proxyWarningDropped !== true
|
|
5173
|
+
identity: job.commitIdentity
|
|
5044
5174
|
});
|
|
5045
5175
|
const result = await runtime.host.exec(
|
|
5046
5176
|
{ container: state.container, user: state.agentUser ?? ADDED_USER, workdir: job.workdir ?? CHECKOUT_DIR, env, argv: ["outerlayer", "sync"] },
|
|
@@ -5054,6 +5184,8 @@ async function syncInContainer(input) {
|
|
|
5054
5184
|
async function copyTranscriptsFromContainer(runtime, state) {
|
|
5055
5185
|
try {
|
|
5056
5186
|
if (state.stopped) {
|
|
5187
|
+
const network = await ensureNetworkReady(runtime, state);
|
|
5188
|
+
if (network !== void 0) return { ok: false, reason: network };
|
|
5057
5189
|
const started = await runtime.host.start(state.container);
|
|
5058
5190
|
if (started.status !== 0) return { ok: false, reason: `the build's container could not be started again (exit ${started.status})` };
|
|
5059
5191
|
state.stopped = false;
|
|
@@ -5067,6 +5199,7 @@ var HOOK_ERRORS_IN_CONTAINER = "/build/home/.outerlayer/spool/hook-errors.log";
|
|
|
5067
5199
|
async function copyHookErrors(runtime, state, jobDir) {
|
|
5068
5200
|
try {
|
|
5069
5201
|
if (state.stopped) {
|
|
5202
|
+
if (await ensureNetworkReady(runtime, state) !== void 0) return;
|
|
5070
5203
|
const started = await runtime.host.start(state.container);
|
|
5071
5204
|
if (started.status !== 0) return;
|
|
5072
5205
|
}
|
|
@@ -5086,6 +5219,8 @@ async function cleanupContainer(runtime, state, jobDir) {
|
|
|
5086
5219
|
if (removedContainer.status !== 0 && !/no such container/i.test(removedContainer.stderr)) {
|
|
5087
5220
|
failures.push(`container ${state.container} was not removed: ${removedContainer.stderr.trim()}`);
|
|
5088
5221
|
}
|
|
5222
|
+
const helperLeft = await removeNetworkHelper(runtime, state);
|
|
5223
|
+
if (helperLeft !== void 0) failures.push(helperLeft);
|
|
5089
5224
|
let volumeGone = false;
|
|
5090
5225
|
for (let attempt = 0; attempt < VOLUME_REMOVE_ATTEMPTS && !volumeGone; attempt++) {
|
|
5091
5226
|
const removed = await runtime.host.removeVolume(state.volume);
|
|
@@ -5115,13 +5250,15 @@ function containerJudgeEnvironment(input) {
|
|
|
5115
5250
|
env: NO_ENV,
|
|
5116
5251
|
argv: ["/bin/sh", "-c", `[ -f ${file} ] && [ ! -L ${file} ] && head -c ${maxBytes + 1} ${file}`]
|
|
5117
5252
|
}, { timeoutMs: REPORT_READ_TIMEOUT_MS });
|
|
5118
|
-
if (read.status > 1) throw new Error(`reading the judge's ${name} exited ${read.status}: ${
|
|
5253
|
+
if (read.status > 1) throw new Error(`reading the judge's ${name} exited ${read.status}: ${firstLine4(read.stderr)}`);
|
|
5119
5254
|
return read.status === 0 && Buffer.byteLength(read.stdout) <= maxBytes ? read.stdout : void 0;
|
|
5120
5255
|
};
|
|
5121
5256
|
return {
|
|
5122
5257
|
stop: async () => {
|
|
5123
5258
|
if (input.config !== void 0) await ensureTunnel(runtime, state, input.jobDir, input.config, job.itemKey, job.branch, job.repositories, input.log);
|
|
5124
5259
|
await stopContainer(runtime, state);
|
|
5260
|
+
const network = await ensureNetworkReady(runtime, state);
|
|
5261
|
+
if (network !== void 0) throw new Error(network);
|
|
5125
5262
|
const started = await runtime.host.start(state.container);
|
|
5126
5263
|
if (started.status !== 0) throw new Error(`the build's container could not be started again (exit ${started.status})`);
|
|
5127
5264
|
state.stopped = false;
|
|
@@ -5133,7 +5270,7 @@ function containerJudgeEnvironment(input) {
|
|
|
5133
5270
|
hashProgram: async () => {
|
|
5134
5271
|
const ran = await runtime.host.exec({ container: state.container, user: ADDED_USER, env: NO_ENV, argv: [...HASH_ARGV] });
|
|
5135
5272
|
const sha256 = ran.status === 0 ? parseProgramHash(ran.stdout) : void 0;
|
|
5136
|
-
return sha256 === void 0 ? { ok: false, reason:
|
|
5273
|
+
return sha256 === void 0 ? { ok: false, reason: firstLine4(ran.stderr) || `the hash could not be taken (exit ${ran.status})` } : { ok: true, sha256 };
|
|
5137
5274
|
},
|
|
5138
5275
|
prepare: async (files, tree) => {
|
|
5139
5276
|
if (filesAreCopied(state)) {
|
|
@@ -5166,7 +5303,7 @@ function containerJudgeEnvironment(input) {
|
|
|
5166
5303
|
// host. Every capability is dropped in the container, so root there could not either; the build's user removes its own, and the runner removes the rest.
|
|
5167
5304
|
clear: async () => {
|
|
5168
5305
|
const removed = await runtime.host.exec({ container: state.container, user, env: NO_ENV, argv: ["find", JUDGE_DIR, "-mindepth", "1", "-user", user, "-delete"] });
|
|
5169
|
-
if (removed.status !== 0) throw new Error(`find exited ${removed.status}: ${
|
|
5306
|
+
if (removed.status !== 0) throw new Error(`find exited ${removed.status}: ${firstLine4(removed.stderr)}`);
|
|
5170
5307
|
if (!filesAreCopied(state)) return;
|
|
5171
5308
|
const emptied = await clearJudgeFolder(runtime, state, secretsOf(runtime, input.jobDir));
|
|
5172
5309
|
if (!emptied.ok) throw new Error(emptied.reason);
|
|
@@ -5204,11 +5341,12 @@ async function startCheckContainer(input) {
|
|
|
5204
5341
|
buildDir: buildDir2,
|
|
5205
5342
|
repository,
|
|
5206
5343
|
imageId: built.imageId,
|
|
5207
|
-
imageEnv: built.imageEnv,
|
|
5208
5344
|
agentUser,
|
|
5209
5345
|
cpuset,
|
|
5210
5346
|
transport,
|
|
5211
|
-
...transport === "exec" ? { jobFiles: "copied" } : {}
|
|
5347
|
+
...transport === "exec" ? { jobFiles: "copied" } : {},
|
|
5348
|
+
...built.network === void 0 ? {} : { network: networkHelperName(name) },
|
|
5349
|
+
...built.home === void 0 ? {} : { home: built.home }
|
|
5212
5350
|
};
|
|
5213
5351
|
const checksDir = join(jobDir, "checks");
|
|
5214
5352
|
mkdirSync(checksDir, { recursive: true });
|
|
@@ -5222,7 +5360,7 @@ async function startCheckContainer(input) {
|
|
|
5222
5360
|
}
|
|
5223
5361
|
return { ok: false, reason };
|
|
5224
5362
|
};
|
|
5225
|
-
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${
|
|
5363
|
+
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${said(result.stderr)}`);
|
|
5226
5364
|
mkdirSync(buildDir2, { recursive: true });
|
|
5227
5365
|
if (!filesAreCopied(state)) chmodSync(buildDir2, 493);
|
|
5228
5366
|
let services;
|
|
@@ -5258,11 +5396,19 @@ async function startCheckContainer(input) {
|
|
|
5258
5396
|
};
|
|
5259
5397
|
const prepared = await host.run(prepareRunArgs(runInput), { logPath });
|
|
5260
5398
|
if (prepared.status !== 0) return dockerFailed("preparing the check environment's volume", prepared);
|
|
5261
|
-
|
|
5399
|
+
if (state.home !== void 0) {
|
|
5400
|
+
const copied = await copyBuildHome(runtime, { ...runInput, user: agentUser }, state.home, logPath);
|
|
5401
|
+
if (copied !== void 0) return fail(copied);
|
|
5402
|
+
}
|
|
5403
|
+
if (state.network !== void 0) {
|
|
5404
|
+
const notReady = await startNetworkHelper(runtime, { name: state.network, buildId, runnerId, image: built.imageId, limits: limits2, ipv6: runtime.ipv6 }, logPath);
|
|
5405
|
+
if (notReady !== void 0) return fail(notReady);
|
|
5406
|
+
}
|
|
5407
|
+
const started = await host.run(containerRunArgs({ ...runInput, network: state.network, home: state.home }), { logPath });
|
|
5262
5408
|
if (started.status !== 0) return dockerFailed("starting the check environment's container", started);
|
|
5263
5409
|
if (transport === "exec") joinBuild(runtime, state, services, (line2) => log.line(`${tag} ${line2}`));
|
|
5264
5410
|
if (!await waitForRelay(runtime, state)) return fail("the relay in the check environment's container did not start");
|
|
5265
|
-
const env = checkEnvironment({ config, item: job.item, repository, hostEnv: runtime.hostEnv, containerEnv: built.containerEnv ?? {}
|
|
5411
|
+
const env = checkEnvironment({ config, item: job.item, repository, hostEnv: runtime.hostEnv, containerEnv: built.containerEnv ?? {} });
|
|
5266
5412
|
const secrets = () => tokens.issuedTokens();
|
|
5267
5413
|
let delivered = false;
|
|
5268
5414
|
const deliverInput = async () => {
|
|
@@ -5287,6 +5433,11 @@ async function startCheckContainer(input) {
|
|
|
5287
5433
|
restart: async () => {
|
|
5288
5434
|
await leaveBuild(runtime, state);
|
|
5289
5435
|
await host.stop(name);
|
|
5436
|
+
const network = await ensureNetworkReady(runtime, state);
|
|
5437
|
+
if (network !== void 0) {
|
|
5438
|
+
log.error(`${tag} ${network}`);
|
|
5439
|
+
return false;
|
|
5440
|
+
}
|
|
5290
5441
|
const again = await host.start(name);
|
|
5291
5442
|
if (again.status !== 0 || !await waitForRelay(runtime, state)) return false;
|
|
5292
5443
|
rejoinBuild(runtime, state, (line2) => log.line(`${tag} ${line2}`));
|
|
@@ -5402,4 +5553,4 @@ function describeMachineDocker(machine) {
|
|
|
5402
5553
|
return `Docker Engine ${version ?? "of no known version"}, older than the ${MIN_ENGINE_MAJOR} that container builds need`;
|
|
5403
5554
|
}
|
|
5404
5555
|
|
|
5405
|
-
export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, ROOT_DISK_ID_PREFIX, RunnerInitError, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, keepUnpinnedRuntimes, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, reachDockerStep, readConfigObject, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, runtimeStepInput, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, withFactoryHosts, withTunnelLog, writeEvalInput, writeRunnerInit };
|
|
5556
|
+
export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, ROOT_DISK_ID_PREFIX, RunnerInitError, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureNetworkReady, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, firstLine4 as firstLine, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, keepUnpinnedRuntimes, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, reachDockerStep, readConfigObject, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, runtimeStepInput, said, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, stoppedHelperReason, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, withFactoryHosts, withTunnelLog, writeEvalInput, writeRunnerInit };
|