summaryrefslogtreecommitdiff
path: root/cgithub/scripts/build.ts
diff options
context:
space:
mode:
authorJoe Mou <dev@mou.fo>2026-08-11 08:37:25 -0400
committerJoe Mou <dev@mou.fo>2026-08-11 08:38:30 -0400
commitab52f48e50d0dd242ad5b0cfbee9c458946cd427 (patch)
treebeb9519f163cd1ee2b229c8811b4de636c76078b /cgithub/scripts/build.ts
parent2b4a69720b53480d82cf296ac5dbe4614d9470b9 (diff)
Show the build's commit in the page footer
Workers can't shell out at request time, so the commit has to be baked in before wrangler bundles the sources. compile-views.ts grows a second job and becomes scripts/build.ts: alongside the precompiled views it writes src/commit.generated.ts with `git describe --tags --always --dirty`, which yields a bare short hash until the repo is tagged and marks builds made from an unclean working copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'cgithub/scripts/build.ts')
-rw-r--r--cgithub/scripts/build.ts52
1 files changed, 52 insertions, 0 deletions
diff --git a/cgithub/scripts/build.ts b/cgithub/scripts/build.ts
new file mode 100644
index 0000000..766e5e8
--- /dev/null
+++ b/cgithub/scripts/build.ts
@@ -0,0 +1,52 @@
+// Generates the sources that can't exist at runtime on Workers:
+//
+// src/views.generated.ts - views/*.eta precompiled into plain functions.
+// Workers disallow runtime code generation (`new Function`), so Eta cannot
+// compile templates there at request time.
+// src/commit.generated.ts - the commit this build was made from, for the
+// page footer. Workers can't shell out to git at request time either.
+import { execFileSync } from "node:child_process";
+import { Eta } from "eta";
+import fs from "node:fs";
+import path from "node:path";
+
+const root = path.join(import.meta.dirname, "..");
+const viewsDir = path.join(root, "views");
+const eta = new Eta({ views: viewsDir });
+
+const names = fs
+ .readdirSync(viewsDir)
+ .filter((name) => name.endsWith(".eta"))
+ .sort();
+
+let out = `// @ts-nocheck
+// Generated by scripts/build.ts -- do not edit.
+export const views = {
+`;
+for (const name of names) {
+ const source = fs.readFileSync(path.join(viewsDir, name), "utf8");
+ const body = eta.compileToString(source);
+ out += ` ${JSON.stringify(name)}: function (it, options) {\n${body}\n },\n`;
+}
+out += "};\n";
+
+fs.writeFileSync(path.join(root, "src", "views.generated.ts"), out);
+console.log(`Compiled ${names.length} templates to src/views.generated.ts`);
+
+// Untagged repositories describe as a bare short hash; --dirty marks a build
+// made from an unclean working copy.
+let commit = "unknown";
+try {
+ commit = execFileSync("git", ["describe", "--tags", "--always", "--dirty"], {
+ cwd: root,
+ encoding: "utf8",
+ }).trim();
+} catch {
+ // Building from a source copy without git history.
+}
+
+fs.writeFileSync(
+ path.join(root, "src", "commit.generated.ts"),
+ `// Generated by scripts/build.ts -- do not edit.\nexport const commit = ${JSON.stringify(commit)};\n`,
+);
+console.log(`Wrote commit ${commit} to src/commit.generated.ts`);