Release ForgeFlow 0.8.7 automatic server discovery

This commit is contained in:
NuklearRabbit
2026-07-26 04:22:02 +02:00
parent 70840839f8
commit 40d41f9a32
13 changed files with 638 additions and 130 deletions
+94
View File
@@ -9,6 +9,9 @@ const {
parseInspection,
dockerIgnoreHasPath,
checksSummary,
parseServerInventory,
inventoryContainerMatch,
remoteIdentity,
xmlEscape,
bash,
} = require("../src/main/unraid-deployment-service.cjs");
@@ -37,6 +40,97 @@ test("server inspection key-value payload is decoded safely", () => {
assert.deepEqual(parsed.existingPreservePaths, ["data", "logs"]);
});
test("server workload inventory links running containers to exact Gitea checkouts", () => {
const b64 = (value) => Buffer.from(value).toString("base64");
const inspect = JSON.stringify([
{
Name: "/Portfolio",
State: { Running: true, Health: { Status: "healthy" } },
Config: {
Labels: {
"com.docker.compose.project.working_dir":
"/mnt/user/appdata/Portfolio",
},
},
Mounts: [],
},
]);
const inventory = parseServerInventory(
`noise\n__FORGEFLOW_INVENTORY__\nR\t${b64("/mnt/user/appdata/Portfolio")}\t${b64("git@gitea.itworx.tech:Jens/Portfolio.git")}\t${"a".repeat(40)}\t${b64("main")}\nC\t${b64(inspect)}\n`,
);
assert.equal(inventory.checkouts.length, 1);
assert.equal(inventory.containers.length, 1);
assert.equal(
remoteIdentity("git@gitea.itworx.tech:Jens/Portfolio.git"),
remoteIdentity("https://gitea.itworx.tech/Jens/Portfolio"),
);
assert.equal(
inventoryContainerMatch(
inventory.checkouts[0],
{ name: "Portfolio" },
inventory.containers[0],
),
100,
);
});
test("automatic server discovery adopts and verifies a running Gitea deployment", async () => {
const b64 = (value) => Buffer.from(value).toString("base64");
const sha = "b".repeat(40);
const container = {
Name: "/Portfolio",
State: { Running: true, Health: { Status: "healthy" } },
Config: {
Labels: {
"com.docker.compose.project.working_dir": "/mnt/user/appdata/Portfolio",
"com.docker.compose.service": "portfolio",
},
},
Mounts: [],
NetworkSettings: { Ports: { "3000/tcp": [{ HostPort: "8080" }] } },
};
const profiles = [];
const states = new Map();
const service = new UnraidDeploymentService({
store: {
getServer: () => ({
id: "unraid",
name: "Unraid",
basePath: "/mnt/user/appdata",
}),
getDeploymentProfiles: () => profiles,
saveDeploymentProfile: async (_fullName, profile) => {
profiles.push(profile);
return profile;
},
saveDeploymentState: async (id, state) => {
states.set(id, state);
return state;
},
},
ssh: {
exec: async () => ({
stdout: `__FORGEFLOW_INVENTORY__\nR\t${b64("/mnt/user/appdata/Portfolio")}\t${b64("git@gitea.itworx.tech:Jens/Portfolio.git")}\t${sha}\t${b64("main")}\nC\t${b64(JSON.stringify([container]))}\n`,
}),
},
gitea: { getBranch: async () => ({ commit: { id: sha } }) },
});
const result = await service.discoverServerWorkloads("unraid", [
{
fullName: "Jens/Portfolio",
name: "Portfolio",
defaultBranch: "main",
cloneUrl: "https://gitea.itworx.tech/Jens/Portfolio.git",
sshUrl: "git@gitea.itworx.tech:Jens/Portfolio.git",
},
]);
assert.equal(result.adopted, 1);
assert.equal(result.verified, 1);
assert.equal(profiles[0].containerName, "Portfolio");
assert.equal(profiles[0].adoptedFromServer, true);
assert.equal(states.get(profiles[0].id).matchesGitea, true);
});
test("Docker ignore checks identify exact runtime and Git context exclusions", () => {
const rules = "# build context\n.git\ndata/\nlogs/**\n!logs/keep.txt\n";
assert.equal(dockerIgnoreHasPath(rules, ".git"), true);