@outerlayer/cli 0.33.0-next.20261022004023 → 0.33.0-next.20261022124145
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/README.md +12 -11
- package/dist/{agent-setup-UY5NBT7C.js → agent-setup-2MJXGAZ5.js} +10 -10
- package/dist/{artifact-link-cmd-2MBHG3PO.js → artifact-link-cmd-6FF2Y6QI.js} +2 -2
- package/dist/build-disk-5GIWYDOB.js +18 -0
- package/dist/build-info.json +1 -1
- package/dist/{builder-VR55L4PV.js → builder-EELBB7SI.js} +4 -4
- package/dist/{check-XGBAFJPP.js → check-EJKRXI2N.js} +36 -34
- package/dist/{chunk-N3KK5BKF.js → chunk-2GHI2J26.js} +7 -7
- package/dist/{chunk-AKR32WHV.js → chunk-5DNCFOXA.js} +9 -7
- package/dist/{chunk-UIBTEDLA.js → chunk-6JNCNHSV.js} +5 -5
- package/dist/{chunk-GHQFV3TS.js → chunk-6WUQSARX.js} +11 -10
- package/dist/{chunk-EG7KPSSP.js → chunk-72BIONOT.js} +6 -6
- package/dist/{chunk-XNGS6LUK.js → chunk-AESNEWYR.js} +1 -1
- package/dist/{chunk-LN4WDONI.js → chunk-AVTI3FL5.js} +1 -1
- package/dist/{chunk-5RUH3PCG.js → chunk-B3EE7OKK.js} +4 -4
- package/dist/{chunk-Y3LIJIRH.js → chunk-BJQ25STI.js} +4 -4
- package/dist/{chunk-6TFTRVOA.js → chunk-C3XLVHN6.js} +2 -2
- package/dist/{chunk-OEITN64Z.js → chunk-D7ECJX4J.js} +15 -38
- package/dist/{chunk-UWEJ6HGB.js → chunk-DY7Y7UT4.js} +2 -2
- package/dist/{chunk-AKHGQKNR.js → chunk-E6CO3MJE.js} +34 -2
- package/dist/{chunk-DM4EGXDO.js → chunk-EWVYQLD3.js} +1 -1
- package/dist/{chunk-BUBMAMIP.js → chunk-FQW7TKIU.js} +2 -2
- package/dist/{chunk-KUTZ6XLS.js → chunk-G63KT5I5.js} +1 -1
- package/dist/{chunk-Q2D4M3GC.js → chunk-GFYEMCPP.js} +1 -1
- package/dist/{chunk-4IG6EZHU.js → chunk-HJYBWJAS.js} +2 -2
- package/dist/{chunk-CMTRZC23.js → chunk-HVIYKGK5.js} +79 -12
- package/dist/{chunk-TNJXCNQ6.js → chunk-JHTJPQSL.js} +4 -4
- package/dist/{chunk-RVWADVBN.js → chunk-JZ4FXSLI.js} +3 -3
- package/dist/{chunk-HT7LVCTX.js → chunk-L3DUKDTR.js} +2 -2
- package/dist/{chunk-KDM77TVX.js → chunk-LCVR4UIS.js} +2 -2
- package/dist/{chunk-OGCG5LOX.js → chunk-LJG6EMLJ.js} +1 -1
- package/dist/{chunk-HJEZ3D3E.js → chunk-LWODW66U.js} +16 -16
- package/dist/chunk-MBE6FEQ3.js +111 -0
- package/dist/{chunk-RW52CUFX.js → chunk-NSPRS7WK.js} +1 -1
- package/dist/{chunk-DE7YSNDX.js → chunk-OJ63GRZ2.js} +2 -2
- package/dist/{chunk-Q4YVHYHT.js → chunk-QJNFO7TQ.js} +3 -3
- package/dist/{chunk-NOXK3QW6.js → chunk-QSSYXK6C.js} +3 -3
- package/dist/{chunk-UENWEDZ3.js → chunk-S2IJQER5.js} +255 -255
- package/dist/{chunk-RQKQTRXM.js → chunk-THTBXIK5.js} +4 -4
- package/dist/{chunk-M5OBRUQE.js → chunk-UIUGTW5C.js} +2 -2
- package/dist/{chunk-YH2632RT.js → chunk-V2EUC2MJ.js} +43 -20
- package/dist/{chunk-SFJD4MRY.js → chunk-WHRR55PC.js} +14 -7
- package/dist/{chunk-CALFNNIY.js → chunk-XTBGPISI.js} +17 -6
- package/dist/chunk-YYYRBYWG.js +32 -0
- package/dist/{claude-launcher-STSKZNW3.js → claude-launcher-IUDNUD2J.js} +17 -6
- package/dist/{cli-BMV37UKQ.js → cli-5JSVOAE5.js} +89 -89
- package/dist/{command-35IERXEA.js → command-7IY3XGAG.js} +24 -23
- package/dist/{connect-cmd-WFHAPGCZ.js → connect-cmd-AQSJVDQU.js} +8 -8
- package/dist/{container-start-3FFBFFNK.js → container-start-BPQHJMNF.js} +25 -24
- package/dist/{context-cleanup-UBOJHGQM.js → context-cleanup-BX5Y3AFL.js} +3 -3
- package/dist/{control-plane-launch-R4X63DYW.js → control-plane-launch-K7YD6KEN.js} +6 -6
- package/dist/{dist-ADFLG3AY.js → dist-ACTRIBVW.js} +2 -2
- package/dist/{docker-2NN3EKTR.js → docker-UKJBLZLW.js} +4 -4
- package/dist/{doctor-CA5QQ5KS.js → doctor-JUR62PMF.js} +48 -25
- package/dist/{emit-artifact-cmd-FR5PUUJR.js → emit-artifact-cmd-HI3EYJA3.js} +13 -13
- package/dist/{emit-cmd-JOO6ZTEI.js → emit-cmd-OX6LYS6I.js} +6 -6
- package/dist/{emit-criteria-cmd-DKPZJTIN.js → emit-criteria-cmd-IC5OIZX2.js} +9 -9
- package/dist/{emit-demo-cmd-G2I4SB7A.js → emit-demo-cmd-HWDC3MAK.js} +211 -101
- package/dist/{emit-finding-cmd-VM4KIVEM.js → emit-finding-cmd-A7RBLHTN.js} +10 -10
- package/dist/{emit-result-cmd-SEKL6HUU.js → emit-result-cmd-2WVVAGST.js} +12 -12
- package/dist/{emit-step-cmd-4YAWK4VE.js → emit-step-cmd-KNVHYSXT.js} +10 -10
- package/dist/{findings-cmd-RXYIWXY4.js → findings-cmd-ISP3P3UY.js} +10 -10
- package/dist/{fleet-readiness-VIX76RNL.js → fleet-readiness-O2WAJJVT.js} +8 -8
- package/dist/{governing-source-APGCKDTS.js → governing-source-PMWZJCXJ.js} +13 -13
- package/dist/{guest-init-BI7267TB.js → guest-init-3LNAL3TB.js} +2 -2
- package/dist/{hook-fast-NVBMSE3N.js → hook-fast-FJ2PMBML.js} +1 -1
- package/dist/index.js +4 -4
- package/dist/{init-BZMBUTU4.js → init-YRSKJNSB.js} +25 -24
- package/dist/{init-VPK3MDM5.js → init-ZXV6LILS.js} +26 -25
- package/dist/{init-cmd-PTQ5WSQ5.js → init-cmd-3F436JBW.js} +18 -18
- package/dist/{init-update-HOTJISWA.js → init-update-6OPETOBA.js} +17 -17
- package/dist/{layout-ZI4RJ6MT.js → layout-JGF7MJHG.js} +4 -4
- package/dist/{login-browser-WUSIVD5E.js → login-browser-3RIZQJY2.js} +2 -2
- package/dist/{loop-FDFEXDKA.js → loop-MCR3EUSZ.js} +36 -34
- package/dist/{machine-ZL72TS6B.js → machine-35YQ7MGN.js} +23 -22
- package/dist/{machine-skills-REHDWINX.js → machine-skills-AGERT2HN.js} +4 -4
- package/dist/{runner-identity-DSFLFUR2.js → runner-identity-GO762MHZ.js} +4 -4
- package/dist/{runner-key-XJ7YSMOF.js → runner-key-BQSR6MK4.js} +25 -24
- package/dist/{session-sender-PLQ5NOEW.js → session-sender-ENL3IBVD.js} +13 -13
- package/dist/{spec-cmd-NIAQWMLE.js → spec-cmd-SLJT7MRX.js} +10 -10
- package/dist/{starter-pack-OESK7UX2.js → starter-pack-UBEC5LTE.js} +5 -5
- package/dist/{status-LJ2UBJCE.js → status-GQEAZBUJ.js} +29 -28
- package/dist/{sync-cmd-UTESQMDU.js → sync-cmd-Z4BYKM6K.js} +12 -12
- package/dist/{watch-4UC4FGI5.js → watch-MBEA6QB4.js} +12 -12
- package/dist/{work-claim-cmd-ODYRE44S.js → work-claim-cmd-TLXRPJWO.js} +12 -12
- package/dist/{work-cmd-QQDUI3YX.js → work-cmd-DYM67Z3F.js} +10 -10
- package/dist/{work-comment-cmd-FIOMDPIZ.js → work-comment-cmd-CRRWP3AH.js} +10 -10
- package/dist/{work-logs-cmd-DA6MPQ6O.js → work-logs-cmd-7LFOEVXI.js} +10 -10
- package/dist/{work-open-pr-cmd-QG2FT7OW.js → work-open-pr-cmd-XXQ75PSU.js} +11 -11
- package/dist/{work-pr-cmd-XNXWWLS5.js → work-pr-cmd-ZVE7EGSC.js} +10 -10
- package/dist/{work-stop-cmd-2KLZ2UH2.js → work-stop-cmd-GVFSTGLK.js} +10 -10
- package/package.json +1 -1
- package/skill-pack/maintained/outerlayer-evidence/SKILL.md +8 -5
- package/dist/{chunk-RJYKTWUP.js → chunk-ELYHDWCC.js} +1 -1
|
@@ -1,22 +1,272 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { parseSize } from './chunk-YJLHUKYS.js';
|
|
4
3
|
import { RecipeError } from './chunk-3Z3MPR55.js';
|
|
5
4
|
import { BUILDKIT_IMAGE } from './chunk-R6QCSHKC.js';
|
|
6
|
-
import {
|
|
5
|
+
import { parseSize } from './chunk-YJLHUKYS.js';
|
|
6
|
+
import { compareVersions } from './chunk-5DNCFOXA.js';
|
|
7
7
|
import { ensureHostKey } from './chunk-JT3YO5MH.js';
|
|
8
8
|
import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, runnerDir, jobsDir } from './chunk-ESP5VZBD.js';
|
|
9
9
|
import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-HDSDUTX4.js';
|
|
10
10
|
import { JOIN_DIR, RELAY_ID, JOIN_SOCKET, TARGET_GATEWAY, TARGET_CLAUDE, destinationTarget, RELAY_USER } from './chunk-MESOOLF4.js';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
|
|
13
|
+
import { join, dirname, resolve } from 'path';
|
|
11
14
|
import { StringDecoder } from 'string_decoder';
|
|
12
15
|
import { spawn } from 'child_process';
|
|
13
|
-
import { existsSync, readFileSync, mkdirSync, createWriteStream, rmSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
|
|
14
|
-
import { dirname, join, resolve } from 'path';
|
|
15
|
-
import { createHash } from 'crypto';
|
|
16
16
|
import { createRequire as createRequire$1 } from 'module';
|
|
17
17
|
import { fileURLToPath } from 'url';
|
|
18
18
|
|
|
19
19
|
createRequire(import.meta.url);
|
|
20
|
+
var PACKAGE = "@devcontainers/cli";
|
|
21
|
+
function buildRootFromDist(moduleDir = dirname(fileURLToPath(import.meta.url))) {
|
|
22
|
+
try {
|
|
23
|
+
const info = JSON.parse(readFileSync(join(moduleDir, "build-info.json"), "utf8"));
|
|
24
|
+
return typeof info.root === "string" ? info.root : void 0;
|
|
25
|
+
} catch {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function resolveDevcontainerCli(opts = {}) {
|
|
30
|
+
const resolve2 = opts.resolve ?? createRequire$1(import.meta.url).resolve;
|
|
31
|
+
try {
|
|
32
|
+
const bin = join(dirname(resolve2(`${PACKAGE}/package.json`)), "devcontainer.js");
|
|
33
|
+
if (existsSync(bin)) return { command: process.execPath, args: [bin] };
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
const buildRoot = opts.buildRoot ?? buildRootFromDist();
|
|
37
|
+
const fallback = buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", PACKAGE);
|
|
38
|
+
if (fallback !== void 0 && existsSync(join(fallback, "devcontainer.js"))) {
|
|
39
|
+
return { command: process.execPath, args: [join(fallback, "devcontainer.js")] };
|
|
40
|
+
}
|
|
41
|
+
throw new RecipeError(
|
|
42
|
+
"devcontainer_cli_missing",
|
|
43
|
+
`the devcontainer CLI is not installed: looked beside this package and in ${fallback ?? "the checkout this build came from (unknown)"}. Run yarn install in that checkout.`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
function devcontainerBuildInvocation(cli, req) {
|
|
47
|
+
return {
|
|
48
|
+
command: cli.command,
|
|
49
|
+
args: [
|
|
50
|
+
...cli.args,
|
|
51
|
+
"build",
|
|
52
|
+
"--workspace-folder",
|
|
53
|
+
req.workspace,
|
|
54
|
+
"--config",
|
|
55
|
+
req.config,
|
|
56
|
+
"--image-name",
|
|
57
|
+
req.imageName,
|
|
58
|
+
...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
|
|
59
|
+
"--log-format",
|
|
60
|
+
"text",
|
|
61
|
+
// Written as an OCI layout instead of loaded into Docker: the runner's builder cannot read Docker's image store, so the next layer starts FROM the layout.
|
|
62
|
+
...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/runner/image/docker.ts
|
|
68
|
+
var CHILD_ENVIRONMENT_NAMES = [
|
|
69
|
+
"PATH",
|
|
70
|
+
"HOME",
|
|
71
|
+
"USER",
|
|
72
|
+
"LOGNAME",
|
|
73
|
+
"TMPDIR",
|
|
74
|
+
"LANG",
|
|
75
|
+
"LC_ALL",
|
|
76
|
+
"DOCKER_HOST",
|
|
77
|
+
"DOCKER_CONFIG",
|
|
78
|
+
"DOCKER_CONTEXT",
|
|
79
|
+
"DOCKER_CERT_PATH",
|
|
80
|
+
"DOCKER_TLS_VERIFY",
|
|
81
|
+
"DOCKER_API_VERSION",
|
|
82
|
+
"DOCKER_BUILDKIT",
|
|
83
|
+
// `docker buildx build` fetches registry tokens in the client and hands them to the builder, so a host that reaches
|
|
84
|
+
// registries through a proxy needs it here as well as in the builder.
|
|
85
|
+
"HTTP_PROXY",
|
|
86
|
+
"HTTPS_PROXY",
|
|
87
|
+
"NO_PROXY",
|
|
88
|
+
"http_proxy",
|
|
89
|
+
"https_proxy",
|
|
90
|
+
"no_proxy",
|
|
91
|
+
"XDG_RUNTIME_DIR",
|
|
92
|
+
"XDG_CONFIG_HOME",
|
|
93
|
+
"XDG_DATA_HOME",
|
|
94
|
+
"XDG_CACHE_HOME",
|
|
95
|
+
"XDG_STATE_HOME"
|
|
96
|
+
];
|
|
97
|
+
function childEnvironment(base) {
|
|
98
|
+
const env = {};
|
|
99
|
+
for (const name of CHILD_ENVIRONMENT_NAMES) {
|
|
100
|
+
const value = base[name];
|
|
101
|
+
if (value !== void 0) env[name] = value;
|
|
102
|
+
}
|
|
103
|
+
return env;
|
|
104
|
+
}
|
|
105
|
+
var spawnRun = (command, args, opts = {}) => new Promise((resolve2) => {
|
|
106
|
+
let log;
|
|
107
|
+
if (opts.logPath !== void 0) {
|
|
108
|
+
mkdirSync(dirname(opts.logPath), { recursive: true });
|
|
109
|
+
log = createWriteStream(opts.logPath, { flags: "a" });
|
|
110
|
+
}
|
|
111
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
112
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
113
|
+
let stdout = "";
|
|
114
|
+
let stderr = "";
|
|
115
|
+
let settled = false;
|
|
116
|
+
const finish = (status, extra = "") => {
|
|
117
|
+
if (settled) return;
|
|
118
|
+
settled = true;
|
|
119
|
+
const result = { status, stdout: stdout + stdoutDecoder.end(), stderr: stderr + stderrDecoder.end() + extra };
|
|
120
|
+
if (log === void 0) {
|
|
121
|
+
resolve2(result);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (extra) log.write(extra);
|
|
125
|
+
log.end(() => resolve2(result));
|
|
126
|
+
};
|
|
127
|
+
let timer;
|
|
128
|
+
const child = spawn(command, args, {
|
|
129
|
+
env: { ...childEnvironment(process.env), ...opts.env },
|
|
130
|
+
stdio: [opts.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
|
|
131
|
+
});
|
|
132
|
+
child.stdout.on("data", (chunk) => {
|
|
133
|
+
stdout += stdoutDecoder.write(chunk);
|
|
134
|
+
log?.write(chunk);
|
|
135
|
+
});
|
|
136
|
+
child.stderr.on("data", (chunk) => {
|
|
137
|
+
stderr += stderrDecoder.write(chunk);
|
|
138
|
+
log?.write(chunk);
|
|
139
|
+
});
|
|
140
|
+
if (opts.timeoutMs !== void 0) {
|
|
141
|
+
timer = setTimeout(() => {
|
|
142
|
+
child.kill("SIGKILL");
|
|
143
|
+
finish(124, `${command}: no answer within ${Math.round(opts.timeoutMs / 1e3)}s
|
|
144
|
+
`);
|
|
145
|
+
}, opts.timeoutMs);
|
|
146
|
+
timer.unref();
|
|
147
|
+
}
|
|
148
|
+
child.on("error", (err) => finish(127, `${command}: ${err.message}
|
|
149
|
+
`));
|
|
150
|
+
child.on("close", (code, signal) => {
|
|
151
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
152
|
+
finish(code ?? (signal ? 128 : 1));
|
|
153
|
+
});
|
|
154
|
+
if (opts.input !== void 0) {
|
|
155
|
+
child.stdin.on("error", () => void 0);
|
|
156
|
+
child.stdin.end(opts.input);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
function toInfo(row) {
|
|
160
|
+
return { id: row.Id, createdAt: row.Created, labels: row.Config?.Labels ?? {} };
|
|
161
|
+
}
|
|
162
|
+
var lines = (text) => [...new Set(text.split("\n").map((l) => l.trim()).filter(Boolean))];
|
|
163
|
+
function layoutDigest(layout) {
|
|
164
|
+
const index = JSON.parse(readFileSync(join(layout, "index.json"), "utf8"));
|
|
165
|
+
const digest = index.manifests?.[0]?.digest;
|
|
166
|
+
if (digest === void 0) throw new Error(`${join(layout, "index.json")} lists no image`);
|
|
167
|
+
return digest;
|
|
168
|
+
}
|
|
169
|
+
function outOfMemory(builder, logPath) {
|
|
170
|
+
return new RecipeError(
|
|
171
|
+
"image_build_out_of_memory",
|
|
172
|
+
`the image build ran out of memory: the kernel stopped a build step at the limit of runner.build.memory (${builder.memory}). Raise runner.build.memory, or lower what the recipe's build steps use; the build log is at ${logPath}`,
|
|
173
|
+
logPath
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
function createDockerHost(deps = {}) {
|
|
177
|
+
const run = deps.run ?? spawnRun;
|
|
178
|
+
const cli = deps.cli ?? resolveDevcontainerCli;
|
|
179
|
+
const builderFor = () => {
|
|
180
|
+
if (deps.builder === void 0) {
|
|
181
|
+
throw new Error("no image builder is configured, so the image build was not started: every image build runs in the runner's builder, which carries runner.build.memory");
|
|
182
|
+
}
|
|
183
|
+
return deps.builder;
|
|
184
|
+
};
|
|
185
|
+
const inspectMany = async (refs) => {
|
|
186
|
+
const result = await run("docker", ["image", "inspect", ...refs]);
|
|
187
|
+
return result.status === 0 ? JSON.parse(result.stdout).map(toInfo) : [];
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
async inspect(ref) {
|
|
191
|
+
return (await inspectMany([ref]))[0] ?? null;
|
|
192
|
+
},
|
|
193
|
+
async list(repository) {
|
|
194
|
+
const ids = await run("docker", [
|
|
195
|
+
"image",
|
|
196
|
+
"ls",
|
|
197
|
+
"--all",
|
|
198
|
+
"--no-trunc",
|
|
199
|
+
"--quiet",
|
|
200
|
+
"--filter",
|
|
201
|
+
`label=ai.outerlayer.repository=${repository}`
|
|
202
|
+
]);
|
|
203
|
+
const found = lines(ids.stdout);
|
|
204
|
+
return found.length === 0 ? [] : inspectMany(found);
|
|
205
|
+
},
|
|
206
|
+
async inUse() {
|
|
207
|
+
const containers = lines((await run("docker", ["ps", "--all", "--no-trunc", "--quiet"])).stdout);
|
|
208
|
+
if (containers.length === 0) return [];
|
|
209
|
+
return lines((await run("docker", ["inspect", "--format", "{{.Image}}", ...containers])).stdout);
|
|
210
|
+
},
|
|
211
|
+
async ensureBuilder() {
|
|
212
|
+
const builder = builderFor();
|
|
213
|
+
const result = await ensureBuilder(run, builder, { waitForIdle: true, replaceStale: deps.replaceStaleBuilder });
|
|
214
|
+
if (!result.ok) throw new RecipeError("image_builder_unavailable", `the image builder is unavailable: ${result.problem}`);
|
|
215
|
+
return { name: builder.name, memory: builder.memory };
|
|
216
|
+
},
|
|
217
|
+
async exportLayout(ref, dir) {
|
|
218
|
+
rmSync(dir, { recursive: true, force: true });
|
|
219
|
+
mkdirSync(dir, { recursive: true });
|
|
220
|
+
const archive = join(dir, ".image.tar");
|
|
221
|
+
const saved = await run("docker", ["save", "--output", archive, ref]);
|
|
222
|
+
if (saved.status !== 0) throw new Error(saved.stderr.trim() || `docker save ${ref} exited ${saved.status}`);
|
|
223
|
+
const unpacked = await run("tar", ["-xf", archive, "-C", dir]);
|
|
224
|
+
rmSync(archive, { force: true });
|
|
225
|
+
if (unpacked.status !== 0) throw new Error(unpacked.stderr.trim() || `tar exited ${unpacked.status}`);
|
|
226
|
+
},
|
|
227
|
+
async buildDockerfile(req) {
|
|
228
|
+
const builder = builderFor();
|
|
229
|
+
if (req.layoutOut !== void 0) {
|
|
230
|
+
rmSync(req.layoutOut, { recursive: true, force: true });
|
|
231
|
+
}
|
|
232
|
+
const labels = Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]);
|
|
233
|
+
const args = [
|
|
234
|
+
"buildx",
|
|
235
|
+
"build",
|
|
236
|
+
"--builder",
|
|
237
|
+
builder.name,
|
|
238
|
+
"--load",
|
|
239
|
+
...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`],
|
|
240
|
+
...req.base === void 0 ? [] : ["--build-context", `${req.base.ref}=oci-layout://${req.base.layout}@${layoutDigest(req.base.layout)}`],
|
|
241
|
+
"--tag",
|
|
242
|
+
req.tag,
|
|
243
|
+
...labels,
|
|
244
|
+
"--file",
|
|
245
|
+
"-",
|
|
246
|
+
req.context
|
|
247
|
+
];
|
|
248
|
+
const result = await trackImageBuild(() => run("docker", args, { logPath: req.logPath, input: req.dockerfile }));
|
|
249
|
+
if (result.status !== 0 && isOutOfMemory(`${result.stdout}
|
|
250
|
+
${result.stderr}`)) throw outOfMemory(builder, req.logPath);
|
|
251
|
+
return result.status;
|
|
252
|
+
},
|
|
253
|
+
async devcontainerBuild(req) {
|
|
254
|
+
const builder = builderFor();
|
|
255
|
+
const { command, args } = devcontainerBuildInvocation(cli(), req);
|
|
256
|
+
if (req.layoutOut !== void 0) {
|
|
257
|
+
rmSync(req.layoutOut, { recursive: true, force: true });
|
|
258
|
+
}
|
|
259
|
+
const result = await trackImageBuild(() => run(command, args, { logPath: req.logPath, env: { BUILDX_BUILDER: builder.name } }));
|
|
260
|
+
if (result.status !== 0 && isOutOfMemory(`${result.stdout}
|
|
261
|
+
${result.stderr}`)) throw outOfMemory(builder, req.logPath);
|
|
262
|
+
return result.status;
|
|
263
|
+
},
|
|
264
|
+
async remove(id) {
|
|
265
|
+
const result = await run("docker", ["rmi", id]);
|
|
266
|
+
if (result.status !== 0) throw new Error(result.stderr.trim() || `docker rmi ${id} exited ${result.status}`);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
20
270
|
var ITEM_KEY_FILE = "item-key";
|
|
21
271
|
function itemKeyPath(jobPath) {
|
|
22
272
|
return join(dirname(jobPath), ITEM_KEY_FILE);
|
|
@@ -481,255 +731,5 @@ function ensureBuilder(rawRun, spec, options = {}) {
|
|
|
481
731
|
}
|
|
482
732
|
);
|
|
483
733
|
}
|
|
484
|
-
var PACKAGE = "@devcontainers/cli";
|
|
485
|
-
function buildRootFromDist(moduleDir = dirname(fileURLToPath(import.meta.url))) {
|
|
486
|
-
try {
|
|
487
|
-
const info = JSON.parse(readFileSync(join(moduleDir, "build-info.json"), "utf8"));
|
|
488
|
-
return typeof info.root === "string" ? info.root : void 0;
|
|
489
|
-
} catch {
|
|
490
|
-
return void 0;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
function resolveDevcontainerCli(opts = {}) {
|
|
494
|
-
const resolve2 = opts.resolve ?? createRequire$1(import.meta.url).resolve;
|
|
495
|
-
try {
|
|
496
|
-
const bin = join(dirname(resolve2(`${PACKAGE}/package.json`)), "devcontainer.js");
|
|
497
|
-
if (existsSync(bin)) return { command: process.execPath, args: [bin] };
|
|
498
|
-
} catch {
|
|
499
|
-
}
|
|
500
|
-
const buildRoot = opts.buildRoot ?? buildRootFromDist();
|
|
501
|
-
const fallback = buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", PACKAGE);
|
|
502
|
-
if (fallback !== void 0 && existsSync(join(fallback, "devcontainer.js"))) {
|
|
503
|
-
return { command: process.execPath, args: [join(fallback, "devcontainer.js")] };
|
|
504
|
-
}
|
|
505
|
-
throw new RecipeError(
|
|
506
|
-
"devcontainer_cli_missing",
|
|
507
|
-
`the devcontainer CLI is not installed: looked beside this package and in ${fallback ?? "the checkout this build came from (unknown)"}. Run yarn install in that checkout.`
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
function devcontainerBuildInvocation(cli, req) {
|
|
511
|
-
return {
|
|
512
|
-
command: cli.command,
|
|
513
|
-
args: [
|
|
514
|
-
...cli.args,
|
|
515
|
-
"build",
|
|
516
|
-
"--workspace-folder",
|
|
517
|
-
req.workspace,
|
|
518
|
-
"--config",
|
|
519
|
-
req.config,
|
|
520
|
-
"--image-name",
|
|
521
|
-
req.imageName,
|
|
522
|
-
...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
|
|
523
|
-
"--log-format",
|
|
524
|
-
"text",
|
|
525
|
-
// Written as an OCI layout instead of loaded into Docker: the runner's builder cannot read Docker's image store, so the next layer starts FROM the layout.
|
|
526
|
-
...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
|
|
527
|
-
]
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// src/runner/image/docker.ts
|
|
532
|
-
var CHILD_ENVIRONMENT_NAMES = [
|
|
533
|
-
"PATH",
|
|
534
|
-
"HOME",
|
|
535
|
-
"USER",
|
|
536
|
-
"LOGNAME",
|
|
537
|
-
"TMPDIR",
|
|
538
|
-
"LANG",
|
|
539
|
-
"LC_ALL",
|
|
540
|
-
"DOCKER_HOST",
|
|
541
|
-
"DOCKER_CONFIG",
|
|
542
|
-
"DOCKER_CONTEXT",
|
|
543
|
-
"DOCKER_CERT_PATH",
|
|
544
|
-
"DOCKER_TLS_VERIFY",
|
|
545
|
-
"DOCKER_API_VERSION",
|
|
546
|
-
"DOCKER_BUILDKIT",
|
|
547
|
-
// `docker buildx build` fetches registry tokens in the client and hands them to the builder, so a host that reaches
|
|
548
|
-
// registries through a proxy needs it here as well as in the builder.
|
|
549
|
-
"HTTP_PROXY",
|
|
550
|
-
"HTTPS_PROXY",
|
|
551
|
-
"NO_PROXY",
|
|
552
|
-
"http_proxy",
|
|
553
|
-
"https_proxy",
|
|
554
|
-
"no_proxy",
|
|
555
|
-
"XDG_RUNTIME_DIR",
|
|
556
|
-
"XDG_CONFIG_HOME",
|
|
557
|
-
"XDG_DATA_HOME",
|
|
558
|
-
"XDG_CACHE_HOME",
|
|
559
|
-
"XDG_STATE_HOME"
|
|
560
|
-
];
|
|
561
|
-
function childEnvironment(base) {
|
|
562
|
-
const env = {};
|
|
563
|
-
for (const name of CHILD_ENVIRONMENT_NAMES) {
|
|
564
|
-
const value = base[name];
|
|
565
|
-
if (value !== void 0) env[name] = value;
|
|
566
|
-
}
|
|
567
|
-
return env;
|
|
568
|
-
}
|
|
569
|
-
var spawnRun = (command, args, opts = {}) => new Promise((resolve2) => {
|
|
570
|
-
let log;
|
|
571
|
-
if (opts.logPath !== void 0) {
|
|
572
|
-
mkdirSync(dirname(opts.logPath), { recursive: true });
|
|
573
|
-
log = createWriteStream(opts.logPath, { flags: "a" });
|
|
574
|
-
}
|
|
575
|
-
const stdoutDecoder = new StringDecoder("utf8");
|
|
576
|
-
const stderrDecoder = new StringDecoder("utf8");
|
|
577
|
-
let stdout = "";
|
|
578
|
-
let stderr = "";
|
|
579
|
-
let settled = false;
|
|
580
|
-
const finish = (status, extra = "") => {
|
|
581
|
-
if (settled) return;
|
|
582
|
-
settled = true;
|
|
583
|
-
const result = { status, stdout: stdout + stdoutDecoder.end(), stderr: stderr + stderrDecoder.end() + extra };
|
|
584
|
-
if (log === void 0) {
|
|
585
|
-
resolve2(result);
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
if (extra) log.write(extra);
|
|
589
|
-
log.end(() => resolve2(result));
|
|
590
|
-
};
|
|
591
|
-
let timer;
|
|
592
|
-
const child = spawn(command, args, {
|
|
593
|
-
env: { ...childEnvironment(process.env), ...opts.env },
|
|
594
|
-
stdio: [opts.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
|
|
595
|
-
});
|
|
596
|
-
child.stdout.on("data", (chunk) => {
|
|
597
|
-
stdout += stdoutDecoder.write(chunk);
|
|
598
|
-
log?.write(chunk);
|
|
599
|
-
});
|
|
600
|
-
child.stderr.on("data", (chunk) => {
|
|
601
|
-
stderr += stderrDecoder.write(chunk);
|
|
602
|
-
log?.write(chunk);
|
|
603
|
-
});
|
|
604
|
-
if (opts.timeoutMs !== void 0) {
|
|
605
|
-
timer = setTimeout(() => {
|
|
606
|
-
child.kill("SIGKILL");
|
|
607
|
-
finish(124, `${command}: no answer within ${Math.round(opts.timeoutMs / 1e3)}s
|
|
608
|
-
`);
|
|
609
|
-
}, opts.timeoutMs);
|
|
610
|
-
timer.unref();
|
|
611
|
-
}
|
|
612
|
-
child.on("error", (err) => finish(127, `${command}: ${err.message}
|
|
613
|
-
`));
|
|
614
|
-
child.on("close", (code, signal) => {
|
|
615
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
616
|
-
finish(code ?? (signal ? 128 : 1));
|
|
617
|
-
});
|
|
618
|
-
if (opts.input !== void 0) {
|
|
619
|
-
child.stdin.on("error", () => void 0);
|
|
620
|
-
child.stdin.end(opts.input);
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
function toInfo(row) {
|
|
624
|
-
return { id: row.Id, createdAt: row.Created, labels: row.Config?.Labels ?? {} };
|
|
625
|
-
}
|
|
626
|
-
var lines = (text) => [...new Set(text.split("\n").map((l) => l.trim()).filter(Boolean))];
|
|
627
|
-
function layoutDigest(layout) {
|
|
628
|
-
const index = JSON.parse(readFileSync(join(layout, "index.json"), "utf8"));
|
|
629
|
-
const digest = index.manifests?.[0]?.digest;
|
|
630
|
-
if (digest === void 0) throw new Error(`${join(layout, "index.json")} lists no image`);
|
|
631
|
-
return digest;
|
|
632
|
-
}
|
|
633
|
-
function outOfMemory(builder, logPath) {
|
|
634
|
-
return new RecipeError(
|
|
635
|
-
"image_build_out_of_memory",
|
|
636
|
-
`the image build ran out of memory: the kernel stopped a build step at the limit of runner.build.memory (${builder.memory}). Raise runner.build.memory, or lower what the recipe's build steps use; the build log is at ${logPath}`,
|
|
637
|
-
logPath
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
function createDockerHost(deps = {}) {
|
|
641
|
-
const run = deps.run ?? spawnRun;
|
|
642
|
-
const cli = deps.cli ?? resolveDevcontainerCli;
|
|
643
|
-
const builderFor = () => {
|
|
644
|
-
if (deps.builder === void 0) {
|
|
645
|
-
throw new Error("no image builder is configured, so the image build was not started: every image build runs in the runner's builder, which carries runner.build.memory");
|
|
646
|
-
}
|
|
647
|
-
return deps.builder;
|
|
648
|
-
};
|
|
649
|
-
const inspectMany = async (refs) => {
|
|
650
|
-
const result = await run("docker", ["image", "inspect", ...refs]);
|
|
651
|
-
return result.status === 0 ? JSON.parse(result.stdout).map(toInfo) : [];
|
|
652
|
-
};
|
|
653
|
-
return {
|
|
654
|
-
async inspect(ref) {
|
|
655
|
-
return (await inspectMany([ref]))[0] ?? null;
|
|
656
|
-
},
|
|
657
|
-
async list(repository) {
|
|
658
|
-
const ids = await run("docker", [
|
|
659
|
-
"image",
|
|
660
|
-
"ls",
|
|
661
|
-
"--all",
|
|
662
|
-
"--no-trunc",
|
|
663
|
-
"--quiet",
|
|
664
|
-
"--filter",
|
|
665
|
-
`label=ai.outerlayer.repository=${repository}`
|
|
666
|
-
]);
|
|
667
|
-
const found = lines(ids.stdout);
|
|
668
|
-
return found.length === 0 ? [] : inspectMany(found);
|
|
669
|
-
},
|
|
670
|
-
async inUse() {
|
|
671
|
-
const containers = lines((await run("docker", ["ps", "--all", "--no-trunc", "--quiet"])).stdout);
|
|
672
|
-
if (containers.length === 0) return [];
|
|
673
|
-
return lines((await run("docker", ["inspect", "--format", "{{.Image}}", ...containers])).stdout);
|
|
674
|
-
},
|
|
675
|
-
async ensureBuilder() {
|
|
676
|
-
const builder = builderFor();
|
|
677
|
-
const result = await ensureBuilder(run, builder, { waitForIdle: true, replaceStale: deps.replaceStaleBuilder });
|
|
678
|
-
if (!result.ok) throw new RecipeError("image_builder_unavailable", `the image builder is unavailable: ${result.problem}`);
|
|
679
|
-
return { name: builder.name, memory: builder.memory };
|
|
680
|
-
},
|
|
681
|
-
async exportLayout(ref, dir) {
|
|
682
|
-
rmSync(dir, { recursive: true, force: true });
|
|
683
|
-
mkdirSync(dir, { recursive: true });
|
|
684
|
-
const archive = join(dir, ".image.tar");
|
|
685
|
-
const saved = await run("docker", ["save", "--output", archive, ref]);
|
|
686
|
-
if (saved.status !== 0) throw new Error(saved.stderr.trim() || `docker save ${ref} exited ${saved.status}`);
|
|
687
|
-
const unpacked = await run("tar", ["-xf", archive, "-C", dir]);
|
|
688
|
-
rmSync(archive, { force: true });
|
|
689
|
-
if (unpacked.status !== 0) throw new Error(unpacked.stderr.trim() || `tar exited ${unpacked.status}`);
|
|
690
|
-
},
|
|
691
|
-
async buildDockerfile(req) {
|
|
692
|
-
const builder = builderFor();
|
|
693
|
-
if (req.layoutOut !== void 0) {
|
|
694
|
-
rmSync(req.layoutOut, { recursive: true, force: true });
|
|
695
|
-
}
|
|
696
|
-
const labels = Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]);
|
|
697
|
-
const args = [
|
|
698
|
-
"buildx",
|
|
699
|
-
"build",
|
|
700
|
-
"--builder",
|
|
701
|
-
builder.name,
|
|
702
|
-
"--load",
|
|
703
|
-
...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`],
|
|
704
|
-
...req.base === void 0 ? [] : ["--build-context", `${req.base.ref}=oci-layout://${req.base.layout}@${layoutDigest(req.base.layout)}`],
|
|
705
|
-
"--tag",
|
|
706
|
-
req.tag,
|
|
707
|
-
...labels,
|
|
708
|
-
"--file",
|
|
709
|
-
"-",
|
|
710
|
-
req.context
|
|
711
|
-
];
|
|
712
|
-
const result = await trackImageBuild(() => run("docker", args, { logPath: req.logPath, input: req.dockerfile }));
|
|
713
|
-
if (result.status !== 0 && isOutOfMemory(`${result.stdout}
|
|
714
|
-
${result.stderr}`)) throw outOfMemory(builder, req.logPath);
|
|
715
|
-
return result.status;
|
|
716
|
-
},
|
|
717
|
-
async devcontainerBuild(req) {
|
|
718
|
-
const builder = builderFor();
|
|
719
|
-
const { command, args } = devcontainerBuildInvocation(cli(), req);
|
|
720
|
-
if (req.layoutOut !== void 0) {
|
|
721
|
-
rmSync(req.layoutOut, { recursive: true, force: true });
|
|
722
|
-
}
|
|
723
|
-
const result = await trackImageBuild(() => run(command, args, { logPath: req.logPath, env: { BUILDX_BUILDER: builder.name } }));
|
|
724
|
-
if (result.status !== 0 && isOutOfMemory(`${result.stdout}
|
|
725
|
-
${result.stderr}`)) throw outOfMemory(builder, req.logPath);
|
|
726
|
-
return result.status;
|
|
727
|
-
},
|
|
728
|
-
async remove(id) {
|
|
729
|
-
const result = await run("docker", ["rmi", id]);
|
|
730
|
-
if (result.status !== 0) throw new Error(result.stderr.trim() || `docker rmi ${id} exited ${result.status}`);
|
|
731
|
-
}
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
734
|
|
|
735
735
|
export { BUILD_LABEL, COMMAND_DIR, HASH_ARGV, JUDGE_DIR, JUDGE_ITEMS, JUDGE_MAX_TURNS, JUDGE_PROGRAM, JUDGE_REPORT, MAX_ITEMS_BYTES, MAX_REPORT_BYTES, MIN_BUILDX_VERSION, RUNNER_LABEL, builderName, builderNameFor, builderSpec, buildxState, childEnvironment, containerExecArgs, containerRunArgs, createDockerHost, dockerIdentity, ensureBuilder, ensureFailureCount, ensureRunnerIdentity, isOutOfMemory, judgeCommand, parseProgramHash, pathLabelValue, prepareRunArgs, proxyEnvironment, readJobFile, readJobFileChecked, readRunnerIdentity, resolveDevcontainerCli, runnerLabelValue, spawnRun, trackImageBuild, withAnswerProtocol, writeJobFile };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { launchRefusalForSession } from './chunk-ESVW4MJY.js';
|
|
4
|
-
import { autoConnect, detectActiveSession } from './chunk-
|
|
5
|
-
import { acquireSpoolLockAt } from './chunk-
|
|
6
|
-
import { resolveRepoIdentity } from './chunk-
|
|
4
|
+
import { autoConnect, detectActiveSession } from './chunk-C3XLVHN6.js';
|
|
5
|
+
import { acquireSpoolLockAt } from './chunk-EWVYQLD3.js';
|
|
6
|
+
import { resolveRepoIdentity } from './chunk-5DNCFOXA.js';
|
|
7
7
|
import { C } from './chunk-ANPNT6PM.js';
|
|
8
8
|
import { resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-VQ2JGZSC.js';
|
|
9
9
|
import { launchedItemForSession } from './chunk-T2Q7ISPE.js';
|
|
10
10
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
11
|
-
import { StepNameSchema, StepBodySchema } from './chunk-
|
|
11
|
+
import { StepNameSchema, StepBodySchema } from './chunk-E6CO3MJE.js';
|
|
12
12
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
13
13
|
import { randomUUID } from 'crypto';
|
|
14
14
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, renameSync, appendFileSync } from 'fs';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-
|
|
3
|
+
import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-G63KT5I5.js';
|
|
4
4
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
5
|
-
import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-
|
|
5
|
+
import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-LJG6EMLJ.js';
|
|
6
6
|
import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
|
|
7
7
|
import { join, dirname, relative, sep } from 'path';
|
|
8
8
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { staleBuildRefusal, staleBuildWarning, detectCi } from './chunk-
|
|
3
|
+
import { staleBuildRefusal, staleBuildWarning, detectCi } from './chunk-WHRR55PC.js';
|
|
4
4
|
import { launchRefusalForSession } from './chunk-ESVW4MJY.js';
|
|
5
|
-
import { detectActiveSession, autoConnect } from './chunk-
|
|
6
|
-
import { readEffectiveArtifactSpoolState, localArtifactIds, isArtifactTombstoned, artifactBlobsDir, appendArtifactRecord, artifactsSpoolPath, findPendingArtifactRecord, sanitizeTerminal, appendArtifactTombstone } from './chunk-
|
|
7
|
-
import { resolveRepoIdentity } from './chunk-
|
|
5
|
+
import { detectActiveSession, autoConnect } from './chunk-C3XLVHN6.js';
|
|
6
|
+
import { readEffectiveArtifactSpoolState, localArtifactIds, isArtifactTombstoned, artifactBlobsDir, appendArtifactRecord, artifactsSpoolPath, findPendingArtifactRecord, sanitizeTerminal, appendArtifactTombstone } from './chunk-EWVYQLD3.js';
|
|
7
|
+
import { resolveRepoIdentity } from './chunk-5DNCFOXA.js';
|
|
8
8
|
import { C } from './chunk-ANPNT6PM.js';
|
|
9
9
|
import { resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-VQ2JGZSC.js';
|
|
10
10
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
11
11
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
12
|
-
import { ARTIFACT_MAX_CAPTION_LENGTH, ArtifactCriterionIdSchema, ARTIFACT_MAX_BYTES, ARTIFACT_MAX_FILENAME_LENGTH, mediaTypeForArtifactPath, inferArtifactKind, ARTIFACT_MAX_REPLACES_TARGETS, parseTestSelector, parseJunit, bindTests } from './chunk-
|
|
12
|
+
import { ARTIFACT_MAX_CAPTION_LENGTH, ArtifactCriterionIdSchema, ARTIFACT_MAX_BYTES, ARTIFACT_MAX_FILENAME_LENGTH, mediaTypeForArtifactPath, inferArtifactKind, ARTIFACT_MAX_REPLACES_TARGETS, parseTestSelector, parseJunit, bindTests } from './chunk-E6CO3MJE.js';
|
|
13
13
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
14
14
|
import { createHash, randomUUID } from 'crypto';
|
|
15
15
|
import { statSync, readFileSync, mkdirSync, existsSync, writeFileSync, renameSync, unlinkSync } from 'fs';
|
|
@@ -116,6 +116,14 @@ function checkTestResults(params) {
|
|
|
116
116
|
}
|
|
117
117
|
return selection.length > 0 ? selection : void 0;
|
|
118
118
|
}
|
|
119
|
+
async function refusalCode(response) {
|
|
120
|
+
try {
|
|
121
|
+
const body = await response.clone().json();
|
|
122
|
+
return typeof body.error?.code === "string" ? body.error.code : void 0;
|
|
123
|
+
} catch {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
119
127
|
async function runEmitArtifact(opts) {
|
|
120
128
|
const env = opts.env ?? process.env;
|
|
121
129
|
const refusal = staleBuildRefusal(env);
|
|
@@ -178,7 +186,7 @@ async function runEmitArtifact(opts) {
|
|
|
178
186
|
`artifact exceeds 8 MiB (${(bytes.length / (1024 * 1024)).toFixed(1)} MiB) \u2014 the gateway refuses larger uploads`
|
|
179
187
|
);
|
|
180
188
|
}
|
|
181
|
-
const filename = basename(filePath);
|
|
189
|
+
const filename = opts.filename ?? basename(filePath);
|
|
182
190
|
if (filename.length > ARTIFACT_MAX_FILENAME_LENGTH) {
|
|
183
191
|
throw new EmitArtifactError(
|
|
184
192
|
`filename is ${filename.length} characters \u2014 the cap is ${ARTIFACT_MAX_FILENAME_LENGTH}`
|
|
@@ -216,6 +224,9 @@ async function runEmitArtifact(opts) {
|
|
|
216
224
|
}
|
|
217
225
|
const mediaType = opts.mediaType ?? mediaTypeForArtifactPath(filePath);
|
|
218
226
|
const kind = inferArtifactKind(mediaType);
|
|
227
|
+
if (opts.range !== void 0 && kind !== "video") {
|
|
228
|
+
throw new EmitArtifactError(`a range applies to a video, but ${opts.file} is ${kind === "file" ? "not a video" : `a ${kind}`}`);
|
|
229
|
+
}
|
|
219
230
|
const tests = checkTestResults({
|
|
220
231
|
file: opts.file,
|
|
221
232
|
bytes,
|
|
@@ -264,7 +275,9 @@ async function runEmitArtifact(opts) {
|
|
|
264
275
|
...criterionId !== void 0 ? { criterionId } : {},
|
|
265
276
|
...replacesTargets !== void 0 ? { replaces: replacesTargets[0] } : {},
|
|
266
277
|
...replacesTargets !== void 0 && replacesTargets.length > 1 ? { replacesTargets } : {},
|
|
267
|
-
...tests !== void 0 ? { tests } : {}
|
|
278
|
+
...tests !== void 0 ? { tests } : {},
|
|
279
|
+
...opts.range !== void 0 ? { range: opts.range } : {},
|
|
280
|
+
...opts.blobOptional === true ? { blobOptional: true } : {}
|
|
268
281
|
};
|
|
269
282
|
try {
|
|
270
283
|
appendArtifactRecord(record, home);
|
|
@@ -331,25 +344,35 @@ async function runEmitArtifact(opts) {
|
|
|
331
344
|
...commitSha !== void 0 ? { commitSha } : {},
|
|
332
345
|
...directTargets !== void 0 && directTargets.length > 0 ? { replaces: directTargets[0] } : {},
|
|
333
346
|
...directTargets !== void 0 && directTargets.length > 1 ? { replacesTargets: directTargets } : {},
|
|
334
|
-
...tests !== void 0 ? { tests } : {}
|
|
347
|
+
...tests !== void 0 ? { tests } : {},
|
|
348
|
+
...opts.range !== void 0 ? { range: opts.range } : {}
|
|
335
349
|
},
|
|
336
350
|
blob: { data: bytes.toString("base64") }
|
|
337
351
|
};
|
|
338
352
|
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
339
353
|
const endpoint = new URL("/v1/artifacts", url).toString();
|
|
354
|
+
const post = async (body) => {
|
|
355
|
+
try {
|
|
356
|
+
return await fetchImpl(endpoint, {
|
|
357
|
+
method: "POST",
|
|
358
|
+
headers: {
|
|
359
|
+
"content-type": "application/json",
|
|
360
|
+
authorization: `Bearer ${apiKey}`,
|
|
361
|
+
"x-outerlayer-app-id": appId
|
|
362
|
+
},
|
|
363
|
+
body: JSON.stringify(body)
|
|
364
|
+
});
|
|
365
|
+
} catch (err) {
|
|
366
|
+
throw new EmitArtifactError(`network error reaching ${endpoint}: ${String(err)}`);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
340
369
|
let response;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
"x-outerlayer-app-id": appId
|
|
348
|
-
},
|
|
349
|
-
body: JSON.stringify(request)
|
|
350
|
-
});
|
|
351
|
-
} catch (err) {
|
|
352
|
-
throw new EmitArtifactError(`network error reaching ${endpoint}: ${String(err)}`);
|
|
370
|
+
if (opts.blobOptional === true) {
|
|
371
|
+
const { blob: _blob, ...withoutBlob } = request;
|
|
372
|
+
response = await post(withoutBlob);
|
|
373
|
+
if (response.status === 409 && await refusalCode(response) === "blob_required") response = await post(request);
|
|
374
|
+
} else {
|
|
375
|
+
response = await post(request);
|
|
353
376
|
}
|
|
354
377
|
if (response.status === 401) {
|
|
355
378
|
throw new EmitArtifactError(
|