Source commit: b8454b34d38cc2ba0bd278e842060db45d091e1c Public tree identity: sha256:69d6c8143bf6227e1bb07852aa94e8af9c26793eca252bb46788894f728cb6d2
191 lines
6 KiB
JavaScript
191 lines
6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const assert = require("assert");
|
|
const cp = require("child_process");
|
|
const fs = require("fs");
|
|
const os = require("os");
|
|
const path = require("path");
|
|
|
|
const repo = path.resolve(__dirname, "..");
|
|
const project = path.join(repo, "tests/fixtures/runtime-conformance");
|
|
const isolatedCwd = fs.mkdtempSync(path.join(os.tmpdir(), "clusterflux-cli-output-"));
|
|
const isolatedHome = fs.mkdtempSync(path.join(os.tmpdir(), "clusterflux-cli-home-"));
|
|
|
|
function clusterflux(args, env = {}, cwd = isolatedCwd) {
|
|
return cp.execFileSync(
|
|
"cargo",
|
|
[
|
|
"run",
|
|
"-q",
|
|
"--manifest-path",
|
|
path.join(repo, "Cargo.toml"),
|
|
"-p",
|
|
"clusterflux-cli",
|
|
"--bin",
|
|
"clusterflux",
|
|
"--",
|
|
...args,
|
|
],
|
|
{
|
|
cwd,
|
|
encoding: "utf8",
|
|
env: {
|
|
...process.env,
|
|
HOME: isolatedHome,
|
|
USERPROFILE: isolatedHome,
|
|
XDG_CONFIG_HOME: path.join(isolatedHome, ".config"),
|
|
XDG_DATA_HOME: path.join(isolatedHome, ".local", "share"),
|
|
XDG_STATE_HOME: path.join(isolatedHome, ".local", "state"),
|
|
...env,
|
|
},
|
|
}
|
|
);
|
|
}
|
|
|
|
function json(args, env, cwd) {
|
|
return JSON.parse(clusterflux(args, env, cwd));
|
|
}
|
|
|
|
function assertHuman(name, output, requiredPatterns) {
|
|
assert(
|
|
!output.trimStart().startsWith("{"),
|
|
`${name} default output should be human-readable text, not JSON`
|
|
);
|
|
for (const pattern of requiredPatterns) {
|
|
assert.match(output, pattern, `${name} human output missing ${pattern}`);
|
|
}
|
|
}
|
|
|
|
const helpHuman = clusterflux(["help"]);
|
|
assertHuman("help", helpHuman, [
|
|
/Primary workflow:/,
|
|
/clusterflux login --browser/,
|
|
/clusterflux project init/,
|
|
/clusterflux node attach; clusterflux-node --worker/,
|
|
/Clusterflux: Launch Virtual Process/,
|
|
/Hosted account creation happens in the browser login flow/,
|
|
/--json/,
|
|
]);
|
|
|
|
const loginHuman = clusterflux([
|
|
"login",
|
|
"--plan",
|
|
"--coordinator",
|
|
"https://coord.example.test",
|
|
]);
|
|
assertHuman("login", loginHuman, [
|
|
/Clusterflux login/,
|
|
/flow: browser/,
|
|
]);
|
|
|
|
const loginJson = json([
|
|
"login",
|
|
"--plan",
|
|
"--coordinator",
|
|
"https://coord.example.test",
|
|
"--json",
|
|
]);
|
|
assert.strictEqual(loginJson.coordinator, "https://coord.example.test");
|
|
assert(loginJson.human_flow.Browser);
|
|
assert.strictEqual(loginJson.human_flow.Browser.hosted_callback, true);
|
|
assert.strictEqual(loginJson.human_flow.Browser.cli_submits_identity_claims, false);
|
|
|
|
const doctorHuman = clusterflux(["doctor"]);
|
|
assertHuman("doctor", doctorHuman, [
|
|
/Clusterflux doctor/,
|
|
/coordinator reachability: not_configured/,
|
|
/dependencies:/,
|
|
/auth:/,
|
|
/node capabilities:/,
|
|
/node readiness: (ready_to_attach|local_dependencies_missing|limited_capabilities)/,
|
|
/node next:/,
|
|
]);
|
|
|
|
const doctorJson = json(["doctor", "--json"]);
|
|
assert.strictEqual(doctorJson.coordinator_reachability.checked, false);
|
|
assert.strictEqual(doctorJson.coordinator_reachability.status, "not_configured");
|
|
assert(
|
|
["ready_to_attach", "local_dependencies_missing", "limited_capabilities"].includes(
|
|
doctorJson.node_readiness_summary.status
|
|
)
|
|
);
|
|
assert.strictEqual(doctorJson.node_readiness_summary.explicit_attach_required, true);
|
|
assert.strictEqual(
|
|
doctorJson.node_readiness_summary.command_execution_capability,
|
|
true
|
|
);
|
|
assert(Array.isArray(doctorJson.node_readiness_summary.missing_local_dependencies));
|
|
assert(doctorJson.node_readiness_summary.next_actions.length >= 2);
|
|
|
|
const authJson = json(["auth", "status", "--json"], {
|
|
CLUSTERFLUX_TOKEN: "token",
|
|
CLUSTERFLUX_TOKEN_EXPIRES_AT: "2026-07-04T00:00:00Z",
|
|
}, isolatedCwd);
|
|
assert.strictEqual(authJson.session.kind, "human");
|
|
assert.strictEqual(authJson.session.token_expiry_posture, "expires_at");
|
|
assert.strictEqual(authJson.session.expires_at, "2026-07-04T00:00:00Z");
|
|
assert.strictEqual(authJson.coordinator_account_status.checked, false);
|
|
assert.strictEqual(authJson.coordinator_account_status.account_status, "unknown");
|
|
assert.strictEqual(
|
|
authJson.coordinator_account_status.private_moderation_details_exposed,
|
|
false
|
|
);
|
|
|
|
const inspectHuman = clusterflux(["bundle", "inspect", "--project", project]);
|
|
assertHuman("bundle inspect", inspectHuman, [
|
|
/Clusterflux bundle inspect/,
|
|
/bundle: sha256:/,
|
|
/environments:/,
|
|
]);
|
|
|
|
const inspectJson = json(["bundle", "inspect", "--project", project, "--json"]);
|
|
assert.strictEqual(inspectJson.project, project);
|
|
assert.match(inspectJson.metadata.identity, /^sha256:/);
|
|
assert.match(inspectJson.metadata.wasm_code, /^sha256:/);
|
|
assert.strictEqual(inspectJson.metadata.task_metadata.default_entrypoint, "build");
|
|
assert.deepStrictEqual(inspectJson.metadata.task_metadata.entrypoints, [
|
|
"build",
|
|
"fail",
|
|
"identity",
|
|
"long-join",
|
|
"park-wake",
|
|
"restart",
|
|
]);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.source_metadata.transfer_policy.coordinator_receives_source_bytes_by_default,
|
|
false
|
|
);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.source_metadata.transfer_policy.default_full_repo_tarball,
|
|
false
|
|
);
|
|
assert.strictEqual(inspectJson.metadata.debug_metadata.dap_virtual_process, true);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.large_input_policy.selected_inputs_are_content_digests,
|
|
true
|
|
);
|
|
assert.strictEqual(inspectJson.metadata.large_input_policy.selected_input_bytes_included, false);
|
|
assert.strictEqual(inspectJson.metadata.large_input_policy.full_repository_bytes_included, false);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.large_input_policy.silent_task_argument_serialization,
|
|
false
|
|
);
|
|
assert(inspectJson.metadata.large_input_policy.supported_handle_types.includes("SourceSnapshot"));
|
|
assert.strictEqual(
|
|
inspectJson.metadata.restart_compatibility.source_edits_can_restart_from_clean_task_boundary,
|
|
true
|
|
);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.restart_compatibility.requires_clean_checkpoint_boundary,
|
|
true
|
|
);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.restart_compatibility.compares_task_abi,
|
|
inspectJson.metadata.task_metadata.task_abi
|
|
);
|
|
assert.strictEqual(
|
|
inspectJson.metadata.restart_compatibility.incompatible_changes_require_whole_process_restart,
|
|
true
|
|
);
|
|
|
|
console.log("CLI output mode smoke passed");
|