feat(app,server): add pull request pane to the workspace sidebar

Introduce a PR tab in the explorer sidebar that shows status checks,
reviews, and the merged timeline for the current branch's pull
request. Extend checkout PR status with number, draft flag, repo
identity, and per-check workflow/duration; add a new
pull_request_timeline request/response pair backed by a GraphQL
query; enrich the workspace git snapshot to carry the fields through
to the client; and extend the checkout-git-actions store so timeline
queries are invalidated alongside status when mutations land.
This commit is contained in:
Mohamed Boudra
2026-04-19 14:26:52 +07:00
parent 6a36db9924
commit e373c33108
27 changed files with 4583 additions and 174 deletions
+49 -96
View File
@@ -24,7 +24,6 @@ import {
pushCurrentBranch,
resolveRepositoryDefaultBranch,
parseWorktreeList,
parseStatusCheckRollup,
isPaseoWorktreePath,
isDescendantPath,
searchGitHubIssuesAndPrs,
@@ -981,101 +980,6 @@ const x = 1;
});
});
it("parses real gh status check rollup output and dedupes by latest check run", () => {
expect(
parseStatusCheckRollup([
{
__typename: "CheckRun",
completedAt: "2026-04-02T13:53:59Z",
conclusion: "SUCCESS",
detailsUrl: "https://github.com/org/repo/actions/runs/123",
name: "review_app",
startedAt: "2026-04-02T13:49:31Z",
status: "COMPLETED",
workflowName: "Deploy PR Preview",
},
{
__typename: "CheckRun",
completedAt: "2026-04-02T13:58:59Z",
conclusion: "FAILURE",
detailsUrl: "https://github.com/org/repo/actions/runs/124",
name: "review_app",
startedAt: "2026-04-02T13:55:31Z",
status: "COMPLETED",
},
]),
).toEqual([
{
name: "review_app",
status: "failure",
url: "https://github.com/org/repo/actions/runs/124",
},
]);
});
it("parses mixed check run and status context entries", () => {
expect(
parseStatusCheckRollup([
{
__typename: "CheckRun",
name: "unit-tests",
status: "IN_PROGRESS",
conclusion: null,
detailsUrl: "https://github.com/org/repo/actions/runs/200",
startedAt: "2026-04-02T13:49:31Z",
},
{
__typename: "StatusContext",
context: "lint",
state: "SUCCESS",
targetUrl: "https://github.com/org/repo/status/300",
createdAt: "2026-04-02T13:48:00Z",
},
]),
).toEqual([
{
name: "unit-tests",
status: "pending",
url: "https://github.com/org/repo/actions/runs/200",
},
{
name: "lint",
status: "success",
url: "https://github.com/org/repo/status/300",
},
]);
});
it("returns an empty list for nullish or empty status check rollups", () => {
expect(parseStatusCheckRollup(undefined)).toEqual([]);
expect(parseStatusCheckRollup(null)).toEqual([]);
expect(parseStatusCheckRollup([])).toEqual([]);
});
it("ignores unknown status check rollup node types", () => {
expect(
parseStatusCheckRollup([
{
__typename: "Commit",
oid: "abc123",
},
{
__typename: "CheckRun",
name: "build",
status: "COMPLETED",
conclusion: "SUCCESS",
detailsUrl: "https://github.com/org/repo/actions/runs/500",
},
]),
).toEqual([
{
name: "build",
status: "success",
url: "https://github.com/org/repo/actions/runs/500",
},
]);
});
it("returns merged PR status when no open PR exists for the current branch", async () => {
execSync("git checkout -b feature", { cwd: repoDir });
execSync("git remote add origin https://github.com/getpaseo/paseo.git", { cwd: repoDir });
@@ -1098,6 +1002,55 @@ const x = 1;
expect(status.status?.state).toBe("merged");
});
it("propagates S1 PR metadata and check display fields through checkout PR status", async () => {
execSync("git checkout -b feature", { cwd: repoDir });
execSync("git remote add origin https://github.com/getpaseo/paseo.git", { cwd: repoDir });
const status = await getPullRequestStatus(
repoDir,
createGitHubServiceForStatus(
createPullRequestStatus({
number: 123,
isDraft: true,
checks: [
{
name: "server-tests",
status: "success",
url: "https://github.com/getpaseo/paseo/actions/runs/123",
workflow: "Server CI",
duration: "2m 14s",
},
],
}),
),
);
expect(status).toEqual({
githubFeaturesEnabled: true,
status: {
number: 123,
url: "https://github.com/getpaseo/paseo/pull/123",
title: "Ship feature",
state: "open",
baseRefName: "main",
headRefName: "feature",
isMerged: false,
isDraft: true,
checks: [
{
name: "server-tests",
status: "success",
url: "https://github.com/getpaseo/paseo/actions/runs/123",
workflow: "Server CI",
duration: "2m 14s",
},
],
checksStatus: "none",
reviewDecision: null,
},
});
});
it("returns closed-unmerged PR status without marking it as merged", async () => {
execSync("git checkout -b feature", { cwd: repoDir });
execSync("git remote add origin https://github.com/getpaseo/paseo.git", { cwd: repoDir });