vadimenovikau/Platform-CI: Immutable QuickStack OCI deployment / Build once and deploy exact digest (push) Successful in 23s
114 lines
4.2 KiB
JavaScript
114 lines
4.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
deployExactImage,
|
|
mergeEnvironment,
|
|
resolveDeploymentBranch,
|
|
selectDeployment,
|
|
toSavePayload,
|
|
validateTarget,
|
|
verifyEndpoint,
|
|
} from "./deploy.mjs";
|
|
|
|
function response(status, body, headers = {}) {
|
|
return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json", ...headers } });
|
|
}
|
|
|
|
function app(overrides = {}) {
|
|
return {
|
|
id: "app-one", name: "One", appType: "APP", projectId: "project-one",
|
|
sourceType: "GIT", buildMethod: "DOCKERFILE", containerImageSource: null,
|
|
containerRegistryUsername: null, containerRegistryPassword: null, dockerfilePath: "./Dockerfile",
|
|
replicas: 1, envVars: "SECRET=preserved\nENVIRONMENT=old", ingressNetworkPolicy: "[]",
|
|
egressNetworkPolicy: "[]", useNetworkPolicy: false, healthCheckPeriodSeconds: 10,
|
|
healthCheckTimeoutSeconds: 2, healthCheckFailureThreshold: 3, appDomains: [], appPorts: [],
|
|
appNodePorts: [], appFileMounts: [], appVolumes: [], appBasicAuths: [], project: {},
|
|
createdAt: "ignored", updatedAt: "ignored", ...overrides,
|
|
};
|
|
}
|
|
|
|
test("selects only the deployment matching the triggering branch", () => {
|
|
const config = { version: 1, deployments: [{ branch: "main" }, { branch: "v1" }] };
|
|
assert.equal(selectDeployment(config, "v1")?.branch, "v1");
|
|
assert.equal(selectDeployment(config, "other"), null);
|
|
});
|
|
|
|
test("resolves push and pull request deployment branches without accepting empty context values", () => {
|
|
assert.equal(
|
|
resolveDeploymentBranch({
|
|
eventName: "push",
|
|
environment: { GITHUB_REF_NAME: "", GITEA_REF_NAME: "main" },
|
|
}),
|
|
"main",
|
|
);
|
|
assert.equal(
|
|
resolveDeploymentBranch({
|
|
eventName: "pull_request",
|
|
environment: { GITHUB_BASE_REF: "", GITEA_BASE_REF: "" },
|
|
eventPayload: { pull_request: { base: { ref: "main" } } },
|
|
}),
|
|
"main",
|
|
);
|
|
assert.throws(
|
|
() => resolveDeploymentBranch({ eventName: "pull_request", environment: {}, eventPayload: {} }),
|
|
/Pull request base branch/,
|
|
);
|
|
});
|
|
|
|
test("validates OCI paths and repository-local build paths", () => {
|
|
assert.equal(validateTarget({ name: "Web", image: "Owner/Web", appId: "app-1" }).image, "owner/web");
|
|
assert.throws(() => validateTarget({ name: "Web", image: "owner/web", appId: "app-1", context: "../secret" }), /inside/);
|
|
});
|
|
|
|
test("preserves response-only fields and existing environment secrets safely", () => {
|
|
const payload = toSavePayload(app());
|
|
assert.equal(payload.createdAt, undefined);
|
|
assert.equal(mergeEnvironment(app().envVars, { ENVIRONMENT: "new" }), "SECRET=preserved\nENVIRONMENT=new");
|
|
});
|
|
|
|
test("postflight waits for the exact expected identity", async () => {
|
|
let attempt = 0;
|
|
const result = await verifyEndpoint(
|
|
{ url: "https://app.example", expectedHeader: "x-build", expectedValue: "$sha12", attempts: 2, intervalSeconds: 0 },
|
|
{
|
|
sha: "1234567890abcdef1234567890abcdef12345678",
|
|
sleep: async () => {},
|
|
fetchImpl: async () => {
|
|
attempt += 1;
|
|
return response(200, {}, { "x-build": attempt === 2 ? "1234567890ab" : "old" });
|
|
},
|
|
},
|
|
);
|
|
assert.equal(result.headerValue, "1234567890ab");
|
|
});
|
|
|
|
test("failed public verification restores and redeploys the previous source", async () => {
|
|
const original = app();
|
|
let current = original;
|
|
let deployments = 0;
|
|
const client = {
|
|
getApp: async () => current,
|
|
saveApp: async (payload) => { current = { ...current, ...payload }; },
|
|
deployApp: async () => ({ deploymentId: `deployment-${++deployments}` }),
|
|
getDeployment: async (_appId, deploymentId) => ({ deploymentId, status: "DEPLOYED" }),
|
|
};
|
|
await assert.rejects(
|
|
deployExactImage({
|
|
client,
|
|
appId: "app-one",
|
|
image: `gitea.example/owner/app@sha256:${"a".repeat(64)}`,
|
|
registryUsername: "deploy",
|
|
registryToken: "token",
|
|
sha: "1".repeat(40),
|
|
sleep: async () => {},
|
|
postflight: { url: "https://app.example", attempts: 1 },
|
|
fetchImpl: async () => response(503, {}),
|
|
}),
|
|
/rolled back/,
|
|
);
|
|
assert.equal(deployments, 2);
|
|
assert.equal(current.sourceType, original.sourceType);
|
|
assert.equal(current.containerImageSource, original.containerImageSource);
|
|
});
|