feat(canvas): add /buildinfo endpoint exposing the build SHA (core#2235) #2253
Reference in New Issue
Block a user
Delete Branch "feat/core2235-canvas-buildinfo"
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?
Closes #2235.
Problem
The platform image exposes
GET /buildinfo({git_sha}) so the fleet redeploy workflow can poll each tenant and assert it runs the merge SHA before reporting success. The Next.js canvas had aGET /api/buildinforoute, but it only readVERCEL_GIT_COMMIT_SHA— which the canvas's ECR-image Docker deploy never sets (the fleet deploys the Docker image, not via Vercel). So the served SHA always reported"dev"and canvas deploys could only be verified indirectly (CI-green gate + immutable:staging-<sha>+ digest-pin), never by the served SHA.Change
Bake the merge SHA into the canvas image at build time and surface it through the existing route.
canvas/Dockerfile—ARG BUILD_SHA=dev->ENV BUILD_SHAin the final runtime stage. Server-only (notNEXT_PUBLIC_) so it stays out of the client bundle. Default"dev"matches workspace-server's sentinel, so an unwired build fails the SHA comparison closed.canvas/src/app/api/buildinfo/route.ts— priorityBUILD_SHA->VERCEL_GIT_COMMIT_SHA->"dev". Addedexport const dynamic = "force-dynamic"so the route readsBUILD_SHAfrom the standalone Node server's runtime env per request rather than freezing it atnext build..gitea/workflows/publish-canvas-image.yml— passBUILD_SHA=${{ github.sha }}(full 40-char SHA) inbuild-args, mirroring how the platform image wiresGIT_SHA.docker-compose.yml—BUILD_SHAbuild arg (defaultdev) for local compose builds.BUILD_SHAwins over the Vercel var, the Vercel fallback, and thedevdefault.Server-vs-static
canvas/next.config.tssetsoutput: "standalone"— the canvas ships a Node server, so this is a server route reading a server-only env, notNEXT_PUBLIC_(which would leak the SHA into the client bundle and freeze it into the static JS).next buildconfirms/api/buildinforenders asƒ (Dynamic) server-rendered on demand, soENV BUILD_SHAin the final image is read at request time.Route shape
GET /api/buildinfo->200 application/jsonFleet verification reads
.git_sha, same field name as workspace-server.Validation
npm ci+npx tsc --noEmit— no new errors in buildinfo files (223 pre-existing tsc errors on cleanmainin unrelated test files; this PR adds zero).npx vitest run src/app/api/buildinfo— 4/4 pass.npm run build— compiles;/api/buildinfoisƒ Dynamic.eslintclean on the route + test;publish-canvas-image.ymlanddocker-compose.ymlparse as valid YAML.Follow-up (flagged, not in scope)
core#2226's canvas deploy could poll this
/api/buildinfoper-tenant to assert the served SHA, the same way the platform redeploy workflow polls workspace-server's/buildinfo— a small wiring follow-up.🤖 Generated with Claude Code
The canvas /api/buildinfo route existed but only read VERCEL_GIT_COMMIT_SHA, which the fleet's ECR-image Docker deploy never sets — so the served SHA always reported "dev" and canvas deploys could not be verified by the served SHA the way the platform's /buildinfo is. Bake the merge SHA into the canvas image at build time and surface it: - canvas/Dockerfile: ARG BUILD_SHA=dev -> ENV BUILD_SHA in the final runtime stage (server-only, not NEXT_PUBLIC_, so it stays out of the client bundle). Default "dev" matches workspace-server's sentinel so an unwired build fails the SHA comparison closed. - route.ts: BUILD_SHA takes priority, then VERCEL_GIT_COMMIT_SHA, then "dev". force-dynamic so the route reads BUILD_SHA from the standalone Node server's runtime env per request (confirmed via next build: the route renders as Dynamic / server-rendered on demand). - publish-canvas-image.yml: pass BUILD_SHA=${{ github.sha }} (full 40-char SHA) so the fleet redeploy verification can match exactly. - docker-compose.yml: BUILD_SHA build arg (default "dev") for local builds. - test: assert BUILD_SHA wins over the Vercel var + the dev fallback. Follow-up (flagged, not in scope): core#2226's canvas deploy could poll this /api/buildinfo per-tenant to assert the served SHA, the same way the platform redeploy workflow polls workspace-server's /buildinfo. Closes #2235 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>QA review (core#2235 canvas /buildinfo). Additive observability route. Reviewed: BUILD_SHA priority chain (BUILD_SHA→VERCEL→dev), force-dynamic ensures runtime-env read under output:standalone, tests assert BUILD_SHA wins + dev fallback, server-only var stays out of client bundle, Dockerfile/workflow/compose wiring consistent. CI green (Canvas build + Playwright E2E). Approve.
Security review (core#2235). No secret/authz surface: /api/buildinfo exposes only the build SHA (same as workspace-server /buildinfo). BUILD_SHA is non-sensitive build metadata, server-only (not NEXT_PUBLIC). No new auth paths, no user input, no injection surface. Approve.