forked from molecule-ai/molecule-core
feat(canvas): add /api/buildinfo for version-display parity with tenant
Workspace-server has GET /buildinfo (PR #2398) — `curl https://<slug>. moleculesai.app/buildinfo` returns the live git SHA. Canvas had no parallel: debugging "is this the deployed code?" required reading Vercel's UI or response headers (deployment ID, not git SHA). Add canvas /api/buildinfo returning {git_sha, git_ref, vercel_env} sourced from VERCEL_GIT_COMMIT_SHA / _REF / VERCEL_ENV — Vercel injects these at build time from the deploying commit. Outside Vercel (local `next dev`, harness) all three are unset and the endpoint returns `git_sha: "dev"`, the same sentinel workspace-server uses pre-ldflags- injection. Now both surfaces speak the same vocabulary: curl https://<slug>.moleculesai.app/buildinfo curl https://canvas.moleculesai.app/api/buildinfo 3 tests cover dev-fallback, Vercel-injected SHA pass-through, and JSON content type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
46ca5aa6d3
commit
fc3b5fd385
48
canvas/src/app/api/buildinfo/__tests__/route.test.ts
Normal file
48
canvas/src/app/api/buildinfo/__tests__/route.test.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Canvas /api/buildinfo — version-display endpoint mirroring
|
||||
* workspace-server's /buildinfo. Lets `curl <url>/api/buildinfo`
|
||||
* confirm which git SHA is live on a canvas deployment.
|
||||
*/
|
||||
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
||||
import { GET } from "../route";
|
||||
|
||||
const ENV_KEYS = ["VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF", "VERCEL_ENV"];
|
||||
|
||||
describe("GET /api/buildinfo", () => {
|
||||
let saved: Record<string, string | undefined>;
|
||||
|
||||
beforeEach(() => {
|
||||
saved = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]]));
|
||||
for (const k of ENV_KEYS) delete process.env[k];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
for (const k of ENV_KEYS) {
|
||||
if (saved[k] === undefined) delete process.env[k];
|
||||
else process.env[k] = saved[k];
|
||||
}
|
||||
});
|
||||
|
||||
it("returns dev sentinel when Vercel env vars are unset", async () => {
|
||||
const res = await GET();
|
||||
const body = await res.json();
|
||||
expect(body).toEqual({ git_sha: "dev", git_ref: "", vercel_env: "local" });
|
||||
});
|
||||
|
||||
it("reports the SHA Vercel injected at build time", async () => {
|
||||
process.env.VERCEL_GIT_COMMIT_SHA = "abc1234567890";
|
||||
process.env.VERCEL_GIT_COMMIT_REF = "main";
|
||||
process.env.VERCEL_ENV = "production";
|
||||
const res = await GET();
|
||||
const body = await res.json();
|
||||
expect(body.git_sha).toBe("abc1234567890");
|
||||
expect(body.git_ref).toBe("main");
|
||||
expect(body.vercel_env).toBe("production");
|
||||
});
|
||||
|
||||
it("returns 200 status and JSON content type", async () => {
|
||||
const res = await GET();
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("content-type")).toContain("application/json");
|
||||
});
|
||||
});
|
||||
18
canvas/src/app/api/buildinfo/route.ts
Normal file
18
canvas/src/app/api/buildinfo/route.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
// Mirror of workspace-server's GET /buildinfo (PR #2398). Lets a developer
|
||||
// confirm which git SHA is live on a canvas deployment with the same
|
||||
// `curl <url>/buildinfo` flow they use against tenant workspaces.
|
||||
//
|
||||
// Vercel injects VERCEL_GIT_COMMIT_SHA / _REF / VERCEL_ENV at build time
|
||||
// from the deploying commit; outside Vercel (local `next dev`, harness)
|
||||
// these are unset and the endpoint reports `git_sha: "dev"`. Same sentinel
|
||||
// the workspace-server uses pre-ldflags-injection so both surfaces speak
|
||||
// the same vocabulary.
|
||||
export async function GET() {
|
||||
return NextResponse.json({
|
||||
git_sha: process.env.VERCEL_GIT_COMMIT_SHA ?? "dev",
|
||||
git_ref: process.env.VERCEL_GIT_COMMIT_REF ?? "",
|
||||
vercel_env: process.env.VERCEL_ENV ?? "local",
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user