refactor(server): migrate pipeline view to ForgePort (first shape-leak fix) #275
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!275
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "refactor/migrate-pipeline-to-forgeport"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
First of the six per-consumer Forgejo migrations called out in PR #274's follow-up backlog. Pipeline was flagged by review as the highest-value target because it's where raw Forgejo shapes (
IssueListEntry,PullRequestSummary,PullReview,WorkflowRunSummary) leaked furthest into view derivation.What changes
domain/views/pipeline.tsswitches fromforgejo-apiimports toForgePortshapes viaForgejoAdapterPipelineDepsDI signatures take port types;PROD_DEPSbuilds an adapter per callr.reviewer,r.state: "approved",r.commitSha,r.submittedAt) instead of raw Forgejo strings"approved","changes_requested","request_review")conclusionused toPort extensions surfaced by this migration
Review's concern #8 on PR #274 called out that shipping the port without consumers made the contract unverified. This migration uncovered three real gaps:
ForgeReview.stale— needed by the webhook-ci bounce path (future migration); already surfaced vialistPullReviewsForgeWorkflowRun.htmlUrl— pipeline picks the newest run's URL for the "click to see CI" stage linkReviewStateaddsrequest_review— distinct from submitted reviews with state"pending"; the review-stage stall detection needs this state to count pending reviewer requests separately from other pending verdictsTests
pipeline.test.ts/pipeline-stall.test.tsfixture helpers now constructForgeIssue/ForgePullRequest/ForgeReview/ForgeWorkflowRunreview()andworkflowRun()fixture builders to keep per-test fixtures terse{status: "completed", conclusion: "success"}in favour ofworkflowRun({status: "success"})— the port's resolved status eliminates the two-field danceChecks
bunx tsc --noEmit -p apps/server/tsconfig.json— EXIT=0bun --cwd apps/server test— 990 pass / 4 pre-existing fails (3 sweeper JSONL pruning + 1 foreman listSessions flaky — all present on main)Remaining migrations (per PR #274 follow-up)
board.ts— same Forgejo shapes as pipeline (next)webhook-handlers.ts,webhook-ci.ts,deps.ts,janitor.ts— mutating pathsagent-runner.ts+foreman.ts→ Claude SDK (Phase 5, requires agent-runner split).Pipeline was the biggest shape-leak site — IssueListEntry, PullRequestSummary, PullReview, WorkflowRunSummary all bled into the view derivation. This commit switches pipeline.ts and its 3 test files to the domain shapes from ForgePort. ### Port extensions surfaced by pipeline usage - `ForgeReview.stale` — Forgejo flags stranded pending requests stale; webhook-ci bounce path (future migration) needs this - `ForgeWorkflowRun.htmlUrl` — pipeline picks the newest run's URL as the stage's "click to see CI" link - `ReviewState` now includes `request_review` — distinct from submitted reviews with state "pending"; the review-stage stall detection needs this to count pending reviewer requests separately ### pipeline.ts changes - `PipelineDeps` signatures take ForgePort shapes; `PROD_DEPS` builds a `ForgejoAdapter` per call and delegates - Adapter's `listIssues` filters out PR-backed rows, so pipeline no longer needs the `!i.pull_request` guard - Derivation logic reads domain fields: `r.reviewer` / `r.state` / `r.commitSha` / `r.submittedAt` instead of `r.user.login` / raw Forgejo strings / `r.commit_id` / `r.submitted_at` - Review-state comparisons use the lowercase enum: `"approved"`, `"changes_requested"`, `"request_review"` - Workflow run status folding rewritten — the port's status field is already the terminal resolution (no separate `conclusion`), so the aggregate logic is simpler - `foldWorkflowRuns` no longer reads `conclusion`; the port's status enum ("success" | "failure" | "in_progress" | …) encodes what conclusion used to ### Tests - `pipeline.test.ts` / `pipeline-stall.test.ts` fixture helpers now construct ForgeIssue / ForgePullRequest / ForgeReview / ForgeWorkflowRun - Added `review()` and `workflowRun()` fixture builders to keep per-test fixtures terse - CI fixtures drop `{status: "completed", conclusion: "success"}` in favour of `workflowRun({status: "success"})` — the port's resolved status eliminates the two-field dance Full server suite: 990 pass / 4 pre-existing fails (3 sweeper JSONL pruning + 1 foreman listSessions flaky). Zero regressions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>