11#!/usr/bin/env node
22/**
3- * Contract: vercel.json wires x-release-id; production-like stamp ≠ "dev".
3+ * Contract: Edge Middleware (or Astro middleware) wires x-release-id;
4+ * production-like module stamp ≠ "dev".
45 */
56import { execFileSync } from "node:child_process" ;
6- import { readFileSync } from "node:fs" ;
7+ import { existsSync , readFileSync } from "node:fs" ;
78import { dirname , resolve } from "node:path" ;
89import { fileURLToPath } from "node:url" ;
910
1011const repoRoot = resolve ( dirname ( fileURLToPath ( import . meta. url ) ) , ".." ) ;
11- const vercelPath = resolve ( repoRoot , "vercel.json" ) ;
1212
13- function headerValue ( config ) {
14- for ( const block of config . headers ?? [ ] ) {
15- for ( const h of block . headers ?? [ ] ) {
16- if ( String ( h . key ) . toLowerCase ( ) === "x-release-id" ) return h . value ;
17- }
13+ const edgeMw = resolve ( repoRoot , "middleware.ts" ) ;
14+ const astroMw = resolve ( repoRoot , "src/middleware.ts" ) ;
15+ if ( existsSync ( edgeMw ) ) {
16+ const src = readFileSync ( edgeMw , "utf8" ) ;
17+ if ( ! src . includes ( "x-release-id" ) || ! src . includes ( "VERCEL_GIT_COMMIT_SHA" ) ) {
18+ console . error ( "FAIL: root middleware.ts must set x-release-id from VERCEL_GIT_COMMIT_SHA" ) ;
19+ process . exit ( 1 ) ;
1820 }
19- return undefined ;
20- }
21-
22- const committed = JSON . parse ( readFileSync ( vercelPath , "utf8" ) ) ;
23- const committedVal = headerValue ( committed ) ;
24- if ( committedVal === undefined ) {
25- console . error ( "FAIL: vercel.json missing x-release-id header" ) ;
21+ } else if ( existsSync ( astroMw ) ) {
22+ const src = readFileSync ( astroMw , "utf8" ) ;
23+ if ( ! src . includes ( "x-release-id" ) ) {
24+ console . error ( "FAIL: src/middleware.ts must set x-release-id" ) ;
25+ process . exit ( 1 ) ;
26+ }
27+ } else {
28+ console . error ( "FAIL: missing middleware.ts (Edge) or src/middleware.ts (Astro)" ) ;
2629 process . exit ( 1 ) ;
2730}
28- if ( committedVal !== "dev" ) {
29- console . error ( `FAIL: committed vercel.json x-release-id must be "dev" (got ${ committedVal } )` ) ;
30- process . exit ( 1 ) ;
31+
32+ const vercelPath = resolve ( repoRoot , "vercel.json" ) ;
33+ if ( existsSync ( vercelPath ) ) {
34+ const vercel = readFileSync ( vercelPath , "utf8" ) ;
35+ if ( / x - r e l e a s e - i d / i. test ( vercel ) ) {
36+ console . error (
37+ "FAIL: do not put x-release-id in vercel.json (committed value sticks; use Edge Middleware)" ,
38+ ) ;
39+ process . exit ( 1 ) ;
40+ }
3141}
3242
3343const sha = "abcdef1234567890deadbeef" ;
@@ -36,34 +46,18 @@ execFileSync(process.execPath, [resolve(repoRoot, "scripts/gen-release-id.mjs")]
3646 env : { ...process . env , VERCEL_GIT_COMMIT_SHA : sha } ,
3747 stdio : "inherit" ,
3848} ) ;
39-
40- const stamped = JSON . parse ( readFileSync ( vercelPath , "utf8" ) ) ;
41- const stampedVal = headerValue ( stamped ) ;
42- const expected = sha . slice ( 0 , 12 ) ;
43- if ( stampedVal !== expected ) {
44- console . error ( `FAIL: stamped x-release-id expected ${ expected } , got ${ stampedVal } ` ) ;
45- process . exit ( 1 ) ;
46- }
47- if ( stampedVal === "dev" ) {
48- console . error ( "FAIL: production-like stamp must not be dev" ) ;
49+ const stamped = readFileSync ( resolve ( repoRoot , "src/release-id.ts" ) , "utf8" ) ;
50+ if ( ! stamped . includes ( `RELEASE_ID = "${ sha . slice ( 0 , 12 ) } "` ) ) {
51+ console . error ( "FAIL: module stamp missing expected SHA" ) ;
4952 process . exit ( 1 ) ;
5053}
5154
5255execFileSync ( process . execPath , [ resolve ( repoRoot , "scripts/restore-release-stub.mjs" ) ] , {
5356 cwd : repoRoot ,
54- env : { ...process . env , VERCEL : "" } ,
5557 stdio : "inherit" ,
5658} ) ;
57-
58- const restored = JSON . parse ( readFileSync ( vercelPath , "utf8" ) ) ;
59- if ( headerValue ( restored ) !== "dev" ) {
60- console . error ( "FAIL: restore did not reset x-release-id to dev" ) ;
61- process . exit ( 1 ) ;
62- }
63-
64- // Ensure module stub is back
65- const mod = readFileSync ( resolve ( repoRoot , "src/release-id.ts" ) , "utf8" ) ;
66- if ( ! mod . includes ( 'RELEASE_ID = "dev"' ) ) {
59+ const restored = readFileSync ( resolve ( repoRoot , "src/release-id.ts" ) , "utf8" ) ;
60+ if ( ! restored . includes ( 'RELEASE_ID = "dev"' ) ) {
6761 console . error ( "FAIL: release-id.ts stub not restored" ) ;
6862 process . exit ( 1 ) ;
6963}
0 commit comments