Publish curated ForgeFlow source from 2ed1787c0b52
This commit is contained in:
commit
f60b269686
254 files changed
+46204
No files matched your search
@@ -0,0 +1,165 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const { registerDeploymentIpc } = require("../src/main/ipc/deployment-handlers.cjs");
|
||||
const { UnraidDeploymentService } = require("../src/main/unraid-deployment-service.cjs");
|
||||
|
||||
const REPOSITORY = { fullName: "Jens/ForgeFlow", owner: { login: "Jens" }, localPath: "C:/Projects/ForgeFlow" };
|
||||
const WORKLOAD = { workloadId: "workload-1", classification: { type: "ambiguous" } };
|
||||
|
||||
// Every collaborator answers, so a channel can only fail on a dependency the
|
||||
// module references but never receives.
|
||||
function harness(overrides = {}) {
|
||||
const calls = [];
|
||||
const record = (name, result) => async (...args) => { calls.push({ name, args }); return typeof result === "function" ? result(...args) : result; };
|
||||
const handlers = new Map();
|
||||
const profile = overrides.profile || { id: "profile-1", provider: "ssh-unraid", branch: "main", name: "Production" };
|
||||
|
||||
const dependencies = {
|
||||
register: (channel, handler) => handlers.set(channel, handler),
|
||||
store: {
|
||||
data: { servers: [{ id: "server-1", name: "Unraid" }], operations: [] },
|
||||
getDeploymentProfile: () => profile,
|
||||
getPublicState: () => ({ ok: true }),
|
||||
saveDeploymentProfile: record("store.saveDeploymentProfile", profile),
|
||||
deleteDeploymentProfile: record("store.deleteDeploymentProfile", []),
|
||||
addOperation: record("store.addOperation", null),
|
||||
},
|
||||
resolveRepository: record("resolveRepository", REPOSITORY),
|
||||
unraid: {
|
||||
preflight: record("unraid.preflight", { ok: true }),
|
||||
repairWriteAccess: record("unraid.repairWriteAccess", { changed: true, after: {}, before: {} }),
|
||||
deploy: record("unraid.deploy", { id: "operation-1" }),
|
||||
rollback: record("unraid.rollback", { id: "operation-2" }),
|
||||
linkServerWorkload: record("unraid.linkServerWorkload", { linked: true }),
|
||||
configureServerGitAccess: record("unraid.configureServerGitAccess", { keyFingerprint: "a", hostFingerprint: "b" }),
|
||||
verifyServerGitProfile: record("unraid.verifyServerGitProfile", { readiness: "ready", ready: true, checkedAt: "now" }),
|
||||
discoverServerWorkloads: record("unraid.discoverServerWorkloads", { serverId: "server-1", workloads: [] }),
|
||||
planServerInventoryReconciliation: record("unraid.planServerInventoryReconciliation", { plan: { id: "plan-1", summary: {} } }),
|
||||
reconcileServerInventory: record("unraid.reconcileServerInventory", { adopted: 0, refreshed: 0, retired: 0 }),
|
||||
scanServerInventory: record("unraid.scanServerInventory", { workloads: [WORKLOAD] }),
|
||||
refreshProfileState: record("unraid.refreshProfileState", { liveSha: null }),
|
||||
applyDockerManMetadata: record("unraid.applyDockerManMetadata", { applied: true }),
|
||||
refreshOperation: record("unraid.refreshOperation", null),
|
||||
reconcileRecordedOperations: record("unraid.reconcileRecordedOperations", []),
|
||||
},
|
||||
deployments: {
|
||||
deploy: record("deployments.deploy", { id: "operation-3" }),
|
||||
rollback: record("deployments.rollback", { id: "operation-4" }),
|
||||
checkHealth: record("deployments.checkHealth", { healthy: true }),
|
||||
refreshProfileState: record("deployments.refreshProfileState", { liveSha: null }),
|
||||
},
|
||||
evaluateDeploymentPolicy: () => ({ note: "", overridden: false, reason: "", violations: [] }),
|
||||
audit: { append: record("audit.append", null) },
|
||||
deployKeys: {
|
||||
inventory: record("deployKeys.inventory", { keys: [] }),
|
||||
planRotation: record("deployKeys.planRotation", { id: "rotation-1" }),
|
||||
rotate: record("deployKeys.rotate", { rotated: true }),
|
||||
planRevocation: record("deployKeys.planRevocation", { id: "revocation-1" }),
|
||||
revoke: record("deployKeys.revoke", { revoked: true }),
|
||||
restore: record("deployKeys.restore", { restored: true }),
|
||||
},
|
||||
repositories: { refresh: record("repositories.refresh", [REPOSITORY]) },
|
||||
inventoryReviews: {
|
||||
preview: (...args) => { calls.push({ name: "inventoryReviews.preview", args }); return { id: "review-1" }; },
|
||||
apply: record("inventoryReviews.apply", { applied: true }),
|
||||
},
|
||||
diagnostics: { info: record("diagnostics.info"), warning: record("diagnostics.warning"), error: record("diagnostics.error"), debug: record("diagnostics.debug") },
|
||||
git: {},
|
||||
gitea: { getBranch: record("gitea.getBranch", { commit: { id: "c".repeat(40) } }) },
|
||||
ssh: {},
|
||||
preflight: { runDeployment: record("preflight.runDeployment", { ok: "actions" }) },
|
||||
...overrides.dependencies,
|
||||
};
|
||||
|
||||
registerDeploymentIpc(dependencies);
|
||||
return { handlers, calls, names: () => calls.map((item) => item.name) };
|
||||
}
|
||||
|
||||
const PAYLOAD = {
|
||||
repository: REPOSITORY,
|
||||
fullName: REPOSITORY.fullName,
|
||||
profileId: "profile-1",
|
||||
sha: "a".repeat(40),
|
||||
serverId: "server-1",
|
||||
workloadId: WORKLOAD.workloadId,
|
||||
planId: "plan-1",
|
||||
action: "manual-link",
|
||||
url: "https://app.example/health",
|
||||
profile: { name: "Production" },
|
||||
targetSha: "b".repeat(40),
|
||||
};
|
||||
|
||||
// Both provider paths have to run: a dependency that only the Gitea Actions
|
||||
// branch reads stays invisible while every channel is exercised as SSH/Unraid.
|
||||
for (const provider of ["ssh-unraid", "gitea-actions"]) {
|
||||
test(`every deployment IPC channel runs with the dependencies it is given (${provider})`, async () => {
|
||||
const { handlers } = harness({ profile: { id: "profile-1", provider, branch: "main", name: "Production" } });
|
||||
assert.ok(handlers.size >= 20, "expected the complete deployment channel surface");
|
||||
|
||||
const failures = [];
|
||||
for (const [channel, handler] of handlers) {
|
||||
try {
|
||||
await handler({ ...PAYLOAD });
|
||||
} catch (error) {
|
||||
// A refusal is a decision the handler made; a missing dependency is not.
|
||||
if (error instanceof ReferenceError || error instanceof TypeError) {
|
||||
failures.push(`${channel}: ${error.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.deepEqual(failures, []);
|
||||
});
|
||||
}
|
||||
|
||||
test("deployment preflight routes by provider", async () => {
|
||||
const actions = harness({ profile: { id: "profile-1", provider: "gitea-actions" } });
|
||||
assert.deepEqual(await actions.handlers.get("deployment:preflight")({ ...PAYLOAD }), { ok: "actions" });
|
||||
assert.ok(actions.names().includes("preflight.runDeployment"));
|
||||
|
||||
const unraid = harness();
|
||||
assert.deepEqual(await unraid.handlers.get("deployment:preflight")({ ...PAYLOAD }), { ok: true });
|
||||
assert.ok(unraid.names().includes("unraid.preflight"));
|
||||
assert.ok(!unraid.names().includes("preflight.runDeployment"));
|
||||
});
|
||||
|
||||
test("write-access repair is refused for anything but an SSH/Unraid profile", async () => {
|
||||
const actions = harness({ profile: { id: "profile-1", provider: "gitea-actions" } });
|
||||
await assert.rejects(
|
||||
() => actions.handlers.get("deployment:repair-write-access")({ ...PAYLOAD }),
|
||||
/available only for SSH \/ Unraid/,
|
||||
);
|
||||
});
|
||||
|
||||
test("a stale workload blocks an inventory review instead of guessing", async () => {
|
||||
const { handlers } = harness({
|
||||
dependencies: { unraid: { scanServerInventory: async () => ({ workloads: [] }) } },
|
||||
});
|
||||
for (const channel of ["deployment:plan-inventory-review", "deployment:apply-inventory-review"]) {
|
||||
await assert.rejects(() => handlers.get(channel)({ ...PAYLOAD }), (error) => {
|
||||
assert.equal(error.code, "INVENTORY_REVIEW_WORKLOAD_STALE");
|
||||
return true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("write-access repair builds a repair script that preserves runtime paths", () => {
|
||||
const service = new UnraidDeploymentService({});
|
||||
const profile = {
|
||||
id: "profile-3",
|
||||
provider: "ssh-unraid",
|
||||
remoteFolder: "portfolio",
|
||||
composeFiles: ["docker-compose.yml"],
|
||||
preservePaths: ["data/uploads"],
|
||||
};
|
||||
const server = { id: "server-1", basePath: "/mnt/user/appdata" };
|
||||
|
||||
const script = service.permissionRepairScript(profile, server, "/mnt/user/appdata/portfolio");
|
||||
|
||||
assert.equal(typeof script, "string");
|
||||
assert.match(script, /data\/uploads/);
|
||||
assert.match(script, /node_modules/);
|
||||
assert.match(script, /ForgeFlow repaired project write access/);
|
||||
});
|
||||
Reference in new issue
Block a user