Files
zopu-code/packages/primitives/src/git.test.ts
2026-07-31 21:00:47 +05:30

146 lines
4.0 KiB
TypeScript

import { Effect, Exit } from "effect";
import { describe, expect, test } from "vitest";
import {
decideGitLifecycle,
inspectGitWorkspace,
makeCommitMessage,
validatePullRequestMetadata,
} from "./git";
const inspectionInput = {
branch: "work/issue-5",
diff: "diff --git a/file.ts b/file.ts",
status: " M file.ts",
};
const inspection = await Effect.runPromise(
inspectGitWorkspace(inspectionInput)
);
describe("Git lifecycle primitives", () => {
test("parses workspace status and treats a diff as publishable changes", () => {
expect(inspection).toMatchObject({
branch: "work/issue-5",
hasChanges: true,
status: [{ index: " ", path: "file.ts", worktree: "M" }],
});
});
test("requires verification before any publish action", async () => {
const result = await Effect.runPromiseExit(
decideGitLifecycle({
baseBranch: "main",
inspection,
pushed: false,
verification: "not-run",
})
);
expect(Exit.isFailure(result)).toBe(true);
if (Exit.isFailure(result)) {
const failure = result.cause as unknown as {
readonly reasons: readonly [
{ readonly error: { readonly reason: string } },
];
};
expect(failure.reasons[0]?.error.reason).toBe("VerificationRequired");
}
});
test("never publishes the default branch", async () => {
const result = await Effect.runPromiseExit(
decideGitLifecycle({
baseBranch: "work/issue-5",
inspection,
pushed: false,
verification: "passed",
})
);
expect(Exit.isFailure(result)).toBe(true);
if (Exit.isFailure(result)) {
const failure = result.cause as unknown as {
readonly reasons: readonly [
{ readonly error: { readonly reason: string } },
];
};
expect(failure.reasons[0]?.error.reason).toBe("InvalidBranch");
}
});
test("moves verified changes through commit, push, PR, then manual merge", async () => {
const commit = await Effect.runPromise(
decideGitLifecycle({
baseBranch: "main",
inspection,
pushed: false,
verification: "passed",
})
);
expect(commit).toEqual({ decision: "commit", status: "committed" });
const push = await Effect.runPromise(
decideGitLifecycle({
baseBranch: "main",
commitSha: "abc123",
inspection: { ...inspection, hasChanges: false, status: [] },
pushed: false,
verification: "passed",
})
);
expect(push).toEqual({ decision: "push", status: "pushed" });
const pr = await Effect.runPromise(
decideGitLifecycle({
baseBranch: "main",
commitSha: "abc123",
inspection: { ...inspection, hasChanges: false, status: [] },
pushed: true,
verification: "passed",
})
);
expect(pr).toEqual({
decision: "create_pull_request",
status: "pull_request_open",
});
const merge = await Effect.runPromise(
decideGitLifecycle({
baseBranch: "main",
commitSha: "abc123",
inspection: { ...inspection, hasChanges: false, status: [] },
pullRequest: {
baseBranch: "main",
branch: "work/issue-5",
number: 5,
status: "open",
url: "https://git.openputer.com/puter/zopu-code/pulls/5",
},
pushed: true,
verification: "passed",
})
);
expect(merge).toEqual({
decision: "manual_merge",
status: "pull_request_open",
});
});
test("validates PR metadata and keeps merge manual", async () => {
const metadata = await Effect.runPromise(
validatePullRequestMetadata({
baseBranch: "main",
branch: "work/issue-5",
number: 5,
status: "open",
url: "https://git.openputer.com/puter/zopu-code/pulls/5",
})
);
expect(metadata.status).toBe("open");
expect(makeCommitMessage(5, "Ship Git lifecycle")).toBe(
"feat(issue-5): Ship Git lifecycle"
);
});
});