The 'fetch+reset path' test called commitAndPush without author args and relied on an ambient git identity. A bare CI runner has none, so 'git commit' failed with 'Author identity unknown'. Pass an explicit author like the sibling tests so the suite is deterministic regardless of runner git config. Co-Authored-By: Claude
74 lines
3.6 KiB
TypeScript
74 lines
3.6 KiB
TypeScript
import { afterAll, beforeAll, expect, test } from "vitest";
|
|
import { execFileSync } from "node:child_process";
|
|
import { mkdtempSync, mkdirSync, rmSync, readFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { ChildProcessGitClient } from "./git";
|
|
|
|
let root: string, bare: string, base: string;
|
|
|
|
beforeAll(() => {
|
|
root = mkdtempSync(join(tmpdir(), "jp-git-"));
|
|
bare = join(root, "remote.git");
|
|
base = join(root, "work");
|
|
mkdirSync(bare); mkdirSync(base);
|
|
execFileSync("git", ["init", "--bare", "-b", "main", bare]);
|
|
// seed an initial commit so the branch exists
|
|
const seed = join(root, "seed");
|
|
mkdirSync(seed);
|
|
execFileSync("git", ["init", "-b", "main", seed]);
|
|
execFileSync("git", ["-C", seed, "config", "user.email", "t@t"]);
|
|
execFileSync("git", ["-C", seed, "config", "user.name", "t"]);
|
|
execFileSync("git", ["-C", seed, "commit", "--allow-empty", "-m", "init"]);
|
|
execFileSync("git", ["-C", seed, "remote", "add", "origin", bare]);
|
|
execFileSync("git", ["-C", seed, "push", "origin", "main"]);
|
|
});
|
|
|
|
afterAll(() => rmSync(root, { recursive: true, force: true }));
|
|
|
|
test("clone, write, commit, push lands files in the remote", async () => {
|
|
const client = new ChildProcessGitClient({ baseDir: base });
|
|
await client.syncClone({ url: bare, branch: "main" });
|
|
await client.writeFiles([
|
|
{ repoPath: "_posts/2026-06-19-hi.md", data: "---\nlayout: post\n---\n\nHi\n" },
|
|
{ repoPath: "assets/img/hi.png", data: Buffer.from([1, 2, 3]) },
|
|
]);
|
|
await client.commitAndPush({ message: "Publish: Hi", branch: "main", authorName: "t", authorEmail: "t@t" });
|
|
|
|
const verify = join(root, "verify");
|
|
execFileSync("git", ["clone", bare, verify]);
|
|
expect(readFileSync(join(verify, "_posts/2026-06-19-hi.md"), "utf8")).toContain("Hi");
|
|
expect(Array.from(readFileSync(join(verify, "assets/img/hi.png")))).toEqual([1, 2, 3]);
|
|
});
|
|
|
|
test("second sync resets cleanly (fetch+reset path)", async () => {
|
|
const client = new ChildProcessGitClient({ baseDir: base });
|
|
await client.syncClone({ url: bare, branch: "main" });
|
|
await client.writeFiles([{ repoPath: "_posts/second.md", data: "x" }]);
|
|
// Pass an explicit author so the test does not depend on an ambient git
|
|
// identity (a bare CI runner has none and `git commit` would fail).
|
|
await client.commitAndPush({ message: "second", branch: "main", authorName: "t", authorEmail: "t@t" });
|
|
const verify = join(root, "verify2");
|
|
execFileSync("git", ["clone", bare, verify]);
|
|
expect(readFileSync(join(verify, "_posts/second.md"), "utf8")).toBe("x");
|
|
});
|
|
|
|
test("commitAndPush rejects with diagnostic error when nothing is staged", async () => {
|
|
// Use a fresh base dir so we get a clean clone
|
|
const base2 = join(root, "work2");
|
|
mkdirSync(base2, { recursive: true });
|
|
const client = new ChildProcessGitClient({ baseDir: base2 });
|
|
// Clone and write a file, then commit it
|
|
await client.syncClone({ url: bare, branch: "main" });
|
|
await client.writeFiles([{ repoPath: "_posts/no-change.md", data: "same content" }]);
|
|
await client.commitAndPush({ message: "initial no-change", branch: "main", authorName: "t", authorEmail: "t@t" });
|
|
|
|
// Now sync again — tree now matches origin, re-writing the same content stages nothing
|
|
const client2 = new ChildProcessGitClient({ baseDir: base2 });
|
|
await client2.syncClone({ url: bare, branch: "main" });
|
|
await client2.writeFiles([{ repoPath: "_posts/no-change.md", data: "same content" }]);
|
|
await expect(
|
|
client2.commitAndPush({ message: "noop", branch: "main", authorName: "t", authorEmail: "t@t" })
|
|
).rejects.toThrow(/no changes to publish/i);
|
|
});
|