chore: show build info in UI#1146
Conversation
📝 WalkthroughWalkthroughThis PR implements a version information display feature across the stack. The Workspace Engine exposes its version via the ChangesVersion Information Display
Sequence DiagramsequenceDiagram
participant User as User
participant Web as Web App
participant API
participant Engine as Workspace Engine
User->>Web: Load workspace
Web->>Web: VersionBadge reads VITE_CTRLPLANE_VERSION
Web->>Web: useServiceVersions hook mounts
Web->>API: GET /api/version
API->>API: read env.CTRLPLANE_VERSION
API->>Engine: fetch /healthz (2000ms timeout)
Engine-->>API: { version, status, service }
API-->>Web: { api, workspaceEngine }
Web->>User: Render version badge with dialog
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/app/components/VersionBadge.tsx`:
- Around line 22-23: Replace the direct fetch call in VersionBadge (the function
that currently does `const response = await fetch("/api/version"); return
response.json();`) with the shared OpenAPI client: import and call createClient
from `~/api/openapi-client`, instantiate the client (e.g., `const client =
createClient()`), then call the appropriate generated operation (the REST
endpoint for version) on the client instead of `fetch`, and return/handle its
typed response; update any local types/await handling to match the client's
return shape.
- Around line 22-24: The code calls response.json() unconditionally after
fetch("/api/version") which can throw on non-2xx responses; update the fetch
logic in VersionBadge (the function that performs fetch("/api/version")) to
check response.ok before parsing, and if not OK either throw a descriptive error
or return a safe fallback (e.g., null) so the caller/query doesn't enter an
unexpected error state; reference the response variable and the response.json()
call when making this change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: aa4a23dd-1bf9-4b00-8b22-d1313fb41c1a
📒 Files selected for processing (6)
apps/api/src/config.tsapps/api/src/routes/version.tsapps/api/src/server.tsapps/web/app/components/VersionBadge.tsxapps/web/app/routes/ws/_layout.tsxapps/workspace-engine/svc/http/server/server.go
| const response = await fetch("/api/version"); | ||
| return response.json(); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Use the shared OpenAPI client for this REST call.
This direct fetch("/api/version") bypasses the web app’s REST client convention and can drift from shared request behavior.
As per coding guidelines, "Use createClient from ~/api/openapi-client for REST-only endpoints".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/components/VersionBadge.tsx` around lines 22 - 23, Replace the
direct fetch call in VersionBadge (the function that currently does `const
response = await fetch("/api/version"); return response.json();`) with the
shared OpenAPI client: import and call createClient from `~/api/openapi-client`,
instantiate the client (e.g., `const client = createClient()`), then call the
appropriate generated operation (the REST endpoint for version) on the client
instead of `fetch`, and return/handle its typed response; update any local
types/await handling to match the client's return shape.
| const response = await fetch("/api/version"); | ||
| return response.json(); | ||
| }, |
There was a problem hiding this comment.
Guard non-OK responses before JSON parsing.
response.json() is called unconditionally; on non-2xx responses this can throw and put the query into an error state unnecessarily.
Proposed fix
queryFn: async (): Promise<ServiceVersions> => {
const response = await fetch("/api/version");
- return response.json();
+ if (!response.ok) {
+ return { api: "—", workspaceEngine: null };
+ }
+ return (await response.json()) as ServiceVersions;
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const response = await fetch("/api/version"); | |
| return response.json(); | |
| }, | |
| queryFn: async (): Promise<ServiceVersions> => { | |
| const response = await fetch("/api/version"); | |
| if (!response.ok) { | |
| return { api: "—", workspaceEngine: null }; | |
| } | |
| return (await response.json()) as ServiceVersions; | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/components/VersionBadge.tsx` around lines 22 - 24, The code
calls response.json() unconditionally after fetch("/api/version") which can
throw on non-2xx responses; update the fetch logic in VersionBadge (the function
that performs fetch("/api/version")) to check response.ok before parsing, and if
not OK either throw a descriptive error or return a safe fallback (e.g., null)
so the caller/query doesn't enter an unexpected error state; reference the
response variable and the response.json() call when making this change.
There was a problem hiding this comment.
Pull request overview
Adds runtime/build version visibility across Ctrlplane services and exposes it in the web UI to address #1122 (“show build info in the UI like argo does”).
Changes:
- Workspace-engine
/healthznow includes aversionfield. - API adds a public
/api/versionendpoint that returns API version plus workspace-engine version (queried via/healthz). - Web app adds a
VersionBadgein the workspace sidebar footer that opens an “About Ctrlplane” dialog showing web/api/workspace-engine versions.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| apps/workspace-engine/svc/http/server/server.go | Adds version to the workspace-engine health check response. |
| apps/web/app/routes/ws/_layout.tsx | Renders the new VersionBadge in the sidebar footer. |
| apps/web/app/components/VersionBadge.tsx | New UI component + react-query fetch to display versions in a dialog. |
| apps/api/src/server.ts | Registers /api/version and excludes it from OpenAPI request validation. |
| apps/api/src/routes/version.ts | Implements /api/version handler and workspace-engine version fetch w/ timeout. |
| apps/api/src/config.ts | Introduces CTRLPLANE_VERSION env var (default dev). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return useQuery({ | ||
| queryKey: ["version"], | ||
| queryFn: async (): Promise<ServiceVersions> => { | ||
| const response = await fetch("/api/version"); |
fixes #1122
Summary by CodeRabbit