Skip to content

Commit c4ce953

Browse files
committed
Add build version and commit visibility in UI and health endpoint
1 parent 6d0ed5c commit c4ce953

7 files changed

Lines changed: 74 additions & 8 deletions

File tree

functions/_lib/buildInfo.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const APP_VERSION = "0.0.0";
2+
export const APP_COMMIT = "6d0ed5c0";
3+
export const APP_BUILD_LABEL = `v${APP_VERSION}+${APP_COMMIT}`;

functions/_lib/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ export type Env = {
3333
DEV_AUTH_USER_ID?: string;
3434
ADMIN_USER_IDS?: string;
3535
REGISTRATION_MODE?: string;
36+
CF_PAGES_URL?: string;
37+
CF_PAGES_BRANCH?: string;
38+
CF_PAGES_COMMIT_SHA?: string;
3639
GEOCODE_RATE_LIMIT_PER_MINUTE?: string;
3740
PROXY_RATE_LIMIT_PER_MINUTE?: string;
3841
VE2DBE_TILELIST_RATE_LIMIT_PER_MINUTE?: string;

functions/api/health.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
import { handleOptions, json, withCors } from "../_lib/http";
22
import type { Env } from "../_lib/types";
3+
import { APP_BUILD_LABEL, APP_COMMIT, APP_VERSION } from "../_lib/buildInfo";
34

45
export const onRequestOptions: PagesFunction<Env> = async ({ request }) => handleOptions(request);
56

6-
export const onRequestGet: PagesFunction<Env> = async ({ request }) =>
7+
const PROD_HOSTS = new Set(["linksim.wilhelmfrancke.com", "linksim.pages.dev"]);
8+
9+
const normalizeHost = (host: string): string => host.trim().toLowerCase();
10+
11+
export const onRequestGet: PagesFunction<Env> = async ({ request, env }) =>
712
withCors(
813
request,
9-
json({
10-
ok: true,
11-
service: "linksim-api",
12-
ts: new Date().toISOString(),
13-
}),
14+
(() => {
15+
const url = new URL(request.url);
16+
const host = normalizeHost(url.hostname);
17+
const envName = PROD_HOSTS.has(host) ? "production" : "test";
18+
return json({
19+
ok: true,
20+
service: "linksim-api",
21+
ts: new Date().toISOString(),
22+
build: {
23+
version: APP_VERSION,
24+
commit: APP_COMMIT,
25+
label: APP_BUILD_LABEL,
26+
},
27+
runtime: {
28+
env: envName,
29+
host,
30+
pagesUrl: env.CF_PAGES_URL ?? null,
31+
pagesBranch: env.CF_PAGES_BRANCH ?? null,
32+
pagesCommitSha: env.CF_PAGES_COMMIT_SHA ?? null,
33+
},
34+
});
35+
})(),
1436
);

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
"license": "GPL-3.0-only",
66
"type": "module",
77
"scripts": {
8+
"build:meta": "node scripts/generate-build-info.mjs",
89
"dev": "vite --config config/vite.config.ts",
9-
"build:client": "vite build --config config/vite.config.ts",
10+
"build:client": "npm run build:meta && vite build --config config/vite.config.ts",
1011
"dev:edge": "npm run build:client && npx wrangler pages dev dist --d1 DB=linksim --r2 AVATAR_BUCKET=linksim-avatars --binding ALLOW_INSECURE_DEV_AUTH=true --binding DEV_AUTH_USER_ID=local-dev-user --local --persist-to .wrangler/state",
11-
"build": "tsc -b config/tsconfig.json && vite build --config config/vite.config.ts",
12+
"build": "npm run build:meta && tsc -b config/tsconfig.json && vite build --config config/vite.config.ts",
1213
"lint": "eslint .",
1314
"preview": "vite preview --config config/vite.config.ts",
1415
"test": "vitest run --config config/vitest.config.ts",

scripts/generate-build-info.mjs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env node
2+
import { execSync } from "node:child_process";
3+
import { readFileSync, writeFileSync } from "node:fs";
4+
import { resolve } from "node:path";
5+
6+
const root = resolve(new URL("..", import.meta.url).pathname);
7+
const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
8+
9+
const shortSha = (() => {
10+
const envSha = process.env.CF_PAGES_COMMIT_SHA || process.env.GITHUB_SHA || "";
11+
if (envSha.trim()) return envSha.trim().slice(0, 8);
12+
try {
13+
return execSync("git rev-parse --short=8 HEAD", { cwd: root, stdio: ["ignore", "pipe", "ignore"] })
14+
.toString("utf8")
15+
.trim();
16+
} catch {
17+
return "unknown";
18+
}
19+
})();
20+
21+
const version = String(pkg.version ?? "0.0.0");
22+
23+
const content = `export const APP_VERSION = "${version}";
24+
export const APP_COMMIT = "${shortSha}";
25+
export const APP_BUILD_LABEL = \`v\${APP_VERSION}+\${APP_COMMIT}\`;
26+
`;
27+
28+
writeFileSync(resolve(root, "src/lib/buildInfo.ts"), content, "utf8");
29+
writeFileSync(resolve(root, "functions/_lib/buildInfo.ts"), content, "utf8");
30+
console.log(`[build-info] ${version}+${shortSha}`);

src/components/Sidebar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { FREQUENCY_PRESETS } from "../lib/frequencyPlans";
1717
import { searchLocations, type GeocodeResult } from "../lib/geocode";
1818
import { LEGACY_ASSETS } from "../lib/legacyAssets";
1919
import { isCurrentTestEnvironment } from "../lib/environment";
20+
import { APP_BUILD_LABEL } from "../lib/buildInfo";
2021
import {
2122
fetchCollaboratorDirectory,
2223
fetchResourceChanges,
@@ -2031,6 +2032,9 @@ export function Sidebar() {
20312032
</div>
20322033
<details className="compact-details">
20332034
<summary>Credits & Attribution</summary>
2035+
<p className="field-help subtle-note">
2036+
Build: {APP_BUILD_LABEL} ({isCurrentTestEnvironment() ? "test" : "production"})
2037+
</p>
20342038
<p className="field-help subtle-note">
20352039
Inspired by{" "}
20362040
<a href={PRIMARY_ATTRIBUTION.projectUrl} rel="noreferrer" target="_blank">

src/lib/buildInfo.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const APP_VERSION = "0.0.0";
2+
export const APP_COMMIT = "6d0ed5c0";
3+
export const APP_BUILD_LABEL = `v${APP_VERSION}+${APP_COMMIT}`;

0 commit comments

Comments
 (0)