@outerlayer/cli 0.24.0 → 0.25.1
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 +21 -0
- package/README.md +9 -0
- package/dist/{agent-setup-QQYRBPK2.js → agent-setup-PDIIGMKE.js} +7 -7
- package/dist/{bridge-4ZARDVGS.js → bridge-5KZ36YDG.js} +3 -3
- package/dist/build-YYVAJ75G.js +12 -0
- package/dist/build-info.json +1 -1
- package/dist/{builder-MECDEKXX.js → builder-MNUJS4RG.js} +7 -7
- package/dist/{check-YYKNYFNI.js → check-C6HEFW6R.js} +39 -38
- package/dist/{chunk-BUBCPP3F.js → chunk-23SPSYXZ.js} +3 -3
- package/dist/{chunk-5ECUMU53.js → chunk-24LQ34XL.js} +6 -6
- package/dist/{chunk-BN3CSI7S.js → chunk-2K3TCQHW.js} +1 -1
- package/dist/{chunk-A62QFN2M.js → chunk-2N72GPS2.js} +3 -3
- package/dist/{chunk-TQ6Y7YV6.js → chunk-3FNPTQRH.js} +5 -5
- package/dist/{chunk-F2W2IYNP.js → chunk-3WZ5ECSM.js} +3 -3
- package/dist/{chunk-WH2QV3UL.js → chunk-4S4VBDSO.js} +1 -1
- package/dist/{chunk-IDSHLKQA.js → chunk-5222PA6S.js} +1 -1
- package/dist/{chunk-6GSA2SKT.js → chunk-A6ORKBVJ.js} +213 -59
- package/dist/{chunk-3W333NFO.js → chunk-APBTVIM4.js} +15 -4
- package/dist/{chunk-HHXBOTRO.js → chunk-ATGHVEU4.js} +1 -1
- package/dist/{chunk-D7K446H6.js → chunk-C36EOUUU.js} +5 -5
- package/dist/{chunk-RVYOOYOA.js → chunk-CQRIZNE6.js} +19 -10
- package/dist/{chunk-FWEWFW3F.js → chunk-DEBOL6ON.js} +1 -1
- package/dist/{chunk-GU4PKXN7.js → chunk-ENFBARQP.js} +185 -38
- package/dist/{chunk-H6IUKXXI.js → chunk-F57CLUH7.js} +207 -35
- package/dist/{chunk-E4OUL7ZP.js → chunk-FXUVXSY2.js} +2 -2
- package/dist/{chunk-F7Y2USIM.js → chunk-H6ZFLIX3.js} +3 -3
- package/dist/{chunk-LY2L3O2O.js → chunk-HPOEVC2V.js} +3 -2
- package/dist/{chunk-ZFLOFAUG.js → chunk-I25F6YVP.js} +8 -8
- package/dist/{chunk-DG2ULWM6.js → chunk-IGRRD7PX.js} +11 -7
- package/dist/{chunk-GISNHSYL.js → chunk-JGD5TWQ2.js} +4 -2
- package/dist/{chunk-D7X5ITVT.js → chunk-JWRX5ZTT.js} +6 -2
- package/dist/{chunk-755WXDBI.js → chunk-K5WVK7IC.js} +1 -1
- package/dist/{chunk-FKXGQOF5.js → chunk-M4B6QKNZ.js} +1 -1
- package/dist/{chunk-5XCAPBE2.js → chunk-N3VSI5ZI.js} +6 -6
- package/dist/{chunk-NTQTDCYR.js → chunk-O2WYUIK7.js} +1 -1
- package/dist/{chunk-BOQY756V.js → chunk-OEU4JSDE.js} +8 -7
- package/dist/{chunk-TTLVQZSH.js → chunk-Q435LWVN.js} +5 -5
- package/dist/{chunk-D4AMAEZ7.js → chunk-QE3UQAHK.js} +322 -17
- package/dist/{chunk-VV7ZD5LR.js → chunk-QMQC6JCO.js} +1 -1
- package/dist/{chunk-FQPN5S4Q.js → chunk-QXNJWSTM.js} +4 -4
- package/dist/{chunk-VBEXKEBV.js → chunk-S6AWZKJN.js} +19 -6
- package/dist/{chunk-V5Q3S4NM.js → chunk-SNQR2EYI.js} +2 -2
- package/dist/{chunk-CZUH2SLQ.js → chunk-UNF7MWEL.js} +1 -1
- package/dist/{chunk-W7O4LA4E.js → chunk-VAMUWK55.js} +3 -3
- package/dist/{chunk-PDIM5T65.js → chunk-XGJUNNXL.js} +1 -1
- package/dist/{chunk-NGZID7UI.js → chunk-XRYUJTAT.js} +8 -1
- package/dist/{chunk-LBCZXXOX.js → chunk-ZGMQQWCV.js} +2 -2
- package/dist/{chunk-KF37SUDM.js → chunk-ZI2ZVWKT.js} +1 -1
- package/dist/{chunk-PVRBE7S4.js → chunk-ZODVSFI4.js} +1 -1
- package/dist/chunk-ZVB57WI6.js +19 -0
- package/dist/{claude-launcher-JCPSHDZQ.js → claude-launcher-WGOCLTG6.js} +1 -1
- package/dist/{cli-ZTBH3FBG.js → cli-YMTNHR4W.js} +107 -102
- package/dist/command-DKYZC7PH.js +533 -0
- package/dist/{config-7Z5DHSGY.js → config-JJ3EO7SB.js} +3 -3
- package/dist/{connect-cmd-NY5LIKVC.js → connect-cmd-F7T4LNKX.js} +7 -7
- package/dist/{container-start-OHBUZEJJ.js → container-start-AX7QXJMR.js} +45 -36
- package/dist/{control-plane-launch-GKGI6HJA.js → control-plane-launch-ZFT6SI4N.js} +6 -6
- package/dist/{dist-2APO44JG.js → dist-QPHZE47F.js} +1 -1
- package/dist/{docker-RKGBJESN.js → docker-5EC5TE3Y.js} +7 -7
- package/dist/{doctor-DOAFZV4O.js → doctor-S6YCZGUU.js} +79 -33
- package/dist/{emit-artifact-cmd-VZHIDPXQ.js → emit-artifact-cmd-DJO475VZ.js} +11 -11
- package/dist/{emit-criteria-cmd-SYLBCWHW.js → emit-criteria-cmd-EULQ2MLI.js} +8 -8
- package/dist/{emit-finding-cmd-52M43NPC.js → emit-finding-cmd-QIIKMITO.js} +8 -8
- package/dist/{emit-result-cmd-BTMTGDAV.js → emit-result-cmd-NMCLTA47.js} +11 -11
- package/dist/{emit-step-cmd-6XTJITZT.js → emit-step-cmd-72OX5P6M.js} +9 -9
- package/dist/{exec-client-CKPK62K2.js → exec-client-KH33DICR.js} +4 -4
- package/dist/{governing-source-GWN7GVEN.js → governing-source-JNQ6PX2A.js} +11 -11
- package/dist/{guest-init-ZBL5CN7Y.js → guest-init-TOSKPGPF.js} +5 -5
- package/dist/{hook-fast-3JL4PXLG.js → hook-fast-NEELST6G.js} +1 -1
- package/dist/host-key-ICJEQBWH.js +9 -0
- package/dist/{image-tag-AO4RBAKW.js → image-tag-6KJOGBQK.js} +4 -4
- package/dist/index.js +4 -4
- package/dist/{init-TSQ3EOQW.js → init-624F4JIP.js} +25 -23
- package/dist/{init-EQTR7AEF.js → init-G7XC5WWL.js} +25 -23
- package/dist/{init-cmd-AF2MH36A.js → init-cmd-UUYA57VO.js} +11 -11
- package/dist/{init-update-SHISHMXV.js → init-update-MMV33PLM.js} +9 -9
- package/dist/{install-ORQC26ZE.js → install-MPEJJ7X6.js} +5 -5
- package/dist/{install-cmd-4LA3UJZ4.js → install-cmd-SE6NCTJK.js} +6 -6
- package/dist/job-state-format-WJQGQB6F.js +6 -0
- package/dist/{logs-5EPHIPZB.js → logs-T4ERSOQ4.js} +3 -3
- package/dist/loop-K5B2A3VW.js +78 -0
- package/dist/{machine-6UNLIPLE.js → machine-J4IFVIKU.js} +21 -19
- package/dist/{mcp-serve-cmd-KMWEKM7C.js → mcp-serve-cmd-7M4VLNI4.js} +5 -5
- package/dist/{paths-XY5ADO32.js → paths-2KGM2LZV.js} +3 -3
- package/dist/pending-BGLMTB5Q.js +9 -0
- package/dist/{pidfile-OJ7RP4Q2.js → pidfile-VYBH3IMN.js} +4 -4
- package/dist/{record-BEJB4J7N.js → record-GNOHDJ2O.js} +4 -4
- package/dist/{relay-PSZ4LGMW.js → relay-GFPPD6GF.js} +1 -1
- package/dist/relay-protocol-HELO5SNH.js +6 -0
- package/dist/{runner-env-ZJWJOJKQ.js → runner-env-GUFV544G.js} +6 -6
- package/dist/{runner-identity-2OOUJSFJ.js → runner-identity-HZ6CBM2R.js} +7 -7
- package/dist/{runner-key-WDFBSJRX.js → runner-key-FFVZUEHE.js} +25 -23
- package/dist/{session-sender-X3BBQZMF.js → session-sender-3SUWNNVP.js} +12 -12
- package/dist/{spec-cmd-QRF5YXKK.js → spec-cmd-VZDE6FFH.js} +9 -9
- package/dist/{status-ZCAAF6MD.js → status-GXTD44DX.js} +35 -29
- package/dist/{sync-cmd-UQK3RYAC.js → sync-cmd-VFB3NEJ6.js} +11 -11
- package/dist/{watch-MOQ3GQTE.js → watch-LWMTDD3L.js} +11 -11
- package/dist/{work-claim-cmd-RT343CLA.js → work-claim-cmd-FOBTDQVR.js} +12 -12
- package/dist/{work-cmd-APXSER2D.js → work-cmd-6HARIBMW.js} +9 -9
- package/dist/{work-comment-cmd-AT5NUYUU.js → work-comment-cmd-BITPALHR.js} +9 -9
- package/dist/{work-logs-cmd-Z5DMNEJP.js → work-logs-cmd-VGB3O2LZ.js} +9 -9
- package/dist/{work-open-pr-cmd-ZTS6MJHL.js → work-open-pr-cmd-SVZCNOIM.js} +10 -10
- package/dist/{work-pr-cmd-IWZCC3WH.js → work-pr-cmd-SJT46GN4.js} +9 -9
- package/dist/{work-stop-cmd-DCAWFDZC.js → work-stop-cmd-WXKVVA4S.js} +9 -9
- package/package.json +2 -2
- package/skill-pack/maintained/outerlayer-build/SKILL.md +1 -1
- package/skill-pack/maintained/outerlayer-build/references/agent-briefs.md +3 -2
- package/skill-pack/maintained/outerlayer-build/references/review-briefs.md +3 -1
- package/dist/build-OVZIT2G2.js +0 -12
- package/dist/command-DO4TERRT.js +0 -208
- package/dist/host-key-W2DLZGZ7.js +0 -9
- package/dist/loop-4WUCS5JP.js +0 -77
- package/dist/pending-35J3ZPLR.js +0 -9
- package/dist/relay-protocol-K7KP2SPI.js +0 -6
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
3
|
+
import { runnerImageVersion } from './chunk-5222PA6S.js';
|
|
4
|
+
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-Q435LWVN.js';
|
|
4
5
|
import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
|
|
5
6
|
import { currentCliBuild } from './chunk-OGFGZQA3.js';
|
|
6
|
-
import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, JUDGE_DIR, JUDGE_REPORT, MAX_REPORT_BYTES, spawnRun } from './chunk-
|
|
7
|
-
import {
|
|
8
|
-
import { execCapture } from './chunk-
|
|
9
|
-
import { GUEST_CID } from './chunk-
|
|
10
|
-
import { describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript } from './chunk-
|
|
11
|
-
import { WorkCommandError } from './chunk-
|
|
7
|
+
import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, JUDGE_DIR, JUDGE_REPORT, MAX_REPORT_BYTES, spawnRun } from './chunk-N3VSI5ZI.js';
|
|
8
|
+
import { hostHelperPinned, firecrackerArch, MICROVM_ARCHES, RecipeError, DOCKER_FEATURE, CLAUDE_CODE_VERSION, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_VERSION, DEFAULT_BASE_IMAGE } from './chunk-APBTVIM4.js';
|
|
9
|
+
import { execCapture } from './chunk-HPOEVC2V.js';
|
|
10
|
+
import { GUEST_CID } from './chunk-XGJUNNXL.js';
|
|
11
|
+
import { describeCallFailure, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript } from './chunk-3FNPTQRH.js';
|
|
12
|
+
import { WorkCommandError } from './chunk-CQRIZNE6.js';
|
|
12
13
|
import { hostAllowed } from './chunk-UXYLWVTQ.js';
|
|
13
14
|
import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
|
|
14
15
|
import { sharedSkillNames, skillConflictMessage } from './chunk-VPEGE3QZ.js';
|
|
15
16
|
import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
|
|
16
|
-
import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-
|
|
17
|
+
import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-QE3UQAHK.js';
|
|
17
18
|
import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-RKOTJQVG.js';
|
|
18
19
|
import { downconvertSession } from './chunk-QZBXLLTV.js';
|
|
19
|
-
import { rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir,
|
|
20
|
-
import { repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT } from './chunk-
|
|
21
|
-
import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, MAX_OPEN_STREAMS, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-
|
|
22
|
-
import { readFileSync, existsSync,
|
|
20
|
+
import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, SHIM_DIR } from './chunk-ZI2ZVWKT.js';
|
|
21
|
+
import { repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath, JOB_MOUNT } from './chunk-2K3TCQHW.js';
|
|
22
|
+
import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, DOCKER_DESKTOP_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, MAX_OPEN_STREAMS, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-JGD5TWQ2.js';
|
|
23
|
+
import { readFileSync, mkdirSync, existsSync, mkdtempSync, rmSync, chmodSync, truncateSync, writeFileSync, readdirSync, lstatSync, copyFileSync, accessSync, constants, statSync, rmdirSync, renameSync, unlinkSync, openSync, closeSync, createWriteStream, createReadStream } from 'fs';
|
|
23
24
|
import { join, dirname, basename } from 'path';
|
|
25
|
+
import { isIP, createConnection, connect, createServer as createServer$1 } from 'net';
|
|
24
26
|
import { spawnSync, spawn } from 'child_process';
|
|
25
27
|
import { availableParallelism, networkInterfaces } from 'os';
|
|
26
28
|
import { randomBytes, createHash } from 'crypto';
|
|
@@ -30,7 +32,6 @@ import { createServer, request } from 'http';
|
|
|
30
32
|
import { request as request$1 } from 'https';
|
|
31
33
|
import { pipeline, finished } from 'stream/promises';
|
|
32
34
|
import { createGunzip, gunzipSync, constants as constants$1 } from 'zlib';
|
|
33
|
-
import { isIP, connect, createServer as createServer$1 } from 'net';
|
|
34
35
|
import { lookup } from 'dns/promises';
|
|
35
36
|
|
|
36
37
|
createRequire(import.meta.url);
|
|
@@ -144,6 +145,101 @@ function realCgroupPort() {
|
|
|
144
145
|
remove: (path) => removeBuildCgroup(fs, path)
|
|
145
146
|
};
|
|
146
147
|
}
|
|
148
|
+
var SUPPORTED_HELPER_PROTOCOLS = [1];
|
|
149
|
+
var HELPER_ENV = "OUTERLAYER_HELPER_SOCKET";
|
|
150
|
+
var HelperRefusal = class extends Error {
|
|
151
|
+
constructor(code, reason) {
|
|
152
|
+
super(reason);
|
|
153
|
+
this.code = code;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
function helperSocketPath(unitName) {
|
|
157
|
+
return `/run/${unitName}-helper/helper.sock`;
|
|
158
|
+
}
|
|
159
|
+
var START_TIMEOUT_MS = 12e4;
|
|
160
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
161
|
+
var MAX_REPLY_BYTES = 1024 * 1024;
|
|
162
|
+
function ask(socketPath, request, timeoutMs) {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
const conn = createConnection(socketPath);
|
|
165
|
+
let text = "";
|
|
166
|
+
let settled = false;
|
|
167
|
+
const settle = (finish) => {
|
|
168
|
+
if (settled) return;
|
|
169
|
+
settled = true;
|
|
170
|
+
conn.destroy();
|
|
171
|
+
finish();
|
|
172
|
+
};
|
|
173
|
+
conn.setTimeout(timeoutMs, () => settle(() => reject(new Error(`the helper at ${socketPath} did not answer within ${Math.round(timeoutMs / 1e3)} seconds`))));
|
|
174
|
+
conn.on("connect", () => conn.write(`${JSON.stringify(request)}
|
|
175
|
+
`));
|
|
176
|
+
conn.on("data", (chunk) => {
|
|
177
|
+
text += chunk.toString("utf8");
|
|
178
|
+
if (text.length > MAX_REPLY_BYTES) return settle(() => reject(new Error(`the helper at ${socketPath} sent a reply that is too long`)));
|
|
179
|
+
const end = text.indexOf("\n");
|
|
180
|
+
if (end === -1) return;
|
|
181
|
+
settle(() => {
|
|
182
|
+
let reply;
|
|
183
|
+
try {
|
|
184
|
+
reply = JSON.parse(text.slice(0, end));
|
|
185
|
+
} catch {
|
|
186
|
+
return reject(new Error(`the helper at ${socketPath} sent a reply that is not JSON`));
|
|
187
|
+
}
|
|
188
|
+
if (reply.status === "refused") return reject(new HelperRefusal(String(reply.code ?? "refused"), String(reply.reason ?? "the helper refused the request")));
|
|
189
|
+
resolve(reply);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
conn.on("error", (err) => settle(() => reject(new Error(`the helper at ${socketPath} did not answer: ${err.message}`))));
|
|
193
|
+
conn.on("close", () => settle(() => reject(new Error(`the helper at ${socketPath} closed the connection without a reply`))));
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function helperClient(socketPath, options = {}) {
|
|
197
|
+
const REQUEST_TIMEOUT_MS = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
198
|
+
return {
|
|
199
|
+
async start({ build, kind }) {
|
|
200
|
+
const reply = await ask(socketPath, { v: 1, op: "start", build, kind }, START_TIMEOUT_MS);
|
|
201
|
+
return { unit: String(reply.unit), chroot: String(reply.chroot), vsock: String(reply.vsock) };
|
|
202
|
+
},
|
|
203
|
+
async stop(build) {
|
|
204
|
+
await ask(socketPath, { v: 1, op: "stop", build }, REQUEST_TIMEOUT_MS);
|
|
205
|
+
},
|
|
206
|
+
async state(build) {
|
|
207
|
+
const reply = await ask(socketPath, { v: 1, op: "state", build }, REQUEST_TIMEOUT_MS);
|
|
208
|
+
return { active: reply.active === true, oomKills: typeof reply.oomKills === "number" ? reply.oomKills : 0 };
|
|
209
|
+
},
|
|
210
|
+
async list() {
|
|
211
|
+
const reply = await ask(socketPath, { v: 1, op: "list" }, REQUEST_TIMEOUT_MS);
|
|
212
|
+
return Array.isArray(reply.builds) ? reply.builds.map(String) : [];
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function reinstallMessage(protocol) {
|
|
217
|
+
const spoken = protocol === void 0 ? "a protocol it does not name" : `protocol ${protocol}`;
|
|
218
|
+
return `the root helper speaks ${spoken}, which this runner does not support, so microVM builds run without the jailer; run \`outerlayer runner install --service --replace\` to install the helper that goes with this release`;
|
|
219
|
+
}
|
|
220
|
+
async function probeHelper(socketPath, options = {}) {
|
|
221
|
+
if (socketPath === void 0 || socketPath === "") return { ok: false, reason: "absent", detail: `${HELPER_ENV} is not set, so this runner was not started by a service that has a helper` };
|
|
222
|
+
if (!(options.pinned ?? hostHelperPinned())) return { ok: false, reason: "unpinned", detail: "this release of the CLI pins no helper, so builds run without the jailer" };
|
|
223
|
+
try {
|
|
224
|
+
const reply = await ask(socketPath, { v: 1, op: "hello" }, options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
|
|
225
|
+
const protocol = typeof reply.protocol === "number" ? reply.protocol : void 0;
|
|
226
|
+
if (protocol === void 0 || !SUPPORTED_HELPER_PROTOCOLS.includes(protocol)) return { ok: false, reason: "unsupported", detail: reinstallMessage(protocol) };
|
|
227
|
+
return { ok: true, client: helperClient(socketPath, { requestTimeoutMs: options.requestTimeoutMs }), firecracker: String(reply.firecracker ?? "") };
|
|
228
|
+
} catch (err) {
|
|
229
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
230
|
+
return { ok: false, reason: "absent", unreachable: true, detail: message.includes(socketPath) ? message : `the helper at ${socketPath} did not answer: ${message}` };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function jailedAlive(unit, cgroupRoot = "/sys/fs/cgroup") {
|
|
234
|
+
try {
|
|
235
|
+
return /^populated 1$/m.test(readFileSync(join(cgroupRoot, "system.slice", `${unit}.service`, "cgroup.events"), "utf8"));
|
|
236
|
+
} catch {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function realHelperPort(env = process.env) {
|
|
241
|
+
return { probe: () => probeHelper(env[HELPER_ENV]), alive: (unit) => jailedAlive(unit) };
|
|
242
|
+
}
|
|
147
243
|
var BranchPrepareError = class extends Error {
|
|
148
244
|
};
|
|
149
245
|
var OWN_PREFIX = "outerlayer/";
|
|
@@ -353,7 +449,8 @@ function pinnedAssets(arch) {
|
|
|
353
449
|
firecracker: {
|
|
354
450
|
url: `${FIRECRACKER_RELEASES}/v${version}/firecracker-v${version}-${arch}.tgz`,
|
|
355
451
|
sha256: FIRECRACKER_SHA256[arch],
|
|
356
|
-
binarySha256: FIRECRACKER_BINARY_SHA256[arch]
|
|
452
|
+
binarySha256: FIRECRACKER_BINARY_SHA256[arch],
|
|
453
|
+
jailerSha256: JAILER_BINARY_SHA256[arch]
|
|
357
454
|
},
|
|
358
455
|
kernel: { url: `${GUEST_ASSETS_BASE_URL}/vmlinux-${arch}`, sha256: GUEST_KERNEL_SHA256[arch] },
|
|
359
456
|
helper: { url: `${GUEST_ASSETS_BASE_URL}/outerlayer-guest-${arch}`, sha256: GUEST_HELPER_SHA256[arch] }
|
|
@@ -392,14 +489,45 @@ async function ensureFile(dir, file, pin, fetchImpl, mode) {
|
|
|
392
489
|
writeAtomic(path, bytes, mode);
|
|
393
490
|
return path;
|
|
394
491
|
}
|
|
395
|
-
function extractWithTar(arch) {
|
|
396
|
-
const name =
|
|
492
|
+
function extractWithTar(arch, program = "firecracker") {
|
|
493
|
+
const name = `${program}-v${FIRECRACKER_VERSION}-${arch}`;
|
|
397
494
|
return async (tarball, destDir) => {
|
|
398
495
|
const result = spawnSync("tar", ["-xzf", tarball, "-C", destDir, "--strip-components=1", `release-v${FIRECRACKER_VERSION}-${arch}/${name}`], { encoding: "utf8" });
|
|
399
496
|
if (result.status !== 0) throw new Error(`tar could not unpack ${tarball}: ${result.stderr.trim()}`);
|
|
400
497
|
return join(destDir, name);
|
|
401
498
|
};
|
|
402
499
|
}
|
|
500
|
+
async function ensureFirecracker(input) {
|
|
501
|
+
const { dir, arch, pins, fetchImpl } = input;
|
|
502
|
+
const firecracker = join(dir, "firecracker");
|
|
503
|
+
if (existsSync(firecracker)) {
|
|
504
|
+
const actual = sha256Of(readFileSync(firecracker));
|
|
505
|
+
if (actual !== pins.firecracker.binarySha256) throw pinProblem("firecracker", pins.firecracker.binarySha256, actual, `at ${firecracker}`);
|
|
506
|
+
return firecracker;
|
|
507
|
+
}
|
|
508
|
+
const tarballName = `firecracker-${arch}.tgz`;
|
|
509
|
+
const tarball = await ensureFile(dir, tarballName, pins.firecracker, fetchImpl, RUNNER_FILE_MODE);
|
|
510
|
+
const scratch = mkdtempSync(join(dir, ".extract-"));
|
|
511
|
+
try {
|
|
512
|
+
const extracted = await (input.extract ?? extractWithTar(arch))(tarball, scratch);
|
|
513
|
+
const bytes = readFileSync(extracted);
|
|
514
|
+
const actual = sha256Of(bytes);
|
|
515
|
+
if (actual !== pins.firecracker.binarySha256) throw pinProblem("firecracker", pins.firecracker.binarySha256, actual, `unpacked from ${tarballName}`);
|
|
516
|
+
writeAtomic(firecracker, bytes, 493);
|
|
517
|
+
} finally {
|
|
518
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
519
|
+
}
|
|
520
|
+
return firecracker;
|
|
521
|
+
}
|
|
522
|
+
async function ensureFirecrackerAndJailer(options) {
|
|
523
|
+
const arch = options.arch ?? firecrackerArch(process.arch);
|
|
524
|
+
if (!MICROVM_ARCHES.includes(arch)) throw new AssetError("firecracker", `no Firecracker assets are pinned for ${arch}, so microVM builds run on ${MICROVM_ARCHES.join(" or ")} hosts only`);
|
|
525
|
+
const pins = options.pins ?? pinnedAssets(arch);
|
|
526
|
+
const dir = vmAssetsDir(options.runnerDir);
|
|
527
|
+
mkdirSync(dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
528
|
+
const firecracker = await ensureFirecracker({ dir, arch, pins, fetchImpl: options.fetchImpl ?? fetch, extract: options.extractFirecracker });
|
|
529
|
+
return { firecracker, jailer: await ensureJailer(options) };
|
|
530
|
+
}
|
|
403
531
|
async function ensureAssets(options) {
|
|
404
532
|
const arch = options.arch ?? firecrackerArch(process.arch);
|
|
405
533
|
if (!MICROVM_ARCHES.includes(arch)) throw new AssetError("firecracker", `no Firecracker or guest assets are pinned for ${arch}, so microVM builds run on ${MICROVM_ARCHES.join(" or ")} hosts only`);
|
|
@@ -407,28 +535,40 @@ async function ensureAssets(options) {
|
|
|
407
535
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
408
536
|
const dir = vmAssetsDir(options.runnerDir);
|
|
409
537
|
mkdirSync(dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
410
|
-
const firecracker =
|
|
411
|
-
if (existsSync(firecracker)) {
|
|
412
|
-
const actual = sha256Of(readFileSync(firecracker));
|
|
413
|
-
if (actual !== pins.firecracker.binarySha256) throw pinProblem("firecracker", pins.firecracker.binarySha256, actual, `at ${firecracker}`);
|
|
414
|
-
} else {
|
|
415
|
-
const tarballName = `firecracker-${arch}.tgz`;
|
|
416
|
-
const tarball = await ensureFile(dir, tarballName, pins.firecracker, fetchImpl, RUNNER_FILE_MODE);
|
|
417
|
-
const scratch = mkdtempSync(join(dir, ".extract-"));
|
|
418
|
-
try {
|
|
419
|
-
const extracted = await (options.extractFirecracker ?? extractWithTar(arch))(tarball, scratch);
|
|
420
|
-
const bytes = readFileSync(extracted);
|
|
421
|
-
const actual = sha256Of(bytes);
|
|
422
|
-
if (actual !== pins.firecracker.binarySha256) throw pinProblem("firecracker", pins.firecracker.binarySha256, actual, `unpacked from ${tarballName}`);
|
|
423
|
-
writeAtomic(firecracker, bytes, 493);
|
|
424
|
-
} finally {
|
|
425
|
-
rmSync(scratch, { recursive: true, force: true });
|
|
426
|
-
}
|
|
427
|
-
}
|
|
538
|
+
const firecracker = await ensureFirecracker({ dir, arch, pins, fetchImpl, extract: options.extractFirecracker });
|
|
428
539
|
const kernel = await ensureFile(dir, `vmlinux-${arch}`, pins.kernel, fetchImpl, RUNNER_FILE_MODE);
|
|
429
540
|
const helper = await ensureFile(dir, `outerlayer-guest-${arch}`, pins.helper, fetchImpl, 493);
|
|
430
541
|
return { firecracker, kernel, helper, helperSha256: pins.helper.sha256 };
|
|
431
542
|
}
|
|
543
|
+
async function ensureJailer(options) {
|
|
544
|
+
const arch = options.arch ?? firecrackerArch(process.arch);
|
|
545
|
+
if (!MICROVM_ARCHES.includes(arch)) throw new AssetError("jailer", `no Firecracker assets are pinned for ${arch}, so microVM builds run on ${MICROVM_ARCHES.join(" or ")} hosts only`);
|
|
546
|
+
const pins = options.pins ?? pinnedAssets(arch);
|
|
547
|
+
const expected = pins.firecracker.jailerSha256;
|
|
548
|
+
if (expected === void 0) throw new AssetError("jailer", "this release pins no hash for the jailer, so it cannot be had");
|
|
549
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
550
|
+
const dir = vmAssetsDir(options.runnerDir);
|
|
551
|
+
mkdirSync(dir, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
552
|
+
const jailer = join(dir, "jailer");
|
|
553
|
+
if (existsSync(jailer)) {
|
|
554
|
+
const actual = sha256Of(readFileSync(jailer));
|
|
555
|
+
if (actual !== expected) throw pinProblem("jailer", expected, actual, `at ${jailer}`);
|
|
556
|
+
return jailer;
|
|
557
|
+
}
|
|
558
|
+
const tarballName = `firecracker-${arch}.tgz`;
|
|
559
|
+
const tarball = await ensureFile(dir, tarballName, pins.firecracker, fetchImpl, RUNNER_FILE_MODE);
|
|
560
|
+
const scratch = mkdtempSync(join(dir, ".extract-"));
|
|
561
|
+
try {
|
|
562
|
+
const extracted = await (options.extractJailer ?? extractWithTar(arch, "jailer"))(tarball, scratch);
|
|
563
|
+
const bytes = readFileSync(extracted);
|
|
564
|
+
const actual = sha256Of(bytes);
|
|
565
|
+
if (actual !== expected) throw pinProblem("jailer", expected, actual, `unpacked from ${tarballName}`);
|
|
566
|
+
writeAtomic(jailer, bytes, 493);
|
|
567
|
+
} finally {
|
|
568
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
569
|
+
}
|
|
570
|
+
return jailer;
|
|
571
|
+
}
|
|
432
572
|
var STOP_GRACE_SECONDS = 15;
|
|
433
573
|
function parseImageConfig(json) {
|
|
434
574
|
const config = JSON.parse(json);
|
|
@@ -755,6 +895,7 @@ function createMicroVmPorts(over = {}) {
|
|
|
755
895
|
rootfs: over.rootfs ?? createRootfsHost(),
|
|
756
896
|
firecracker: over.firecracker ?? createFirecrackerHost(),
|
|
757
897
|
cgroup: over.cgroup ?? realCgroupPort(),
|
|
898
|
+
helper: over.helper ?? realHelperPort(),
|
|
758
899
|
exec: over.exec ?? execCapture
|
|
759
900
|
};
|
|
760
901
|
}
|
|
@@ -2343,6 +2484,7 @@ function createContainerRuntime(opts = {}) {
|
|
|
2343
2484
|
tunnelOptions: opts.tunnelOptions,
|
|
2344
2485
|
sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
|
|
2345
2486
|
hostEnv: opts.hostEnv ?? process.env,
|
|
2487
|
+
platform: opts.platform ?? process.platform,
|
|
2346
2488
|
credentials: opts.credentials ?? /* @__PURE__ */ new Map(),
|
|
2347
2489
|
github: { gitUrl: opts.github?.gitUrl ?? "https://github.com", apiUrl: opts.github?.apiUrl ?? "https://api.github.com" },
|
|
2348
2490
|
remoteFor,
|
|
@@ -2531,8 +2673,8 @@ async function provisionContainer(input) {
|
|
|
2531
2673
|
if (!(Number.parseInt(engine, 10) >= MIN_ENGINE_MAJOR)) {
|
|
2532
2674
|
return fail(`Docker Engine ${engine} is too old: container builds need Engine ${MIN_ENGINE_MAJOR} or later`);
|
|
2533
2675
|
}
|
|
2534
|
-
if (/docker desktop/i.test(await host.operatingSystem() ?? "")) {
|
|
2535
|
-
return fail(
|
|
2676
|
+
if (/docker desktop/i.test(await host.operatingSystem() ?? "") && !(runnerImageVersion(runtime.hostEnv) !== void 0 && runtime.platform === "linux")) {
|
|
2677
|
+
return fail(DOCKER_DESKTOP_REASON);
|
|
2536
2678
|
}
|
|
2537
2679
|
const governing = await resolveGoverningSource({ config, repository, fetchImpl: input.fetchImpl });
|
|
2538
2680
|
if (!governing.ok) return fail(governing.reason);
|
|
@@ -2587,11 +2729,16 @@ async function provisionContainer(input) {
|
|
|
2587
2729
|
if (env.skippedTokenVariables.length > 0) {
|
|
2588
2730
|
log.line(`${tag} not passing ${env.skippedTokenVariables.join(", ")} from runner.build.variables into the build: its repository token comes from the runner`);
|
|
2589
2731
|
}
|
|
2732
|
+
const ignoredProperties = report.ignored.map(({ property, source }) => ({ property, source }));
|
|
2733
|
+
if (report.docker) {
|
|
2734
|
+
ignoredProperties.push({ property: "docker daemon", source: `feature ${DOCKER_FEATURE}` });
|
|
2735
|
+
log.line(`${tag} container builds have no Docker daemon, so steps that run Docker will fail`);
|
|
2736
|
+
}
|
|
2590
2737
|
const environment = {
|
|
2591
2738
|
isolation: "container",
|
|
2592
2739
|
recipe: { sourceCommit: report.sourceCommit, key: report.recipeKey, path: report.recipe },
|
|
2593
2740
|
imageId: report.imageId,
|
|
2594
|
-
ignoredProperties
|
|
2741
|
+
ignoredProperties,
|
|
2595
2742
|
variables: env.variables,
|
|
2596
2743
|
cliVersion: input.cliVersion
|
|
2597
2744
|
};
|
|
@@ -3157,4 +3304,4 @@ async function startCheckContainer(input) {
|
|
|
3157
3304
|
};
|
|
3158
3305
|
}
|
|
3159
3306
|
|
|
3160
|
-
export { ADDED_USER, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, LEASE_SECONDS, MIN_ENGINE_MAJOR, cleanupContainer, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, deleteBuildDisk, deliverContainerHooks, ensureRootfs, ensureTunnel, filesAreCopied, ghHostsYml, gitRemoteFor, isLiteralAddress, keepGhConfigCurrent, leaseExpiresAtMs, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, parseCpuList, prepareBranch, provisionContainer, resolveAgentUser, runBuildSteps, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startServicesFor, stopContainer, syncInContainer, writeEvalInput };
|
|
3307
|
+
export { ADDED_USER, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HelperRefusal, LEASE_SECONDS, MIN_ENGINE_MAJOR, cleanupContainer, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, deleteBuildDisk, deliverContainerHooks, ensureFirecrackerAndJailer, ensureRootfs, ensureTunnel, filesAreCopied, ghHostsYml, gitRemoteFor, helperSocketPath, isLiteralAddress, keepGhConfigCurrent, leaseExpiresAtMs, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, parseCpuList, prepareBranch, probeHelper, provisionContainer, resolveAgentUser, runBuildSteps, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startServicesFor, stopContainer, syncInContainer, writeEvalInput };
|