Skip to content

refactor(dashboard): SSoT GitHub links in deploy routes#6389

Merged
ogzhanolguncu merged 9 commits into
mainfrom
ssot-github-deploy-link
Jun 10, 2026
Merged

refactor(dashboard): SSoT GitHub links in deploy routes#6389
ogzhanolguncu merged 9 commits into
mainfrom
ssot-github-deploy-link

Conversation

@ogzhanolguncu

@ogzhanolguncu ogzhanolguncu commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

TLDR; we were creating Github URLs all over the /projects routes, but now we call them from the single place.

Problem

We are constructing Github URLs all over the place, because we need to tell people what caused that deployment or which branch/repo leads to where in Github.

Fix

Instead of constructing them manually in every component we need, we'll thread them through functions like these. This will give us ability to control those in a single place and allow us to add prefixes, suffixes if need to URLs.

export function githubRepoUrl(repoFullName: RepoName): string | undefined {
  return repoFullName ? `${GITHUB_BASE}/${repoFullName}` : undefined;
}

export function githubCommitUrl(
  repoFullName: RepoName,
  sha: string | null | undefined,
): string | undefined {
  return repoFullName && sha ? `${GITHUB_BASE}/${repoFullName}/commit/${sha}` : undefined;
}

....

Test

mise exec -- pnpm --dir=web/apps/dashboard vitest run lib/navigation/url.test.ts lib/github-url.test.ts

Those should pass.

Setup

  • Create a project and trigger a deployment.
  • Open a preview URL and run a few cURLs against it.

GitHub links (each resolves to the right page)

  • Project > Requests detail links work.
image
  • Create deployment button (create-deployment-button.tsx) → branch.
Screenshot 2026-06-09 at 11 33 38
  • Resource card (resource-card.tsx) in app list + project list → correct PR number, else commit.
Screenshot 2026-06-09 at 11 36 22
  • Active deployment card (active-deployment-card) marked items → correct commit/branch.
Screenshot 2026-06-09 at 11 41 58
  • Deployment approval (deployment-approval.tsx) generates correct URLs. Fork case: open a PR from a fork — commit/branch links point at the fork repo, the PR link at the base repo.

@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dashboard Ready Ready Preview, Comment Jun 10, 2026 7:50pm
design Ready Ready Preview, Comment Jun 10, 2026 7:50pm

Request Review

@ogzhanolguncu ogzhanolguncu changed the title Ssot GitHub deploy link refactor(dashboard): SSoT GitHub links in deploy routes Jun 9, 2026
@ogzhanolguncu ogzhanolguncu marked this pull request as ready for review June 9, 2026 09:16

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — a behavior-preserving refactor that consolidates ad-hoc https://github.com/... string construction across deploy-route components into a single source-of-truth module.

  • New github-urls.ts module — five builders (githubRepoUrl, githubCommitUrl, githubBranchUrl, githubPullUrl, githubDeploymentUrl) that each return undefined when a required part is missing, so callers fall back to plain text instead of rendering broken links.
  • Fork-aware routing in githubDeploymentUrl — prefers the PR link (always anchored to the base repo) and falls back to the commit on forkRepoFullName || repoFullName, with the prNumber != null gate correctly treating 0 as present.
  • Consumers rewiredsentinel-log-details, deployment-approval, project-details-content, create-deployment-button, active-deployment-card, and both list views now thread URLs through the builders; all use truthiness checks, so the prior null sentinel becoming undefined is behaviorally inert.
  • tRPC list endpointsdeploy/app/list.ts and deploy/project/list.ts now select gitCommitSha, prNumber, and forkRepositoryFullName from deployments and flatten them into list payloads; collection schemas (apps.ts, projects.ts) and optimistic-insert sites gain the matching nullable fields.
  • Thorough vitest coveragegithub-urls.test.ts exercises every builder, the missing-part fallbacks, the prNumber === 0 edge case, and fork-vs-base PR routing.

The only real behavior change is in resource-card.tsx: the commit title in project/app lists was previously a dead <Link href="#"> and now renders a real external <a> (or a plain <span> for image-based deployments). That is an intended improvement. Schema additions match the existing deployments.ts types, and all link consumers preserve their fallback semantics. Clean and mergeable.

Pullfrog  | View workflow run | Using Claude Opus𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one minor scope observation inline.

Reviewed changes — the delta since the prior pullfrog review (c1beac0) reworks the github-link layer from standalone functions into a namespaced object backed by a new generic url-assembly module.

  • Renamed github-urls.tsgithub-url.ts — the five standalone builders (githubRepoUrl, githubCommitUrl, etc.) become methods on a single githubUrl object (.repo, .commit, .branch, .pull, .deployment); all consumers and the test suite are rewired accordingly. Output is identical, so this is behavior-preserving.
  • New lib/navigation/url.ts module — low-level verbatim url assembly (buildUrl, withQuery, toQueryString); the githubUrl builders now delegate to buildUrl instead of inlining template literals.
  • Test coveragelib/navigation/url.test.ts exercises buildUrl/withQuery/toQueryString (including the null/undefined-drop and 0/false-keep semantics, and unencoded : in values); github-url.test.ts updated to the new namespace.

The refactor is sound and the new module is well-tested. The verbatim no-encoding contract is consistent with the dashboard's existing ?<field>=<operator>:<value> logs-filter convention.

ℹ️ navigation/url ships query-string machinery with no production caller

The new module exports withQuery and toQueryString, and buildUrl accepts a query part — but every production caller is github-url.ts, which only ever passes base + segments and never query. The query path is currently exercised solely by its own tests.

This isn't a bug, and the dashboard's logs-filter URLs are an obvious future consumer, so it's reasonable to keep. Flagging only because AGENTS.md calls out "no speculative features" — worth a one-line confirmation that the query helpers are intended to land a follow-up that wires them into the logs-nav builders, rather than sitting dead.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread web/apps/dashboard/lib/navigation/url.ts

@dave-hawkins dave-hawkins left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Would be good to get others opinions too tho, but i don't have any strong opinions on this!

@mcstepp mcstepp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — the delta since the prior pullfrog review (a4cca98) is one substantive correctness fix to the project-list payload; the rest is a Merge branch 'main' pulling base-branch progress.

  • Fixed repo/commit mismatch in deploy/project/list.ts — the repo lookup was keyed by project.id, so a multi-app project could pair its primary app's commit/PR with whichever repo connection won for the project. The query now selects apps.id (stored as appId on primaryAppByProject) and githubRepoConnections.appId, and repoByApp is keyed by appId so the repo matches the app that supplied the commit. This aligns project/list.ts with app/list.ts, which already keyed by appId.

The fix is sound: github_repo_connections.app_id is notNull().unique() in the schema, so the appId key is a safe unique identity and the repoByApp.has(row.appId) dedup is harmless/defensive. The repo query also gains an inArray(githubRepoConnections.projectId, projectIds) scope, narrowing it from all workspace connections — behavior-preserving given the keyed lookup. The inline comment explaining the multi-app rationale is accurate. Prior informational thread (review 4459458696) is resolved — author confirmed PR #6393 will consume the query helpers.

Pullfrog  | View workflow run | Using Claude Opus𝕏

Merged via the queue into main with commit 1e7bda8 Jun 10, 2026
15 checks passed
@ogzhanolguncu ogzhanolguncu deleted the ssot-github-deploy-link branch June 10, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants