94 lines
4.0 KiB
TypeScript
94 lines
4.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { mkdtemp } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import {
|
|
RegistryAddressedPublicationStore,
|
|
registryManifestDigest,
|
|
type RegistryAddressedRequestV1,
|
|
} from "../src/workspaces/registry-publication.js";
|
|
|
|
describe("addressed publication", () => {
|
|
it("derives one order-independent digest from the exact commit and workspace identities", () => {
|
|
const identities = [
|
|
{ workspaceId: "workspace-z", revision: "a".repeat(40), descriptorBlob: "b".repeat(40), manifestSha256: "c".repeat(64) },
|
|
{ workspaceId: "workspace-a", revision: "d".repeat(40), descriptorBlob: "e".repeat(40), manifestSha256: "f".repeat(64) },
|
|
] as const;
|
|
expect(registryManifestDigest("1".repeat(40) as any, identities)).toBe(
|
|
registryManifestDigest("1".repeat(40) as any, [...identities].reverse()),
|
|
);
|
|
expect(registryManifestDigest("2".repeat(40) as any, identities)).not.toBe(
|
|
registryManifestDigest("1".repeat(40) as any, identities),
|
|
);
|
|
});
|
|
|
|
it("claims a complete pull context and advances only through legal phases", async () => {
|
|
const root = await mkdtemp(join(process.env.TMPDIR ?? "/tmp", "thoth-pub-"));
|
|
const runId = "a".repeat(32);
|
|
const baseCommit = "b".repeat(40);
|
|
const targetCommit = "c".repeat(40);
|
|
const base = {
|
|
commit: baseCommit,
|
|
manifestSha256: "d".repeat(64),
|
|
workspaces: [{
|
|
workspaceId: "workspace-a" as any,
|
|
revision: "e".repeat(40) as any,
|
|
descriptorBlob: "f".repeat(40) as any,
|
|
manifestSha256: "0".repeat(64) as any,
|
|
}],
|
|
};
|
|
const request: RegistryAddressedRequestV1 = {
|
|
mode: "create",
|
|
operation: "registry_pull",
|
|
runId: runId as any,
|
|
requestSha256: "1".repeat(64) as any,
|
|
installationIdentitySha256: "2".repeat(64) as any,
|
|
repositoryIdentitySha256: "3".repeat(64) as any,
|
|
expectedBaseCommit: baseCommit as any,
|
|
remoteRefIdentitySha256: "4".repeat(64) as any,
|
|
};
|
|
const store = new RegistryAddressedPublicationStore(root);
|
|
|
|
const claimed = await store.claim(request, base);
|
|
expect(claimed).toMatchObject({
|
|
operation: "registry_pull",
|
|
baseCommit,
|
|
baseManifestSha256: base.manifestSha256,
|
|
baseWorkspaces: base.workspaces,
|
|
phase: "request_claimed",
|
|
});
|
|
const advertised = await store.transition(runId as any, "target_advertised", {
|
|
advertisedTargetCommit: targetCommit as any,
|
|
immutableTargetRef: `refs/thoth/addressed-runs/${runId}/target`,
|
|
});
|
|
expect(advertised.phase).toBe("target_advertised");
|
|
const fetched = await store.transition(runId as any, "target_fetched", {
|
|
fetchedTargetCommit: targetCommit as any,
|
|
});
|
|
expect(fetched.phase).toBe("target_fetched");
|
|
const planned = await store.transition(runId as any, "planned", {
|
|
targetCommit: targetCommit as any,
|
|
targetManifestSha256: "5".repeat(64) as any,
|
|
targetWorkspaces: [],
|
|
changedWorkspaceIds: ["workspace-a" as any],
|
|
changedSetSha256: "6".repeat(64) as any,
|
|
changedSetRule: "symmetric_base_target_workspace_difference",
|
|
planSha256: "7".repeat(64) as any,
|
|
});
|
|
expect(planned.phase).toBe("planned");
|
|
expect((await store.transition(runId as any, "participants_prepared", {
|
|
participantsSha256: "8".repeat(64) as any,
|
|
synchronizersSha256: "9".repeat(64) as any,
|
|
})).phase).toBe("participants_prepared");
|
|
expect((await store.transition(runId as any, "publication_intent_durable", {
|
|
publicationIntentSha256: "a".repeat(64) as any,
|
|
})).phase).toBe("publication_intent_durable");
|
|
expect((await store.transition(runId as any, "target_published", {
|
|
publishedActiveStateSha256: "b".repeat(64) as any,
|
|
})).phase).toBe("target_published");
|
|
expect((await store.transition(runId as any, "terminal_durable", {
|
|
terminalResultSha256: "c".repeat(64) as any,
|
|
terminalPublication: "target",
|
|
})).phase).toBe("terminal_durable");
|
|
});
|
|
});
|