@outerlayer/cli 0.4.1 → 0.5.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 +16 -0
- package/dist/{build-TZUUTRGH.js → build-PAEKVYVK.js} +1 -1
- package/dist/build-info.json +1 -1
- package/dist/{check-7MFH6HNC.js → check-4Q33B5ZE.js} +15 -13
- package/dist/{chunk-5Y3QQRUH.js → chunk-3DD6AOWC.js} +37 -0
- package/dist/{chunk-RFUPN6KX.js → chunk-CHLVJNTE.js} +5 -5
- package/dist/{chunk-SY4GK4SP.js → chunk-D2KWEAN6.js} +1 -1
- package/dist/{chunk-LT5TZHYH.js → chunk-EGABNHZG.js} +3 -3
- package/dist/{chunk-4C4THABW.js → chunk-EX6M5JPR.js} +31 -29
- package/dist/{chunk-QY22NZUW.js → chunk-F4NU4H3V.js} +401 -20
- package/dist/{chunk-TWNWNS2Q.js → chunk-H4CK2YK4.js} +8 -8
- package/dist/{chunk-7WERLFVR.js → chunk-JLDZTG3A.js} +1 -1
- package/dist/{chunk-Y7KJLXYN.js → chunk-OR6AEEDO.js} +3 -3
- package/dist/{chunk-W5FVUZXV.js → chunk-RMAZ2NWA.js} +2 -2
- package/dist/{chunk-3TFPDVTI.js → chunk-RTXKYLCA.js} +2 -2
- package/dist/{chunk-HZRNMGLF.js → chunk-T52PKE2Y.js} +144 -127
- package/dist/chunk-UGP76IZ5.js +34 -0
- package/dist/{chunk-DM3VFDS3.js → chunk-UWH5DSUP.js} +32 -20
- package/dist/{chunk-YFHIIH4B.js → chunk-W7UTFZDH.js} +2 -2
- package/dist/{chunk-WFJ65NUD.js → chunk-WOBNRVQT.js} +1 -1
- package/dist/chunk-YYYRBYWG.js +32 -0
- package/dist/{chunk-ZNA27WEV.js → chunk-Z62HNKEJ.js} +3 -3
- package/dist/{chunk-LYCDNMOH.js → chunk-ZOC7JSYC.js} +1 -1
- package/dist/{chunk-QDQEUVUF.js → chunk-ZXBITXTS.js} +1 -1
- package/dist/{cli-W62AFRSW.js → cli-LHSUYYMI.js} +56 -51
- package/dist/{config-XVJYZ4IQ.js → config-HL2AIR3K.js} +1 -1
- package/dist/{connect-cmd-ZTJONP37.js → connect-cmd-OJBFHZWP.js} +4 -4
- package/dist/{dist-44CQVWGT.js → dist-WDV7U7UJ.js} +1 -1
- package/dist/{doctor-ZLGZYMDK.js → doctor-MOA3RIEP.js} +23 -9
- package/dist/{emit-artifact-cmd-AKZP7TMF.js → emit-artifact-cmd-FDWYKURA.js} +4 -4
- package/dist/{emit-criteria-cmd-7MXQVCKD.js → emit-criteria-cmd-OCXHLK34.js} +1 -1
- package/dist/{emit-finding-cmd-N2FTGCVC.js → emit-finding-cmd-POW7PKIA.js} +1 -1
- package/dist/{emit-result-cmd-4CPDBMN2.js → emit-result-cmd-ID35SH53.js} +4 -4
- package/dist/index.js +1 -1
- package/dist/{init-XXEKWZQP.js → init-2IPOIXJV.js} +8 -8
- package/dist/{init-55Y4LHWF.js → init-FYDJAKTM.js} +7 -7
- package/dist/{init-cmd-WLST2F7G.js → init-cmd-KLIDRVXQ.js} +6 -6
- package/dist/{loop-JFIBP4B7.js → loop-NEBUGD2Q.js} +12 -10
- package/dist/{machine-ZBPT2J3R.js → machine-ECU3QCZD.js} +6 -6
- package/dist/record-C43U4PKS.js +7 -0
- package/dist/{status-UJXWZRN5.js → status-CLATHCTQ.js} +27 -9
- package/dist/{sync-cmd-4G4A7EVN.js → sync-cmd-SWQ5KLPL.js} +4 -4
- package/dist/{watch-7SKJKGAA.js → watch-3YW6Z3DQ.js} +4 -4
- package/dist/{work-claim-cmd-5F7VZ42N.js → work-claim-cmd-3OPWA77E.js} +6 -6
- package/dist/{work-cmd-QAUZ7MTD.js → work-cmd-NUR4CAG6.js} +3 -3
- package/dist/{work-comment-cmd-BNCSBTLH.js → work-comment-cmd-6TTTYGHM.js} +3 -3
- package/dist/{work-open-pr-cmd-VFYZHIIW.js → work-open-pr-cmd-KZ7QQFLD.js} +4 -4
- package/dist/{work-pr-cmd-PV32ZLSI.js → work-pr-cmd-QNUBE6IQ.js} +2 -2
- package/package.json +1 -1
- package/skill-pack/maintained/emitting-evidence/SKILL.md +4 -4
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { LEASE_SECONDS, releaseLease, isUnfinished, writeJobFile, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, readJobFile, hookLimitsFor } from './chunk-
|
|
4
|
-
import { RUNNER_PROTOCOL } from './chunk-
|
|
3
|
+
import { LEASE_SECONDS, releaseLease, isUnfinished, writeJobFile, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, readJobFile, hookLimitsFor, readJobFileChecked, ALREADY_RELEASED } from './chunk-UWH5DSUP.js';
|
|
4
|
+
import { RUNNER_PROTOCOL } from './chunk-ZXBITXTS.js';
|
|
5
|
+
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
|
|
5
6
|
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-ABIWDUMS.js';
|
|
6
7
|
import { readMarker, currentVersion, removeMarker, writeMarker, entryIn, versionDir, switchCurrent, cleanVersions, isInLayout, startedThroughCurrent, stagingDir } from './chunk-YYYXRJUW.js';
|
|
8
|
+
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
7
9
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
8
|
-
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, formatClock, measureDisk, createRunnerLog, ensureTunnel, keepGhConfigCurrent, createContainerRuntime } from './chunk-
|
|
10
|
+
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, formatClock, measureDisk, createRunnerLog, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, runnerLabelValue, BUILD_LABEL, RUNNER_LABEL } from './chunk-T52PKE2Y.js';
|
|
9
11
|
import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
+
import { spawnRun } from './chunk-774HEQL6.js';
|
|
13
|
+
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-RMAZ2NWA.js';
|
|
14
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-3DD6AOWC.js';
|
|
12
15
|
import { exceedsDisk } from './chunk-F6GFZXZ3.js';
|
|
13
16
|
import { parseClaimIdentity, sharedUserEnvironment, JOB_MOUNT } from './chunk-AUFG23AA.js';
|
|
14
17
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
15
18
|
import { loadHostKey, ensureHostKey, signerFor } from './chunk-M5POMKKW.js';
|
|
16
|
-
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
19
|
+
import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, spoolDir, RUNNER_FILE_MODE, rootfsDir } from './chunk-ZM2IMMYN.js';
|
|
17
20
|
import { HOOKS_DIR_NAME, writeCommitHooks } from './chunk-XCCLFVXM.js';
|
|
18
21
|
import { randomBytes } from 'crypto';
|
|
19
|
-
import { mkdirSync, existsSync, chmodSync, statSync, readdirSync, readFileSync, rmSync, renameSync, writeFileSync } from 'fs';
|
|
22
|
+
import { mkdirSync, existsSync, chmodSync, statSync, readdirSync, readFileSync, rmSync, renameSync, writeFileSync, lstatSync } from 'fs';
|
|
20
23
|
import { join, dirname } from 'path';
|
|
21
24
|
|
|
22
25
|
createRequire(import.meta.url);
|
|
@@ -68,7 +71,9 @@ async function sendHeartbeat(args, fetchImpl) {
|
|
|
68
71
|
outcome: args.lastUpdate.outcome,
|
|
69
72
|
reason: args.lastUpdate.reason,
|
|
70
73
|
...args.lastUpdate.at !== void 0 ? { at: args.lastUpdate.at } : {}
|
|
71
|
-
}
|
|
74
|
+
},
|
|
75
|
+
// Free disk on the runner's file system, in bytes. Sent only while held, so a host with room sends nothing about its disk.
|
|
76
|
+
lowDisk: args.lowDisk === void 0 ? void 0 : { free: args.lowDisk.free, needed: args.lowDisk.needed }
|
|
72
77
|
};
|
|
73
78
|
try {
|
|
74
79
|
const response = await postJson(
|
|
@@ -371,9 +376,9 @@ function retryFailure(version, err) {
|
|
|
371
376
|
}
|
|
372
377
|
return { outcome: "retrying", reason: messageOf(err) };
|
|
373
378
|
}
|
|
374
|
-
function finish(args,
|
|
375
|
-
let update = { from: args.own, to: args.version, outcome:
|
|
376
|
-
if (
|
|
379
|
+
function finish(args, failure2) {
|
|
380
|
+
let update = { from: args.own, to: args.version, outcome: failure2.outcome, reason: failure2.reason, at: isoAt(args.now) };
|
|
381
|
+
if (failure2.outcome === "retrying") {
|
|
377
382
|
const previous = readLastUpdate(args.configPath);
|
|
378
383
|
const attempts = previous?.to === args.version && previous.outcome === "retrying" ? (previous.attempts ?? 1) + 1 : 1;
|
|
379
384
|
update = { ...update, attempts };
|
|
@@ -383,16 +388,16 @@ function finish(args, failure) {
|
|
|
383
388
|
} catch (err) {
|
|
384
389
|
args.log.error(`could not record the update attempt: ${messageOf(err)}`);
|
|
385
390
|
}
|
|
386
|
-
if (
|
|
391
|
+
if (failure2.outcome === "retrying") {
|
|
387
392
|
return {
|
|
388
393
|
kind: "retrying",
|
|
389
|
-
reason:
|
|
390
|
-
detail:
|
|
394
|
+
reason: failure2.reason,
|
|
395
|
+
detail: failure2.detail ?? failure2.reason,
|
|
391
396
|
attempts: update.attempts ?? 1,
|
|
392
397
|
retryAtMs: retryAfterMs(update)
|
|
393
398
|
};
|
|
394
399
|
}
|
|
395
|
-
return { kind: "failed", outcome:
|
|
400
|
+
return { kind: "failed", outcome: failure2.outcome, reason: failure2.reason };
|
|
396
401
|
}
|
|
397
402
|
async function earlyFailure(args) {
|
|
398
403
|
const current = currentVersion(args.configPath);
|
|
@@ -423,8 +428,8 @@ async function earlyFailure(args) {
|
|
|
423
428
|
return void 0;
|
|
424
429
|
}
|
|
425
430
|
async function preflightUpdate(args) {
|
|
426
|
-
const
|
|
427
|
-
return
|
|
431
|
+
const failure2 = await earlyFailure(args);
|
|
432
|
+
return failure2 === void 0 ? void 0 : finish(args, failure2);
|
|
428
433
|
}
|
|
429
434
|
async function performUpdate(args) {
|
|
430
435
|
const { configPath, own, version, deps } = args;
|
|
@@ -525,12 +530,325 @@ function settleUpdate(args) {
|
|
|
525
530
|
}
|
|
526
531
|
}
|
|
527
532
|
|
|
533
|
+
// src/runner/housekeeping/docker.ts
|
|
534
|
+
var KIND_LABEL = "ai.outerlayer.kind";
|
|
535
|
+
function failure(result, what) {
|
|
536
|
+
return new Error(`${what}: ${result.stderr.trim() || `docker exited ${result.status}`}`);
|
|
537
|
+
}
|
|
538
|
+
function labelled(stdout, runnerId) {
|
|
539
|
+
const found = [];
|
|
540
|
+
for (const line of stdout.split("\n")) {
|
|
541
|
+
const [key = "", build = "", runner = ""] = line.replace(/\r?\n$/, "").split(" ");
|
|
542
|
+
if (key.trim() === "" || build === "") continue;
|
|
543
|
+
if (runner !== "" && runner !== runnerId) continue;
|
|
544
|
+
found.push({ key: key.trim(), build, owned: runner === runnerId });
|
|
545
|
+
}
|
|
546
|
+
return found;
|
|
547
|
+
}
|
|
548
|
+
function decimalUnits() {
|
|
549
|
+
return { b: 1, kb: 1e3, mb: 1e6, gb: 1e9, tb: 1e12, pb: 1e15 };
|
|
550
|
+
}
|
|
551
|
+
function parsePrunedBytes(stdout) {
|
|
552
|
+
const match = /^Total(?: reclaimed space)?:\s*([\d.]+)\s*([A-Za-z]*)\s*$/im.exec(stdout);
|
|
553
|
+
if (match === null) return 0;
|
|
554
|
+
const unit = decimalUnits()[match[2].toLowerCase() || "b"];
|
|
555
|
+
return unit === void 0 ? 0 : Math.round(Number(match[1]) * unit);
|
|
556
|
+
}
|
|
557
|
+
function createHousekeepingDocker(deps) {
|
|
558
|
+
const run = deps.run ?? spawnRun;
|
|
559
|
+
return {
|
|
560
|
+
async listBuildContainers() {
|
|
561
|
+
const result = await run("docker", [
|
|
562
|
+
"ps",
|
|
563
|
+
"--all",
|
|
564
|
+
"--no-trunc",
|
|
565
|
+
"--filter",
|
|
566
|
+
`label=${BUILD_LABEL}`,
|
|
567
|
+
"--format",
|
|
568
|
+
`{{.ID}} {{.Label "${BUILD_LABEL}"}} {{.Label "${RUNNER_LABEL}"}}`
|
|
569
|
+
]);
|
|
570
|
+
if (result.status !== 0) throw failure(result, "docker ps");
|
|
571
|
+
return labelled(result.stdout, deps.runnerId).map(({ key, build, owned }) => ({ id: key, build, owned }));
|
|
572
|
+
},
|
|
573
|
+
async listBuildVolumes() {
|
|
574
|
+
const result = await run("docker", [
|
|
575
|
+
"volume",
|
|
576
|
+
"ls",
|
|
577
|
+
"--filter",
|
|
578
|
+
`label=${BUILD_LABEL}`,
|
|
579
|
+
"--format",
|
|
580
|
+
`{{.Name}} {{.Label "${BUILD_LABEL}"}} {{.Label "${RUNNER_LABEL}"}}`
|
|
581
|
+
]);
|
|
582
|
+
if (result.status !== 0) throw failure(result, "docker volume ls");
|
|
583
|
+
return labelled(result.stdout, deps.runnerId).map(({ key, build, owned }) => ({ name: key, build, owned }));
|
|
584
|
+
},
|
|
585
|
+
async removeContainer(id) {
|
|
586
|
+
const result = await run("docker", ["rm", "--force", "--volumes", id]);
|
|
587
|
+
if (result.status !== 0) throw failure(result, `docker rm ${id}`);
|
|
588
|
+
},
|
|
589
|
+
async removeVolume(name) {
|
|
590
|
+
const result = await run("docker", ["volume", "rm", "--force", name]);
|
|
591
|
+
if (result.status !== 0) throw failure(result, `docker volume rm ${name}`);
|
|
592
|
+
},
|
|
593
|
+
async imageState(ref) {
|
|
594
|
+
const result = await run("docker", ["image", "inspect", "--format", "{{.Id}}", ref]);
|
|
595
|
+
if (result.status === 0) return "present";
|
|
596
|
+
return /no such image|not found/i.test(result.stderr) ? "missing" : "unknown";
|
|
597
|
+
},
|
|
598
|
+
async listDanglingImages() {
|
|
599
|
+
const listed = await run("docker", [
|
|
600
|
+
"image",
|
|
601
|
+
"ls",
|
|
602
|
+
"--all",
|
|
603
|
+
"--no-trunc",
|
|
604
|
+
"--quiet",
|
|
605
|
+
"--filter",
|
|
606
|
+
"dangling=true",
|
|
607
|
+
"--filter",
|
|
608
|
+
`label=${KIND_LABEL}`
|
|
609
|
+
]);
|
|
610
|
+
if (listed.status !== 0) throw failure(listed, "docker image ls");
|
|
611
|
+
const ids = [...new Set(listed.stdout.split("\n").map((l) => l.trim()).filter(Boolean))];
|
|
612
|
+
if (ids.length === 0) return [];
|
|
613
|
+
const inspected = await run("docker", ["image", "inspect", ...ids]);
|
|
614
|
+
if (inspected.status !== 0) throw failure(inspected, "docker image inspect");
|
|
615
|
+
return JSON.parse(inspected.stdout).map((row) => ({
|
|
616
|
+
id: row.Id,
|
|
617
|
+
size: row.Size ?? 0,
|
|
618
|
+
labels: row.Config?.Labels ?? {}
|
|
619
|
+
}));
|
|
620
|
+
},
|
|
621
|
+
async removeImage(id) {
|
|
622
|
+
const result = await run("docker", ["rmi", id]);
|
|
623
|
+
if (result.status !== 0) throw failure(result, `docker rmi ${id}`);
|
|
624
|
+
},
|
|
625
|
+
async builderPrune(keepBytes) {
|
|
626
|
+
const result = await run("docker", ["builder", "prune", "--force", "--keep-storage", String(keepBytes)]);
|
|
627
|
+
if (result.status !== 0) throw failure(result, "docker builder prune");
|
|
628
|
+
return { freedBytes: parsePrunedBytes(result.stdout) };
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/runner/housekeeping/select.ts
|
|
634
|
+
var DAY_MS = 864e5;
|
|
635
|
+
function spoolMaxAgeMs() {
|
|
636
|
+
return 24 * 36e5;
|
|
637
|
+
}
|
|
638
|
+
function selectJobDirs(entries, nowMs, keepDays) {
|
|
639
|
+
return entries.filter(
|
|
640
|
+
(entry) => (entry.state === "finished" || entry.state === "no_job_file") && nowMs - entry.mtimeMs > keepDays * DAY_MS
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
function liveBuildIds(jobs) {
|
|
644
|
+
const ids = /* @__PURE__ */ new Set();
|
|
645
|
+
for (const job of jobs) {
|
|
646
|
+
for (const id of [job.container?.buildId, job.microvm?.buildId, job.build?.buildId]) if (id !== void 0) ids.add(id);
|
|
647
|
+
}
|
|
648
|
+
return ids;
|
|
649
|
+
}
|
|
650
|
+
function finishedBuildIds(jobs) {
|
|
651
|
+
return liveBuildIds(jobs);
|
|
652
|
+
}
|
|
653
|
+
function liveImageIds(jobs) {
|
|
654
|
+
const ids = /* @__PURE__ */ new Set();
|
|
655
|
+
for (const job of jobs) {
|
|
656
|
+
for (const id of [job.container?.imageId, job.microvm?.imageId]) if (id !== void 0) ids.add(id);
|
|
657
|
+
}
|
|
658
|
+
return ids;
|
|
659
|
+
}
|
|
660
|
+
function selectOrphans(items, live, finished) {
|
|
661
|
+
return items.filter((item) => !live.has(item.build) && (item.owned || finished.has(item.build)));
|
|
662
|
+
}
|
|
663
|
+
function rootDiskImageId(fileName) {
|
|
664
|
+
if (!fileName.endsWith(".ext4") || fileName.includes(".partial-")) return void 0;
|
|
665
|
+
const id = fileName.slice(0, -".ext4".length);
|
|
666
|
+
return id === "" ? void 0 : id;
|
|
667
|
+
}
|
|
668
|
+
function selectSpool(files, nowMs, buildRunning) {
|
|
669
|
+
return buildRunning ? [] : files.filter((file) => nowMs - file.mtimeMs > spoolMaxAgeMs());
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/runner/housekeeping/run.ts
|
|
673
|
+
function sizeOf(path) {
|
|
674
|
+
try {
|
|
675
|
+
const stats = lstatSync(path);
|
|
676
|
+
if (!stats.isDirectory()) return stats.size;
|
|
677
|
+
return readdirSync(path).reduce((sum, name) => sum + sizeOf(join(path, name)), 0);
|
|
678
|
+
} catch {
|
|
679
|
+
return 0;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
function listDir(path) {
|
|
683
|
+
try {
|
|
684
|
+
return readdirSync(path);
|
|
685
|
+
} catch {
|
|
686
|
+
return [];
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
function mtimeOf(path) {
|
|
690
|
+
try {
|
|
691
|
+
return statSync(path).mtimeMs;
|
|
692
|
+
} catch {
|
|
693
|
+
return void 0;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
function readJobs(jobsPath) {
|
|
697
|
+
const entries = [];
|
|
698
|
+
const unfinished = [];
|
|
699
|
+
const finished = [];
|
|
700
|
+
const unreadable = [];
|
|
701
|
+
for (const dirent of existsSync(jobsPath) ? readdirSync(jobsPath, { withFileTypes: true }) : []) {
|
|
702
|
+
if (!dirent.isDirectory()) continue;
|
|
703
|
+
const dirPath = join(jobsPath, dirent.name);
|
|
704
|
+
const mtimeMs = mtimeOf(dirPath);
|
|
705
|
+
if (mtimeMs === void 0) continue;
|
|
706
|
+
const read = readJobFileChecked(join(dirPath, "job.json"));
|
|
707
|
+
let state;
|
|
708
|
+
if (read.kind === "missing") {
|
|
709
|
+
state = "no_job_file";
|
|
710
|
+
} else if (read.kind === "unreadable") {
|
|
711
|
+
unreadable.push(dirent.name);
|
|
712
|
+
state = "unreadable";
|
|
713
|
+
} else if (isUnfinished(read.job)) {
|
|
714
|
+
unfinished.push(read.job);
|
|
715
|
+
state = "unfinished";
|
|
716
|
+
} else {
|
|
717
|
+
finished.push(read.job);
|
|
718
|
+
state = read.job.releaseFailed === void 0 || read.job.releaseFailed === ALREADY_RELEASED ? "finished" : "release_failed";
|
|
719
|
+
}
|
|
720
|
+
entries.push({ name: dirent.name, mtimeMs, state });
|
|
721
|
+
}
|
|
722
|
+
return { entries, unfinished, finished, unreadable };
|
|
723
|
+
}
|
|
724
|
+
async function removeDanglingImages(docker, log, live) {
|
|
725
|
+
let freed = 0;
|
|
726
|
+
for (const image of await docker.listDanglingImages()) {
|
|
727
|
+
if (image.labels[KIND_LABEL] === void 0) continue;
|
|
728
|
+
if (live.has(image.id)) continue;
|
|
729
|
+
try {
|
|
730
|
+
await docker.removeImage(image.id);
|
|
731
|
+
freed += image.size;
|
|
732
|
+
log.line(`housekeeping: removed dangling image ${image.id.replace(/^sha256:/, "").slice(0, 12)} (${formatBytes(image.size)}), a rebuild replaced it`);
|
|
733
|
+
} catch (err) {
|
|
734
|
+
log.error(`housekeeping: could not remove dangling image ${image.id}: ${describeCallFailure(err)}`);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return freed;
|
|
738
|
+
}
|
|
739
|
+
async function runHousekeeping(options) {
|
|
740
|
+
const { docker, log } = options;
|
|
741
|
+
const nowMs = options.now().getTime();
|
|
742
|
+
const root = runnerDir(options.configPath);
|
|
743
|
+
let freed = 0;
|
|
744
|
+
let listed;
|
|
745
|
+
try {
|
|
746
|
+
const containers = await docker.listBuildContainers();
|
|
747
|
+
listed = { containers, volumes: await docker.listBuildVolumes() };
|
|
748
|
+
} catch (err) {
|
|
749
|
+
log.error(`housekeeping: Docker could not be asked, so nothing in Docker is removed this pass: ${describeCallFailure(err)}`);
|
|
750
|
+
}
|
|
751
|
+
const jobs = readJobs(jobsDir(options.configPath));
|
|
752
|
+
for (const name of jobs.unreadable) {
|
|
753
|
+
log.error(`housekeeping: job file ${name}/job.json does not parse, so nothing in Docker is removed this pass`);
|
|
754
|
+
}
|
|
755
|
+
const canTell = jobs.unreadable.length === 0;
|
|
756
|
+
for (const entry of selectJobDirs(jobs.entries, nowMs, options.keepDays)) {
|
|
757
|
+
const path = join(jobsDir(options.configPath), entry.name);
|
|
758
|
+
const size = sizeOf(path);
|
|
759
|
+
try {
|
|
760
|
+
rmSync(path, { recursive: true, force: true });
|
|
761
|
+
freed += size;
|
|
762
|
+
log.line(`housekeeping: removed job directory ${entry.name} (${formatBytes(size)}), last changed ${formatDuration(nowMs - entry.mtimeMs)} ago`);
|
|
763
|
+
} catch (err) {
|
|
764
|
+
log.error(`housekeeping: could not remove job directory ${entry.name}: ${describeCallFailure(err)}`);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
const live = liveBuildIds(jobs.unfinished);
|
|
768
|
+
const finished = finishedBuildIds(jobs.finished);
|
|
769
|
+
if (canTell && listed !== void 0) {
|
|
770
|
+
for (const container of selectOrphans(listed.containers, live, finished)) {
|
|
771
|
+
try {
|
|
772
|
+
await docker.removeContainer(container.id);
|
|
773
|
+
log.line(`housekeeping: removed container ${container.id.slice(0, 12)}, no unfinished build ${container.build} names it`);
|
|
774
|
+
} catch (err) {
|
|
775
|
+
log.error(`housekeeping: could not remove container ${container.id}: ${describeCallFailure(err)}`);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
for (const volume of selectOrphans(listed.volumes, live, finished)) {
|
|
779
|
+
try {
|
|
780
|
+
await docker.removeVolume(volume.name);
|
|
781
|
+
log.line(`housekeeping: removed volume ${volume.name}, no unfinished build ${volume.build} names it`);
|
|
782
|
+
} catch (err) {
|
|
783
|
+
log.error(`housekeeping: could not remove volume ${volume.name}: ${describeCallFailure(err)}`);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (canTell && listed !== void 0) {
|
|
788
|
+
freed += await removeStaleRootDisks(root, jobs.unfinished, options);
|
|
789
|
+
try {
|
|
790
|
+
freed += await removeDanglingImages(docker, log, liveImageIds(jobs.unfinished));
|
|
791
|
+
} catch (err) {
|
|
792
|
+
log.error(`housekeeping: dangling images could not be listed: ${describeCallFailure(err)}`);
|
|
793
|
+
}
|
|
794
|
+
if (options.buildCacheMax !== "off") {
|
|
795
|
+
try {
|
|
796
|
+
const pruned = await docker.builderPrune(options.buildCacheMax);
|
|
797
|
+
freed += pruned.freedBytes;
|
|
798
|
+
log.line(`housekeeping: pruned the build cache down to ${formatBytes(options.buildCacheMax)}, freed ${formatBytes(pruned.freedBytes)}`);
|
|
799
|
+
} catch (err) {
|
|
800
|
+
log.error(`housekeeping: the build cache could not be pruned: ${describeCallFailure(err)}`);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
const spoolPath = spoolDir(root);
|
|
805
|
+
const spoolFiles = listDir(spoolPath).flatMap((name) => {
|
|
806
|
+
const mtimeMs = mtimeOf(join(spoolPath, name));
|
|
807
|
+
return mtimeMs === void 0 ? [] : [{ name, mtimeMs }];
|
|
808
|
+
});
|
|
809
|
+
for (const file of selectSpool(spoolFiles, nowMs, jobs.unfinished.length > 0)) {
|
|
810
|
+
const path = join(spoolPath, file.name);
|
|
811
|
+
const size = sizeOf(path);
|
|
812
|
+
try {
|
|
813
|
+
rmSync(path, { recursive: true, force: true });
|
|
814
|
+
freed += size;
|
|
815
|
+
log.line(`housekeeping: removed spool file ${file.name} (${formatBytes(size)}), last changed ${formatDuration(nowMs - file.mtimeMs)} ago and no build is running`);
|
|
816
|
+
} catch (err) {
|
|
817
|
+
log.error(`housekeeping: could not remove spool file ${file.name}: ${describeCallFailure(err)}`);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
log.line(`housekeeping: pass finished, freed ${formatBytes(freed)}`);
|
|
821
|
+
return { freedBytes: freed };
|
|
822
|
+
}
|
|
823
|
+
async function removeStaleRootDisks(root, unfinished, options) {
|
|
824
|
+
const dir = rootfsDir(root);
|
|
825
|
+
const inUse = new Set(unfinished.flatMap((job) => job.microvm?.rootfs === void 0 ? [] : [job.microvm.rootfs]));
|
|
826
|
+
let freed = 0;
|
|
827
|
+
for (const name of listDir(dir)) {
|
|
828
|
+
const imageId = rootDiskImageId(name);
|
|
829
|
+
if (imageId === void 0) continue;
|
|
830
|
+
const path = join(dir, name);
|
|
831
|
+
if (inUse.has(path)) continue;
|
|
832
|
+
if (await options.docker.imageState(`sha256:${imageId}`) !== "missing") continue;
|
|
833
|
+
const size = sizeOf(path);
|
|
834
|
+
try {
|
|
835
|
+
rmSync(path, { force: true });
|
|
836
|
+
freed += size;
|
|
837
|
+
options.log.line(`housekeeping: removed root disk ${name} (${formatBytes(size)}), Docker no longer has its image`);
|
|
838
|
+
} catch (err) {
|
|
839
|
+
options.log.error(`housekeeping: could not remove root disk ${name}: ${describeCallFailure(err)}`);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return freed;
|
|
843
|
+
}
|
|
844
|
+
|
|
528
845
|
// src/runner/loop.ts
|
|
529
846
|
var QUEUE_ORDER = ["amend", "implement"];
|
|
530
847
|
var TRACKER_REPOSITORY_HOSTS = {
|
|
531
848
|
github: "github.com",
|
|
532
849
|
gitlab: "gitlab.com"
|
|
533
850
|
};
|
|
851
|
+
var HOUSEKEEPING_INTERVAL_MS = 36e5;
|
|
534
852
|
function logOf(state) {
|
|
535
853
|
state.deps.log ??= createRunnerLog(state.deps.now ?? (() => /* @__PURE__ */ new Date()));
|
|
536
854
|
return state.deps.log;
|
|
@@ -645,7 +963,8 @@ async function sendTickHeartbeat(state, workRequest) {
|
|
|
645
963
|
slotsUsed: state.jobs.size,
|
|
646
964
|
slotsTotal: state.config.concurrency,
|
|
647
965
|
workRequest: next,
|
|
648
|
-
lastUpdate: readLastUpdate(state.config.configPath)
|
|
966
|
+
lastUpdate: readLastUpdate(state.config.configPath),
|
|
967
|
+
lowDisk: state.lowDisk
|
|
649
968
|
},
|
|
650
969
|
state.deps.fetchImpl
|
|
651
970
|
);
|
|
@@ -769,9 +1088,64 @@ async function tick(state) {
|
|
|
769
1088
|
}
|
|
770
1089
|
await sendTickHeartbeat(state, state.lastWorkRequest);
|
|
771
1090
|
}
|
|
1091
|
+
function holdOffForDisk(state) {
|
|
1092
|
+
const minimum = state.config.housekeeping?.minFreeDisk ?? 0;
|
|
1093
|
+
const root = runnerDir(state.config.configPath);
|
|
1094
|
+
const free = minimum === 0 ? Number.POSITIVE_INFINITY : (state.deps.freeBytes ?? freeBytes)(root) ?? Number.POSITIVE_INFINITY;
|
|
1095
|
+
const log = logOf(state);
|
|
1096
|
+
if (free < minimum) {
|
|
1097
|
+
if (state.lowDisk === void 0) {
|
|
1098
|
+
log.line(
|
|
1099
|
+
`holding off new work: ${formatBytes(free)} free on the runner's file system, ${formatBytes(minimum)} needed (runner.housekeeping.minFreeDisk) \xB7 claiming again once there is room`
|
|
1100
|
+
);
|
|
1101
|
+
recordHousekeeping(state, root, { holding: { free, needed: minimum, since: nowOf(state).toISOString() } });
|
|
1102
|
+
}
|
|
1103
|
+
state.lowDisk = { free, needed: minimum };
|
|
1104
|
+
return true;
|
|
1105
|
+
}
|
|
1106
|
+
if (state.lowDisk !== void 0) {
|
|
1107
|
+
state.lowDisk = void 0;
|
|
1108
|
+
log.line("free disk is back above the minimum \xB7 taking work again");
|
|
1109
|
+
recordHousekeeping(state, root, { holding: void 0 });
|
|
1110
|
+
} else if (!state.holdRecordChecked) {
|
|
1111
|
+
if (readHousekeepingRecord(root).holding !== void 0) recordHousekeeping(state, root, { holding: void 0 });
|
|
1112
|
+
}
|
|
1113
|
+
state.holdRecordChecked = true;
|
|
1114
|
+
return false;
|
|
1115
|
+
}
|
|
1116
|
+
function recordHousekeeping(state, root, patch) {
|
|
1117
|
+
try {
|
|
1118
|
+
writeHousekeepingRecord(root, patch);
|
|
1119
|
+
} catch (err) {
|
|
1120
|
+
logOf(state).error(`could not write housekeeping.json: ${describeCallFailure(err)}`);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
async function housekeepingPass(state) {
|
|
1124
|
+
const config = state.config.housekeeping;
|
|
1125
|
+
if (config === void 0 || state.housekeepingRunning) return;
|
|
1126
|
+
state.housekeepingRunning = true;
|
|
1127
|
+
try {
|
|
1128
|
+
state.deps.housekeeping ??= {};
|
|
1129
|
+
state.deps.housekeeping.docker ??= createHousekeepingDocker({ runnerId: runnerLabelValue(state.config.configPath) });
|
|
1130
|
+
const result = await runHousekeeping({
|
|
1131
|
+
configPath: state.config.configPath,
|
|
1132
|
+
keepDays: config.jobsKeepDays,
|
|
1133
|
+
buildCacheMax: config.buildCacheMax,
|
|
1134
|
+
docker: state.deps.housekeeping.docker,
|
|
1135
|
+
now: state.deps.now ?? (() => /* @__PURE__ */ new Date()),
|
|
1136
|
+
log: logOf(state)
|
|
1137
|
+
});
|
|
1138
|
+
recordHousekeeping(state, runnerDir(state.config.configPath), { lastRunAt: nowOf(state).toISOString(), freedBytes: result.freedBytes });
|
|
1139
|
+
} catch (err) {
|
|
1140
|
+
logOf(state).error(`housekeeping failed: ${describeCallFailure(err)}`);
|
|
1141
|
+
} finally {
|
|
1142
|
+
state.housekeepingRunning = false;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
772
1145
|
async function runTick(state) {
|
|
773
1146
|
reloadConfig(state);
|
|
774
1147
|
if (await updateWhenIdle(state)) return;
|
|
1148
|
+
if (holdOffForDisk(state)) return;
|
|
775
1149
|
const log = logOf(state);
|
|
776
1150
|
const repoFilter = new RepoFilter(state.config.repos);
|
|
777
1151
|
let filtered = 0;
|
|
@@ -825,7 +1199,7 @@ var CLAIM_REFUSAL_CODES = new Set(
|
|
|
825
1199
|
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous branch_claimed_elsewhere".split(" ")
|
|
826
1200
|
);
|
|
827
1201
|
async function tryClaimAndStart(state, item, queue) {
|
|
828
|
-
const { postJson: postJson2 } = await import('./work-cmd-
|
|
1202
|
+
const { postJson: postJson2 } = await import('./work-cmd-NUR4CAG6.js');
|
|
829
1203
|
const log = logOf(state);
|
|
830
1204
|
const hostKey = await loadHostKey(state.config.configPath);
|
|
831
1205
|
const claim = await retrySend(
|
|
@@ -1525,7 +1899,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
1525
1899
|
const outcome = await onStartUnderMarker({
|
|
1526
1900
|
configPath,
|
|
1527
1901
|
own: ownVersionOf(deps),
|
|
1528
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
1902
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-4Q33B5ZE.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
1529
1903
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
1530
1904
|
log
|
|
1531
1905
|
});
|
|
@@ -1606,6 +1980,12 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
1606
1980
|
let interrupts = 0;
|
|
1607
1981
|
state.pollTimerSeconds = state.config.pollSeconds;
|
|
1608
1982
|
const pollTimer = setInterval(() => void tick(state), state.pollTimerSeconds * 1e3);
|
|
1983
|
+
const hooksKind = builtinKind(config.hooks.provision);
|
|
1984
|
+
const housekeepingTimer = hooksKind === "container" || hooksKind === "vm" ? (() => {
|
|
1985
|
+
const everyMs = deps.housekeeping?.intervalMs ?? HOUSEKEEPING_INTERVAL_MS;
|
|
1986
|
+
void housekeepingPass(state);
|
|
1987
|
+
return setInterval(() => void housekeepingPass(state), everyMs);
|
|
1988
|
+
})() : void 0;
|
|
1609
1989
|
const watchTimer = setInterval(() => {
|
|
1610
1990
|
const now = nowMs();
|
|
1611
1991
|
for (const active of state.jobs.values()) {
|
|
@@ -1639,6 +2019,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
1639
2019
|
if (intakeClosed) return;
|
|
1640
2020
|
intakeClosed = true;
|
|
1641
2021
|
clearInterval(pollTimer);
|
|
2022
|
+
clearInterval(housekeepingTimer);
|
|
1642
2023
|
};
|
|
1643
2024
|
const close = () => {
|
|
1644
2025
|
stopIntake();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { isLinkedRepository } from './chunk-
|
|
3
|
+
import { isLinkedRepository } from './chunk-D2KWEAN6.js';
|
|
4
4
|
import { readStatuslineState, STATE_FRESH_MS } from './chunk-F47JBIAW.js';
|
|
5
|
-
import { resolveCredentials, getJson, WorkCommandError } from './chunk-
|
|
6
|
-
import { sanitizeTerminal } from './chunk-
|
|
7
|
-
import { resolveRepoIdentity, compareVersions, SUPPORTED_VERSIONS } from './chunk-
|
|
5
|
+
import { resolveCredentials, getJson, WorkCommandError } from './chunk-RMAZ2NWA.js';
|
|
6
|
+
import { sanitizeTerminal } from './chunk-WOBNRVQT.js';
|
|
7
|
+
import { resolveRepoIdentity, compareVersions, SUPPORTED_VERSIONS } from './chunk-EX6M5JPR.js';
|
|
8
8
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
9
9
|
import { readSettings, settingsPath, isOurStatuslineSlot, statuslineWrappedOriginal, REGISTERED_EVENTS, isOurHookCommand, ourCommandBins, cliBinResolvable, ourDirectScriptBins, wrappedOriginalCommand } from './chunk-5QRP3MVS.js';
|
|
10
10
|
import { readPin, readContextManifest, readDegraded, readSourceCache } from './chunk-WIOZAJ2W.js';
|
|
@@ -1004,7 +1004,7 @@ function doctorExitCode(checks) {
|
|
|
1004
1004
|
|
|
1005
1005
|
// src/doctor-report.ts
|
|
1006
1006
|
async function gatherDoctorChecks() {
|
|
1007
|
-
const { defaultRunnerConfigPath, hasRunnerBlock, loadRunnerConfig, runnerVmOf } = await import('./config-
|
|
1007
|
+
const { defaultRunnerConfigPath, hasRunnerBlock, loadRunnerConfig, runnerVmOf } = await import('./config-HL2AIR3K.js');
|
|
1008
1008
|
const configPath = defaultRunnerConfigPath();
|
|
1009
1009
|
const checks = runDoctor({ runnerHost: hasRunnerBlock(configPath) });
|
|
1010
1010
|
const credential = await credentialChecks();
|
|
@@ -1016,7 +1016,7 @@ async function gatherDoctorChecks() {
|
|
|
1016
1016
|
const { runnerVmCheck } = await import('./doctor-53F2PYY7.js');
|
|
1017
1017
|
checks.push(runnerVmCheck(configPath, { lima: realLima(), home: homeFromEnv(), instance: runnerVm.instance }));
|
|
1018
1018
|
} else if (hasRunnerBlock(configPath)) {
|
|
1019
|
-
const { runnerHostChecks } = await import('./doctor-
|
|
1019
|
+
const { runnerHostChecks } = await import('./doctor-MOA3RIEP.js');
|
|
1020
1020
|
const hooks = (() => {
|
|
1021
1021
|
try {
|
|
1022
1022
|
return loadRunnerConfig(configPath).hooks;
|
|
@@ -1041,8 +1041,8 @@ async function gatherDoctorChecks() {
|
|
|
1041
1041
|
})();
|
|
1042
1042
|
const runner = (() => {
|
|
1043
1043
|
try {
|
|
1044
|
-
const { concurrency, build } = loadRunnerConfig(configPath);
|
|
1045
|
-
return { concurrency, buildMemory: build?.memory ?? "8g" };
|
|
1044
|
+
const { concurrency, build, housekeeping } = loadRunnerConfig(configPath);
|
|
1045
|
+
return { concurrency, buildMemory: build?.memory ?? "8g", minFreeDisk: housekeeping?.minFreeDisk };
|
|
1046
1046
|
} catch {
|
|
1047
1047
|
return void 0;
|
|
1048
1048
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
4
|
-
import { resolveRepoIdentity } from './chunk-
|
|
4
|
+
import { resolveRepoIdentity } from './chunk-EX6M5JPR.js';
|
|
5
5
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
6
6
|
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
7
7
|
import { unauthorizedMessage, resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { dashboardBase, isRepositoryLinked, workPageUrl, notLinkedText } from './chunk-
|
|
4
|
-
import { sanitizeTerminal } from './chunk-
|
|
5
|
-
import { remoteLookupFailed } from './chunk-
|
|
3
|
+
import { dashboardBase, isRepositoryLinked, workPageUrl, notLinkedText } from './chunk-D2KWEAN6.js';
|
|
4
|
+
import { sanitizeTerminal } from './chunk-WOBNRVQT.js';
|
|
5
|
+
import { remoteLookupFailed } from './chunk-EX6M5JPR.js';
|
|
6
6
|
import { resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
|
|
7
7
|
import { findGitDirs, readRepoConnection, writeRepoConnection } from './chunk-BJ3KTMDH.js';
|
|
8
8
|
import { createInterface } from 'readline/promises';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
4
|
-
import { sanitizeTerminal } from './chunk-
|
|
5
|
-
import { resolveRepoIdentity } from './chunk-
|
|
4
|
+
import { sanitizeTerminal } from './chunk-WOBNRVQT.js';
|
|
5
|
+
import { resolveRepoIdentity } from './chunk-EX6M5JPR.js';
|
|
6
6
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
7
7
|
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
8
8
|
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { MIN_ENGINE_MAJOR } from './chunk-
|
|
4
|
-
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-
|
|
3
|
+
import { MIN_ENGINE_MAJOR } from './chunk-T52PKE2Y.js';
|
|
4
|
+
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-Z62HNKEJ.js';
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
6
|
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|
|
7
7
|
|