mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
ci: namespace Vercel convex preview names per builder (#3161)
A second preview deploy-key consumer runs --preview-create on raw branch names; Convex replaces same-name previews by delete-and-create, so it was deleting Vercel's fresh deployments mid-push (get_config_hashes and wait_for_schema 404s on every PR preview today; confirmed via the Convex team audit log create/delete pairs seconds apart). Suffix all Vercel-built preview names with -vercel so no other consumer can collide with them.
This commit is contained in:
@@ -107,13 +107,13 @@ describe("Vercel build plan", () => {
|
||||
|
||||
expect(spawn).toHaveBeenCalledTimes(3);
|
||||
expect(spawn.mock.calls.map(([command]) => command)).toEqual(["bunx", "bunx", "bun"]);
|
||||
expect(spawn.mock.calls[0]?.[1]).toContain("pe/claw-413-pr-previews");
|
||||
expect(spawn.mock.calls[1]?.[1]).toContain("pe/claw-413-pr-previews-retry-2");
|
||||
expect(spawn.mock.calls[2]?.[1]).toContain("pe/claw-413-pr-previews-retry-2");
|
||||
expect(spawn.mock.calls[0]?.[1]).toContain("pe/claw-413-pr-previews-vercel");
|
||||
expect(spawn.mock.calls[1]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-2");
|
||||
expect(spawn.mock.calls[2]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-2");
|
||||
expect(sleep).toHaveBeenCalledOnce();
|
||||
expect(sleep).toHaveBeenCalledWith(20_000);
|
||||
expect(log).toHaveBeenCalledWith(
|
||||
"[vercel-build] convex preview pipeline failed (attempt 1/3); retrying in 20s with preview name pe/claw-413-pr-previews-retry-2...",
|
||||
"[vercel-build] convex preview pipeline failed (attempt 1/3); retrying in 20s with preview name pe/claw-413-pr-previews-vercel-retry-2...",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -130,10 +130,10 @@ describe("Vercel build plan", () => {
|
||||
|
||||
expect(spawn).toHaveBeenCalledTimes(4);
|
||||
expect(spawn.mock.calls.map(([command]) => command)).toEqual(["bunx", "bun", "bunx", "bun"]);
|
||||
expect(spawn.mock.calls[0]?.[1]).toContain("pe/claw-413-pr-previews");
|
||||
expect(spawn.mock.calls[1]?.[1]).toContain("pe/claw-413-pr-previews");
|
||||
expect(spawn.mock.calls[2]?.[1]).toContain("pe/claw-413-pr-previews-retry-2");
|
||||
expect(spawn.mock.calls[3]?.[1]).toContain("pe/claw-413-pr-previews-retry-2");
|
||||
expect(spawn.mock.calls[0]?.[1]).toContain("pe/claw-413-pr-previews-vercel");
|
||||
expect(spawn.mock.calls[1]?.[1]).toContain("pe/claw-413-pr-previews-vercel");
|
||||
expect(spawn.mock.calls[2]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-2");
|
||||
expect(spawn.mock.calls[3]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-2");
|
||||
expect(sleep).toHaveBeenCalledOnce();
|
||||
expect(sleep).toHaveBeenCalledWith(20_000);
|
||||
});
|
||||
@@ -153,8 +153,8 @@ describe("Vercel build plan", () => {
|
||||
await expect(main({ env: previewEnv, spawn, sleep })).resolves.toBe(1);
|
||||
|
||||
expect(spawn).toHaveBeenCalledTimes(6);
|
||||
expect(spawn.mock.calls[4]?.[1]).toContain("pe/claw-413-pr-previews-retry-3");
|
||||
expect(spawn.mock.calls[5]?.[1]).toContain("pe/claw-413-pr-previews-retry-3");
|
||||
expect(spawn.mock.calls[4]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-3");
|
||||
expect(spawn.mock.calls[5]?.[1]).toContain("pe/claw-413-pr-previews-vercel-retry-3");
|
||||
expect(sleep).toHaveBeenCalledTimes(2);
|
||||
expect(sleep).toHaveBeenNthCalledWith(1, 20_000);
|
||||
expect(sleep).toHaveBeenNthCalledWith(2, 40_000);
|
||||
|
||||
@@ -107,10 +107,15 @@ export async function main({
|
||||
const branchName = env.VERCEL_GIT_COMMIT_REF?.trim();
|
||||
if (!branchName) throw new Error("Preview builds require VERCEL_GIT_COMMIT_REF");
|
||||
|
||||
// Namespace preview names per builder: a second deploy-key consumer running
|
||||
// --preview-create on the raw branch name replaces (deletes) our deployment
|
||||
// mid-push, which surfaced as get_config_hashes/wait_for_schema 404s.
|
||||
const baseName = `${branchName}-vercel`;
|
||||
|
||||
const maxAttempts = 3;
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
||||
const previewName = attempt === 1 ? branchName : `${branchName}-retry-${attempt}`;
|
||||
const plan = attempt === 1 ? initialPlan : resolveVercelBuildPlan(env, previewName);
|
||||
const previewName = attempt === 1 ? baseName : `${baseName}-retry-${attempt}`;
|
||||
const plan = resolveVercelBuildPlan(env, previewName);
|
||||
const failure = runBuildPlan(plan, spawn);
|
||||
if (!failure) return 0;
|
||||
|
||||
@@ -120,7 +125,7 @@ export async function main({
|
||||
}
|
||||
|
||||
const delayMs = attempt * 20_000;
|
||||
const nextPreviewName = `${branchName}-retry-${attempt + 1}`;
|
||||
const nextPreviewName = `${baseName}-retry-${attempt + 1}`;
|
||||
console.error(
|
||||
`[vercel-build] convex preview pipeline failed (attempt ${attempt}/${maxAttempts}); retrying in ${delayMs / 1_000}s with preview name ${nextPreviewName}...`,
|
||||
);
|
||||
|
||||
@@ -40,6 +40,10 @@ chromium Playwright browser has already been installed.
|
||||
Vercel preview builds retry the full Convex deploy-and-seed pipeline up to three
|
||||
times, waiting 20 seconds and then 40 seconds. Retries use fresh suffixed preview
|
||||
names because duplicate names can resolve to an earlier, incomplete deployment.
|
||||
All Vercel-created preview names carry a `-vercel` suffix: `--preview-create`
|
||||
replaces (deletes) any same-name deployment, so a second deploy-key consumer
|
||||
using raw branch names would otherwise delete Vercel's deployment mid-push
|
||||
(observed 2026-07-17 as get_config_hashes/wait_for_schema 404s on every PR).
|
||||
|
||||
To reproduce the local-auth browser gate locally, install the chromium
|
||||
Playwright browser once and run:
|
||||
|
||||
Reference in New Issue
Block a user