@vm0/runner 2.13.0 → 2.13.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/index.js +32 -29
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -9106,12 +9106,12 @@ async function executeJob(context, config, options = {}) {
|
|
|
9106
9106
|
}
|
|
9107
9107
|
|
|
9108
9108
|
// src/commands/start.ts
|
|
9109
|
-
var
|
|
9109
|
+
var activeRuns = /* @__PURE__ */ new Set();
|
|
9110
9110
|
function writeStatusFile(statusFilePath, mode, startedAt) {
|
|
9111
9111
|
const status = {
|
|
9112
9112
|
mode,
|
|
9113
|
-
|
|
9114
|
-
|
|
9113
|
+
active_runs: activeRuns.size,
|
|
9114
|
+
active_run_ids: Array.from(activeRuns),
|
|
9115
9115
|
started_at: startedAt.toISOString(),
|
|
9116
9116
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9117
9117
|
};
|
|
@@ -9225,7 +9225,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9225
9225
|
if (state.mode === "running") {
|
|
9226
9226
|
console.log("\n[Maintenance] Entering drain mode...");
|
|
9227
9227
|
console.log(
|
|
9228
|
-
`[Maintenance] Active jobs: ${
|
|
9228
|
+
`[Maintenance] Active jobs: ${activeRuns.size} (will wait for completion)`
|
|
9229
9229
|
);
|
|
9230
9230
|
state.mode = "draining";
|
|
9231
9231
|
updateStatus();
|
|
@@ -9234,7 +9234,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9234
9234
|
const jobPromises = /* @__PURE__ */ new Set();
|
|
9235
9235
|
while (running) {
|
|
9236
9236
|
if (state.mode === "draining") {
|
|
9237
|
-
if (
|
|
9237
|
+
if (activeRuns.size === 0) {
|
|
9238
9238
|
console.log("[Maintenance] All jobs completed, exiting drain mode");
|
|
9239
9239
|
running = false;
|
|
9240
9240
|
break;
|
|
@@ -9245,7 +9245,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9245
9245
|
}
|
|
9246
9246
|
continue;
|
|
9247
9247
|
}
|
|
9248
|
-
if (
|
|
9248
|
+
if (activeRuns.size >= config.sandbox.max_concurrent) {
|
|
9249
9249
|
if (jobPromises.size > 0) {
|
|
9250
9250
|
await Promise.race(jobPromises);
|
|
9251
9251
|
updateStatus();
|
|
@@ -9270,7 +9270,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9270
9270
|
() => claimJob(config.server, job.runId)
|
|
9271
9271
|
);
|
|
9272
9272
|
console.log(`Claimed job: ${context.runId}`);
|
|
9273
|
-
|
|
9273
|
+
activeRuns.add(context.runId);
|
|
9274
9274
|
updateStatus();
|
|
9275
9275
|
const jobPromise = executeJob2(context, config).catch((error) => {
|
|
9276
9276
|
console.error(
|
|
@@ -9278,7 +9278,7 @@ var startCommand = new Command("start").description("Start the runner").option("
|
|
|
9278
9278
|
error instanceof Error ? error.message : "Unknown error"
|
|
9279
9279
|
);
|
|
9280
9280
|
}).finally(() => {
|
|
9281
|
-
|
|
9281
|
+
activeRuns.delete(context.runId);
|
|
9282
9282
|
jobPromises.delete(jobPromise);
|
|
9283
9283
|
updateStatus();
|
|
9284
9284
|
});
|
|
@@ -9513,8 +9513,8 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
9513
9513
|
const jobs = [];
|
|
9514
9514
|
const statusVmIds = /* @__PURE__ */ new Set();
|
|
9515
9515
|
const allocations = getAllocations();
|
|
9516
|
-
if (status?.
|
|
9517
|
-
for (const runId of status.
|
|
9516
|
+
if (status?.active_run_ids) {
|
|
9517
|
+
for (const runId of status.active_run_ids) {
|
|
9518
9518
|
const vmId = runId.split("-")[0];
|
|
9519
9519
|
if (!vmId) continue;
|
|
9520
9520
|
statusVmIds.add(vmId);
|
|
@@ -9536,13 +9536,14 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
9536
9536
|
ipToVmIds.set(ip, existing);
|
|
9537
9537
|
}
|
|
9538
9538
|
const maxConcurrent = config.sandbox.max_concurrent;
|
|
9539
|
-
console.log(`
|
|
9539
|
+
console.log(`Runs (${jobs.length} active, max ${maxConcurrent}):`);
|
|
9540
9540
|
if (jobs.length === 0) {
|
|
9541
|
-
console.log(" No active
|
|
9541
|
+
console.log(" No active runs");
|
|
9542
9542
|
} else {
|
|
9543
|
-
console.log(
|
|
9543
|
+
console.log(
|
|
9544
|
+
" Run ID VM ID IP Status"
|
|
9545
|
+
);
|
|
9544
9546
|
for (const job of jobs) {
|
|
9545
|
-
const shortId = job.runId.substring(0, 12) + "...";
|
|
9546
9547
|
const ipConflict = (ipToVmIds.get(job.ip)?.length ?? 0) > 1;
|
|
9547
9548
|
let statusText;
|
|
9548
9549
|
if (ipConflict) {
|
|
@@ -9553,7 +9554,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
9553
9554
|
statusText = "\u26A0\uFE0F No process";
|
|
9554
9555
|
}
|
|
9555
9556
|
console.log(
|
|
9556
|
-
` ${
|
|
9557
|
+
` ${job.runId} ${job.vmId} ${job.ip.padEnd(15)} ${statusText}`
|
|
9557
9558
|
);
|
|
9558
9559
|
}
|
|
9559
9560
|
}
|
|
@@ -9561,7 +9562,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
9561
9562
|
for (const job of jobs) {
|
|
9562
9563
|
if (!job.hasProcess) {
|
|
9563
9564
|
warnings.push({
|
|
9564
|
-
message: `
|
|
9565
|
+
message: `Run ${job.vmId} in status.json but no Firecracker process running`
|
|
9565
9566
|
});
|
|
9566
9567
|
}
|
|
9567
9568
|
}
|
|
@@ -9640,15 +9641,15 @@ import { Command as Command3 } from "commander";
|
|
|
9640
9641
|
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3, rmSync } from "fs";
|
|
9641
9642
|
import { dirname as dirname3, join as join4 } from "path";
|
|
9642
9643
|
import * as readline2 from "readline";
|
|
9643
|
-
var killCommand = new Command3("kill").description("Force terminate a
|
|
9644
|
-
async (
|
|
9644
|
+
var killCommand = new Command3("kill").description("Force terminate a run and clean up all resources").argument("<run-id>", "Run ID (full UUID or short 8-char vmId)").option("--config <path>", "Config file path", "./runner.yaml").option("--force", "Skip confirmation prompt").action(
|
|
9645
|
+
async (runIdArg, options) => {
|
|
9645
9646
|
try {
|
|
9646
9647
|
loadConfig(options.config);
|
|
9647
9648
|
const configDir = dirname3(options.config);
|
|
9648
9649
|
const statusFilePath = join4(configDir, "status.json");
|
|
9649
9650
|
const workspacesDir = join4(configDir, "workspaces");
|
|
9650
|
-
const { vmId, runId } =
|
|
9651
|
-
console.log(`Killing
|
|
9651
|
+
const { vmId, runId } = resolveRunId(runIdArg, statusFilePath);
|
|
9652
|
+
console.log(`Killing run ${vmId}...`);
|
|
9652
9653
|
const proc = findProcessByVmId(vmId);
|
|
9653
9654
|
const tapDevice = `tap${vmId}`;
|
|
9654
9655
|
const workspaceDir = join4(workspacesDir, `vm0-${vmId}`);
|
|
@@ -9728,17 +9729,17 @@ var killCommand = new Command3("kill").description("Force terminate a job and cl
|
|
|
9728
9729
|
const status = JSON.parse(
|
|
9729
9730
|
readFileSync4(statusFilePath, "utf-8")
|
|
9730
9731
|
);
|
|
9731
|
-
const oldCount = status.
|
|
9732
|
-
status.
|
|
9732
|
+
const oldCount = status.active_runs;
|
|
9733
|
+
status.active_run_ids = status.active_run_ids.filter(
|
|
9733
9734
|
(id) => id !== runId
|
|
9734
9735
|
);
|
|
9735
|
-
status.
|
|
9736
|
+
status.active_runs = status.active_run_ids.length;
|
|
9736
9737
|
status.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
9737
9738
|
writeFileSync3(statusFilePath, JSON.stringify(status, null, 2));
|
|
9738
9739
|
results.push({
|
|
9739
9740
|
step: "status.json",
|
|
9740
9741
|
success: true,
|
|
9741
|
-
message: `Updated (
|
|
9742
|
+
message: `Updated (active_runs: ${oldCount} -> ${status.active_runs})`
|
|
9742
9743
|
});
|
|
9743
9744
|
} catch (error) {
|
|
9744
9745
|
results.push({
|
|
@@ -9763,10 +9764,10 @@ var killCommand = new Command3("kill").description("Force terminate a job and cl
|
|
|
9763
9764
|
}
|
|
9764
9765
|
console.log("");
|
|
9765
9766
|
if (allSuccess) {
|
|
9766
|
-
console.log(`
|
|
9767
|
+
console.log(`Run ${vmId} killed successfully.`);
|
|
9767
9768
|
process.exit(0);
|
|
9768
9769
|
} else {
|
|
9769
|
-
console.log(`
|
|
9770
|
+
console.log(`Run ${vmId} cleanup completed with errors.`);
|
|
9770
9771
|
process.exit(1);
|
|
9771
9772
|
}
|
|
9772
9773
|
} catch (error) {
|
|
@@ -9777,7 +9778,7 @@ var killCommand = new Command3("kill").description("Force terminate a job and cl
|
|
|
9777
9778
|
}
|
|
9778
9779
|
}
|
|
9779
9780
|
);
|
|
9780
|
-
function
|
|
9781
|
+
function resolveRunId(input, statusFilePath) {
|
|
9781
9782
|
if (input.includes("-")) {
|
|
9782
9783
|
const vmId = input.split("-")[0];
|
|
9783
9784
|
return { vmId: vmId ?? input, runId: input };
|
|
@@ -9787,7 +9788,9 @@ function resolveJobId(input, statusFilePath) {
|
|
|
9787
9788
|
const status = JSON.parse(
|
|
9788
9789
|
readFileSync4(statusFilePath, "utf-8")
|
|
9789
9790
|
);
|
|
9790
|
-
const match = status.
|
|
9791
|
+
const match = status.active_run_ids.find(
|
|
9792
|
+
(id) => id.startsWith(input)
|
|
9793
|
+
);
|
|
9791
9794
|
if (match) {
|
|
9792
9795
|
return { vmId: input, runId: match };
|
|
9793
9796
|
}
|
|
@@ -9901,7 +9904,7 @@ var benchmarkCommand = new Command4("benchmark").description(
|
|
|
9901
9904
|
});
|
|
9902
9905
|
|
|
9903
9906
|
// src/index.ts
|
|
9904
|
-
var version = true ? "2.13.
|
|
9907
|
+
var version = true ? "2.13.1" : "0.1.0";
|
|
9905
9908
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
9906
9909
|
program.addCommand(startCommand);
|
|
9907
9910
|
program.addCommand(doctorCommand);
|