229 lines
7.1 KiB
JavaScript
Executable file
229 lines
7.1 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
const assert = require("assert");
|
|
const cp = require("child_process");
|
|
const net = require("net");
|
|
const path = require("path");
|
|
|
|
const repo = path.resolve(__dirname, "..");
|
|
const project = path.join(repo, "examples/launch-build-demo");
|
|
|
|
function runDisasmer(args) {
|
|
return new Promise((resolve) => {
|
|
const child = cp.spawn(
|
|
"cargo",
|
|
["run", "-q", "-p", "disasmer-cli", "--bin", "disasmer", "--", ...args],
|
|
{
|
|
cwd: repo,
|
|
stdio: ["ignore", "pipe", "pipe"],
|
|
}
|
|
);
|
|
let stdout = "";
|
|
let stderr = "";
|
|
child.stdout.setEncoding("utf8");
|
|
child.stderr.setEncoding("utf8");
|
|
child.stdout.on("data", (chunk) => {
|
|
stdout += chunk;
|
|
});
|
|
child.stderr.on("data", (chunk) => {
|
|
stderr += chunk;
|
|
});
|
|
child.on("close", (code, signal) => {
|
|
resolve({ code, signal, stdout, stderr });
|
|
});
|
|
});
|
|
}
|
|
|
|
async function runWithOneCoordinatorResponse(buildArgs, response) {
|
|
let request = "";
|
|
const server = net.createServer((socket) => {
|
|
socket.setEncoding("utf8");
|
|
socket.on("data", (chunk) => {
|
|
request += chunk;
|
|
if (!request.includes("\n")) return;
|
|
socket.write(JSON.stringify(response) + "\n");
|
|
socket.end();
|
|
server.close();
|
|
});
|
|
});
|
|
|
|
const address = await new Promise((resolve) => {
|
|
server.listen(0, "127.0.0.1", () => resolve(server.address()));
|
|
});
|
|
const coordinator = `http://${address.address}:${address.port}`;
|
|
const result = await runDisasmer(buildArgs(coordinator));
|
|
return { request, result };
|
|
}
|
|
|
|
async function main() {
|
|
const nonInteractive = await runDisasmer([
|
|
"run",
|
|
"build",
|
|
"--project",
|
|
project,
|
|
"--non-interactive",
|
|
"--json",
|
|
]);
|
|
assert.strictEqual(nonInteractive.signal, null, nonInteractive.stderr);
|
|
assert.strictEqual(nonInteractive.code, 20, nonInteractive.stderr);
|
|
assert.doesNotMatch(nonInteractive.stderr, /Opening Disasmer browser login/);
|
|
const nonInteractiveReport = JSON.parse(nonInteractive.stdout);
|
|
assert.strictEqual(nonInteractiveReport.status, "authentication_required");
|
|
assert.strictEqual(nonInteractiveReport.non_interactive, true);
|
|
assert.strictEqual(nonInteractiveReport.browser_opened, false);
|
|
assert.strictEqual(nonInteractiveReport.machine_error.category, "authentication");
|
|
assert.strictEqual(nonInteractiveReport.machine_error.stable_exit_code, 20);
|
|
assert.strictEqual(
|
|
nonInteractiveReport.machine_error.process_exit_code_applied,
|
|
true
|
|
);
|
|
assert(
|
|
nonInteractiveReport.machine_error.next_actions.includes(
|
|
"pass --local to run against local services"
|
|
)
|
|
);
|
|
|
|
let request = "";
|
|
const server = net.createServer((socket) => {
|
|
socket.setEncoding("utf8");
|
|
socket.on("data", (chunk) => {
|
|
request += chunk;
|
|
if (!request.includes("\n")) return;
|
|
socket.write(
|
|
JSON.stringify({
|
|
type: "error",
|
|
message: "quota unavailable: resource limit exceeded for api_calls",
|
|
}) + "\n"
|
|
);
|
|
socket.end();
|
|
server.close();
|
|
});
|
|
});
|
|
|
|
const address = await new Promise((resolve) => {
|
|
server.listen(0, "127.0.0.1", () => resolve(server.address()));
|
|
});
|
|
const coordinator = `http://${address.address}:${address.port}`;
|
|
|
|
const result = await runDisasmer([
|
|
"run",
|
|
"build",
|
|
"--project",
|
|
project,
|
|
"--coordinator",
|
|
coordinator,
|
|
"--json",
|
|
]);
|
|
|
|
assert.strictEqual(result.signal, null, result.stderr);
|
|
assert.strictEqual(result.code, 22, result.stderr);
|
|
assert.match(request, /"type":"start_process"/);
|
|
const report = JSON.parse(result.stdout);
|
|
assert.strictEqual(report.status, "coordinator_rejected");
|
|
assert.strictEqual(report.run_start.machine_error.category, "quota");
|
|
assert.strictEqual(report.run_start.machine_error.resource_category, "api_calls");
|
|
assert.strictEqual(report.run_start.machine_error.community_tier_language, true);
|
|
assert.strictEqual(
|
|
report.run_start.machine_error.community_tier_label,
|
|
"community tier"
|
|
);
|
|
assert.doesNotMatch(result.stdout, new RegExp(["free", "tier"].join(" "), "i"));
|
|
assert.strictEqual(
|
|
report.run_start.machine_error.private_abuse_heuristics_exposed,
|
|
false
|
|
);
|
|
assert.strictEqual(report.run_start.machine_error.stable_exit_code, 22);
|
|
assert.strictEqual(
|
|
report.run_start.machine_error.process_exit_code_applied,
|
|
true
|
|
);
|
|
assert(
|
|
report.run_start.machine_error.next_actions.includes("disasmer quota status")
|
|
);
|
|
|
|
const artifactDownload = await runWithOneCoordinatorResponse(
|
|
(coordinator) => [
|
|
"artifact",
|
|
"download",
|
|
"app.txt",
|
|
"--coordinator",
|
|
coordinator,
|
|
"--json",
|
|
],
|
|
{
|
|
type: "artifact_download_denied",
|
|
message: "artifact download unauthorized for project",
|
|
}
|
|
);
|
|
assert.strictEqual(artifactDownload.result.signal, null, artifactDownload.result.stderr);
|
|
assert.strictEqual(artifactDownload.result.code, 21, artifactDownload.result.stderr);
|
|
assert.match(artifactDownload.request, /"type":"create_artifact_download_link"/);
|
|
const artifactDownloadReport = JSON.parse(artifactDownload.result.stdout);
|
|
assert.strictEqual(
|
|
artifactDownloadReport.download_session.machine_error.category,
|
|
"authorization"
|
|
);
|
|
assert.strictEqual(
|
|
artifactDownloadReport.download_session.machine_error.process_exit_code_applied,
|
|
true
|
|
);
|
|
|
|
const artifactExport = await runWithOneCoordinatorResponse(
|
|
(coordinator) => [
|
|
"artifact",
|
|
"export",
|
|
"app.txt",
|
|
"--to",
|
|
path.join(project, "target", "blocked-artifact.txt"),
|
|
"--coordinator",
|
|
coordinator,
|
|
"--json",
|
|
],
|
|
{
|
|
type: "artifact_export_unavailable",
|
|
message: "direct connectivity unavailable for artifact export",
|
|
}
|
|
);
|
|
assert.strictEqual(artifactExport.result.signal, null, artifactExport.result.stderr);
|
|
assert.strictEqual(artifactExport.result.code, 25, artifactExport.result.stderr);
|
|
assert.match(artifactExport.request, /"type":"export_artifact_to_node"/);
|
|
const artifactExportReport = JSON.parse(artifactExport.result.stdout);
|
|
assert.strictEqual(
|
|
artifactExportReport.export_plan.machine_error.category,
|
|
"connectivity"
|
|
);
|
|
assert.strictEqual(
|
|
artifactExportReport.export_plan.machine_error.process_exit_code_applied,
|
|
true
|
|
);
|
|
|
|
const confirmation = await runDisasmer([
|
|
"process",
|
|
"cancel",
|
|
"--coordinator",
|
|
"127.0.0.1:9",
|
|
"--json",
|
|
]);
|
|
assert.strictEqual(confirmation.signal, null, confirmation.stderr);
|
|
assert.strictEqual(confirmation.code, 23, confirmation.stderr);
|
|
const confirmationReport = JSON.parse(confirmation.stdout);
|
|
assert.strictEqual(confirmationReport.status, "confirmation_required");
|
|
assert.strictEqual(confirmationReport.coordinator_request_sent, false);
|
|
assert.strictEqual(confirmationReport.machine_error.category, "policy");
|
|
assert.strictEqual(
|
|
confirmationReport.machine_error.process_exit_code_applied,
|
|
true
|
|
);
|
|
assert(
|
|
confirmationReport.next_actions.some((action) => action.includes("--yes"))
|
|
);
|
|
}
|
|
|
|
main()
|
|
.then(() => {
|
|
console.log("CLI error exit smoke passed");
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|