mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-25 10:42:45 +00:00
* feat(workspaces): gate fork repository automation Cross-repository change requests can execute contributor-controlled package hooks even when the setup command comes from the base repository. Persist the checkout provenance and require one explicit workspace-level setup action before repository automation runs. * fix(workspaces): clarify blocked script errors * fix(app): keep long toasts readable * test(server): expect fork repository provenance * test(server): make setup marker portable * test(app): retry transient sidebar layout
113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { mkdirSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { expect, test } from "../support/fixtures";
|
|
import { createTempGitRepo } from "../support/helpers/workspace";
|
|
import {
|
|
connectWorkspaceSetupClient,
|
|
openHomeWithProject,
|
|
openWorkspaceScriptsMenu,
|
|
seedProjectForWorkspaceSetup,
|
|
startWorkspaceScriptFromMenu,
|
|
} from "../support/helpers/workspace-setup";
|
|
import { waitForWorkspaceTabsVisible } from "../support/helpers/workspace-tabs";
|
|
import { getServerId } from "../support/helpers/server-id";
|
|
import { buildHostWorkspaceRoute } from "../../src/utils/host-routes";
|
|
|
|
const evidenceDir = "/tmp/fork-setup-gate";
|
|
|
|
test("fork workspace setup stays blocked until the user runs it", async ({ page }) => {
|
|
test.setTimeout(90_000);
|
|
mkdirSync(evidenceDir, { recursive: true });
|
|
const client = await connectWorkspaceSetupClient();
|
|
const repo = await createTempGitRepo("fork-setup-gate-", {
|
|
withRemote: true,
|
|
originUrl: "https://github.com/paseo-e2e/local-fixture.git",
|
|
branches: ["pr-branch-2"],
|
|
paseoConfig: {
|
|
worktree: {
|
|
setup: ["node -e \"setTimeout(() => console.log('setup complete'), 1500)\""],
|
|
},
|
|
scripts: { dev: { command: 'node -e "setTimeout(() => {}, 30000)"' } },
|
|
},
|
|
});
|
|
|
|
try {
|
|
const localRemote = path.join(repo.path, "remote.git");
|
|
execFileSync("git", ["update-ref", "refs/pull/2/head", "refs/heads/pr-branch-2"], {
|
|
cwd: localRemote,
|
|
});
|
|
execFileSync(
|
|
"git",
|
|
["config", `url.${localRemote}.insteadOf`, "git@github.com:fork-owner/local-fixture.git"],
|
|
{ cwd: repo.path },
|
|
);
|
|
execFileSync(
|
|
"git",
|
|
[
|
|
"config",
|
|
"--add",
|
|
`url.${localRemote}.insteadOf`,
|
|
"https://github.com/paseo-e2e/local-fixture.git",
|
|
],
|
|
{ cwd: repo.path },
|
|
);
|
|
await seedProjectForWorkspaceSetup(client, repo.path);
|
|
const result = await client.createWorkspace({
|
|
source: {
|
|
kind: "worktree",
|
|
cwd: repo.path,
|
|
action: "checkout",
|
|
checkoutSource: { kind: "change_request", forge: "github", number: 2 },
|
|
},
|
|
});
|
|
if (!result.workspace || result.error)
|
|
throw new Error(result.error ?? "Workspace creation failed");
|
|
expect(result.setupSkippedReason).toContain("Scripts are blocked for PR #2");
|
|
|
|
await openHomeWithProject(page, repo.path);
|
|
await page.goto(buildHostWorkspaceRoute(getServerId(), result.workspace.id));
|
|
await waitForWorkspaceTabsVisible(page);
|
|
|
|
await test.step("the blocked setup tab opens with the fork warning", async () => {
|
|
await expect(page.getByTestId("workspace-setup-panel")).toBeVisible({ timeout: 30_000 });
|
|
await expect(page.getByRole("alert")).toContainText("fork-owner/local-fixture");
|
|
await expect(page.getByRole("button", { name: "Run setup" })).toBeVisible();
|
|
await page.screenshot({
|
|
path: path.join(evidenceDir, "blocked-fork-setup.png"),
|
|
fullPage: true,
|
|
});
|
|
});
|
|
|
|
await test.step("starting a script explains why it is blocked", async () => {
|
|
await openWorkspaceScriptsMenu(page);
|
|
await startWorkspaceScriptFromMenu(page, "dev");
|
|
await expect(page.getByText(/Scripts are blocked for PR #2/)).toBeVisible();
|
|
await page.screenshot({
|
|
path: path.join(evidenceDir, "blocked-script-error.png"),
|
|
fullPage: true,
|
|
});
|
|
await page.reload();
|
|
await waitForWorkspaceTabsVisible(page);
|
|
await expect(page.getByRole("button", { name: "Run setup" })).toBeVisible();
|
|
});
|
|
|
|
await test.step("running setup replaces the warning with normal progress", async () => {
|
|
await page.getByRole("button", { name: "Run setup" }).click();
|
|
await expect(page.getByTestId("workspace-setup-status")).toContainText(/Running|Completed/, {
|
|
timeout: 30_000,
|
|
});
|
|
await page.screenshot({
|
|
path: path.join(evidenceDir, "fork-setup-running.png"),
|
|
fullPage: true,
|
|
});
|
|
await expect(page.getByTestId("workspace-setup-status")).toContainText("Completed", {
|
|
timeout: 30_000,
|
|
});
|
|
});
|
|
} finally {
|
|
await client.close();
|
|
await repo.cleanup();
|
|
}
|
|
});
|