mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 02:20:38 +09:00
Repair stale worktree links before runtime start
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
08fea10ce1
commit
8be6fe987b
2 changed files with 245 additions and 2 deletions
|
|
@ -20,6 +20,7 @@ import {
|
|||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
cleanupExecutionWorkspaceArtifacts,
|
||||
ensureServerWorkspaceLinksCurrent,
|
||||
ensureRuntimeServicesForRun,
|
||||
normalizeAdapterManagedRuntimeServices,
|
||||
reconcilePersistedRuntimeServicesOnStartup,
|
||||
|
|
@ -187,6 +188,96 @@ describe("sanitizeRuntimeServiceBaseEnv", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("ensureServerWorkspaceLinksCurrent", () => {
|
||||
it("relinks stale server workspace dependencies inside the current repo root", async () => {
|
||||
const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-runtime-links-"));
|
||||
const staleRoot = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-runtime-links-stale-"));
|
||||
const serverNodeModulesScopeDir = path.join(repoRoot, "server", "node_modules", "@paperclipai");
|
||||
const expectedPackageDir = path.join(repoRoot, "packages", "db");
|
||||
const stalePackageDir = path.join(staleRoot, "db");
|
||||
|
||||
await fs.mkdir(path.join(repoRoot, "server"), { recursive: true });
|
||||
await fs.mkdir(expectedPackageDir, { recursive: true });
|
||||
await fs.mkdir(stalePackageDir, { recursive: true });
|
||||
await fs.mkdir(serverNodeModulesScopeDir, { recursive: true });
|
||||
await fs.writeFile(path.join(repoRoot, "pnpm-workspace.yaml"), "packages:\n - packages/*\n - server\n", "utf8");
|
||||
await fs.writeFile(
|
||||
path.join(repoRoot, "server", "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@paperclipai/server",
|
||||
dependencies: {
|
||||
"@paperclipai/db": "workspace:*",
|
||||
},
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(expectedPackageDir, "package.json"),
|
||||
JSON.stringify({ name: "@paperclipai/db" }),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(stalePackageDir, "package.json"),
|
||||
JSON.stringify({ name: "@paperclipai/db" }),
|
||||
"utf8",
|
||||
);
|
||||
await fs.symlink(stalePackageDir, path.join(serverNodeModulesScopeDir, "db"));
|
||||
|
||||
const commands: Array<{ command: string; args: string[]; cwd: string }> = [];
|
||||
await ensureServerWorkspaceLinksCurrent(path.join(repoRoot, "server"), {
|
||||
runCommand: async (command, args, cwd) => {
|
||||
commands.push({ command, args, cwd });
|
||||
await fs.rm(path.join(serverNodeModulesScopeDir, "db"), { force: true });
|
||||
await fs.symlink(expectedPackageDir, path.join(serverNodeModulesScopeDir, "db"));
|
||||
},
|
||||
});
|
||||
|
||||
expect(commands).toHaveLength(1);
|
||||
expect(commands[0]).toMatchObject({
|
||||
command: process.platform === "win32" ? "pnpm.cmd" : "pnpm",
|
||||
args: ["install", "--force", "--config.confirmModulesPurge=false"],
|
||||
cwd: repoRoot,
|
||||
});
|
||||
expect(await fs.realpath(path.join(serverNodeModulesScopeDir, "db"))).toBe(await fs.realpath(expectedPackageDir));
|
||||
});
|
||||
|
||||
it("skips relinking when server workspace dependencies already point at the repo", async () => {
|
||||
const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-runtime-links-current-"));
|
||||
const serverNodeModulesScopeDir = path.join(repoRoot, "server", "node_modules", "@paperclipai");
|
||||
const expectedPackageDir = path.join(repoRoot, "packages", "db");
|
||||
|
||||
await fs.mkdir(path.join(repoRoot, "server"), { recursive: true });
|
||||
await fs.mkdir(expectedPackageDir, { recursive: true });
|
||||
await fs.mkdir(serverNodeModulesScopeDir, { recursive: true });
|
||||
await fs.writeFile(path.join(repoRoot, "pnpm-workspace.yaml"), "packages:\n - packages/*\n - server\n", "utf8");
|
||||
await fs.writeFile(
|
||||
path.join(repoRoot, "server", "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@paperclipai/server",
|
||||
dependencies: {
|
||||
"@paperclipai/db": "workspace:*",
|
||||
},
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(expectedPackageDir, "package.json"),
|
||||
JSON.stringify({ name: "@paperclipai/db" }),
|
||||
"utf8",
|
||||
);
|
||||
await fs.symlink(expectedPackageDir, path.join(serverNodeModulesScopeDir, "db"));
|
||||
|
||||
let invoked = false;
|
||||
await ensureServerWorkspaceLinksCurrent(path.join(repoRoot, "server"), {
|
||||
runCommand: async () => {
|
||||
invoked = true;
|
||||
},
|
||||
});
|
||||
|
||||
expect(invoked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("realizeExecutionWorkspace", () => {
|
||||
it("creates and reuses a git worktree for an issue-scoped branch", async () => {
|
||||
const repoRoot = await createTempRepo();
|
||||
|
|
@ -663,7 +754,7 @@ describe("realizeExecutionWorkspace", () => {
|
|||
await fs.realpath(path.join(repoRoot, "packages", "shared")),
|
||||
);
|
||||
},
|
||||
15_000,
|
||||
30_000,
|
||||
);
|
||||
|
||||
it("records worktree setup and provision operations when a recorder is provided", async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue