@se-studio/site-check 2.1.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `smoke-test-deploy-check` CLI for post-build Vercel smoke gates (`SMOKE_TEST_SKIP_BUILD` on `smoke-test-one`). Export `resolveSmokePortFromConfig` from the smoke-test module.
8
+
9
+ ## 2.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 911334e: Add preview smoke test API (`runPreviewStaticSmokeTest`) and canonical Vercel env helpers (`PREVIEW_SITE_URL`, `VERCEL_PROTECTION_BYPASS_TOKEN`, `SITEMAP_PROD_URL`, `PRODUCTION_SITE_URL`). `fetch-options` and `--vercel-bypass` now resolve bypass from `VERCEL_PROTECTION_BYPASS_TOKEN` first.
14
+
3
15
  ## 2.1.3
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -23,7 +23,10 @@ npx @se-studio/site-check https://example.com --check-against http://localhost:3
23
23
  # Enable rewrite check (optional; off by default)
24
24
  npx @se-studio/site-check https://example.com --check-rewrites
25
25
 
26
- # Vercel Deployment Protection: use env secret
26
+ # Vercel Deployment Protection: use env secret (preferred name)
27
+ VERCEL_PROTECTION_BYPASS_TOKEN=your-secret npx @se-studio/site-check https://preview.vercel.app --vercel-bypass
28
+
29
+ # Legacy alias still works
27
30
  VERCEL_AUTOMATION_BYPASS_SECRET=your-secret npx @se-studio/site-check https://preview.vercel.app --vercel-bypass
28
31
 
29
32
  # Vercel bypass with explicit secret
@@ -68,7 +71,7 @@ Use this to ensure a development or staging build has the same pages as producti
68
71
  | `--check-against <devUrl>` | Compare mode: use production sitemap(s) but check that each page exists on development (same path on `<devUrl>`). No markdown download. |
69
72
  | `--check-rewrites` | Enable checking for unexpected rewrites (x-nextjs-rewritten-path). Default: off. When set, the run fails if any sitemap page URL rewrites to a different path (locale-only rewrites allowed with `SITE_CHECK_LOCALES`). |
70
73
  | `--ignore-missing-child-sitemaps` | When the root sitemap (or `sitemap-unindexed.xml`) is a **sitemap index**, any child `<loc>` that returns **404** is skipped instead of failing validation. Other non-2xx responses still fail. After skipping, at least one page URL must still be collected from the remaining children. |
71
- | `--vercel-bypass [secret]` | Set `x-vercel-protection-bypass` for [Vercel Deployment Protection](https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation). If `secret` is omitted, uses `VERCEL_AUTOMATION_BYPASS_SECRET` from the environment. |
74
+ | `--vercel-bypass [secret]` | Set `x-vercel-protection-bypass` for [Vercel Deployment Protection](https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation). If `secret` is omitted, uses `VERCEL_PROTECTION_BYPASS_TOKEN` from the environment (aliases: `VERCEL_AUTOMATION_BYPASS_SECRET`, `VERCEL_BYPASS_TOKEN`). |
72
75
 
73
76
  Headers from `-H` override the Vercel bypass header if the same name is used.
74
77
 
@@ -77,6 +80,10 @@ Headers from `-H` override the Vercel bypass header if the same name is used.
77
80
  | Variable | Description |
78
81
  |----------|-------------|
79
82
  | `SITE_CHECK_LOCALES` | Comma-separated list of locale path segments (e.g. `en,en-gb,de`). When set, a rewrite is considered acceptable if the only difference between the requested path and the rewritten path is a leading locale segment. If unset, any rewrite to a different path fails. |
83
+ | `PREVIEW_SITE_URL` | Vercel develop/preview deployment base URL (preview smoke tests, protected preview fetches). Trailing slash is stripped. |
84
+ | `SITEMAP_PROD_URL` | Public production site base URL (sitemap-validate scripts, smoke case curation). Trailing slash is stripped. |
85
+ | `PRODUCTION_SITE_URL` | Production site base URL for audits and tooling that need a canonical prod origin. Trailing slash is stripped. |
86
+ | `VERCEL_PROTECTION_BYPASS_TOKEN` | Vercel Deployment Protection bypass secret (Vercel → Settings → Deployment Protection). Sent as `x-vercel-protection-bypass`. Aliases: `VERCEL_AUTOMATION_BYPASS_SECRET`, `VERCEL_BYPASS_TOKEN`. |
80
87
 
81
88
  ## Production HTML audit (`@se-studio/site-check/production-audit`)
82
89
 
@@ -98,7 +105,7 @@ Curated local smoke tests for marketing sites: verify HTML and `.md` for URLs li
98
105
 
99
106
  Import from `@se-studio/site-check/smoke-test`:
100
107
 
101
- - `loadStaticSmokeConfig`, `runStaticSmokeTest`, `runSmokeTest`
108
+ - `loadStaticSmokeConfig`, `runStaticSmokeTest`, `runPreviewStaticSmokeTest`, `runSmokeTest`
102
109
  - `formatSmokeTestReport`, `getSmokeTestExitCode`
103
110
 
104
111
  **Per-app usage** (see `apps/example-empty`):
@@ -108,22 +115,37 @@ pnpm build --filter @se-studio/site-check # once, or after package changes
108
115
  cd apps/example-empty
109
116
  pnpm smoke-test:run # dev server must be running on app port
110
117
  pnpm smoke-test # dev server + smoke (default dev:dev) + stop
118
+ pnpm smoke-test:preview # curated cases against Vercel preview (no local server)
111
119
  ```
112
120
 
113
- Add `smoke.cases.json` and `scripts/smoke-test-run.ts`. No Contentful or `cms-server` imports required. Set `SMOKE_TEST_IGNORE=true` in `.env.local` to skip the full `smoke-test` CI script.
121
+ Add `smoke.cases.json`, `scripts/smoke-test-run.ts`, and optionally `scripts/smoke-test-preview.ts` (or use `node ../../scripts/smoke-test-preview.mjs` from the app directory). No Contentful or `cms-server` imports required. Set `SMOKE_TEST_IGNORE=true` in `.env.local` to skip the full `smoke-test` CI script.
122
+
123
+ **Preview smoke** (`runPreviewStaticSmokeTest`): reads `PREVIEW_SITE_URL` and `VERCEL_PROTECTION_BYPASS_TOKEN` from `.env.local` (or `process.env`), applies the bypass header, and runs the same curated cases against the live preview deployment. No local dev server required.
114
124
 
115
125
  **`smoke-test-one` env:**
116
126
 
117
127
  | Variable | Purpose |
118
128
  |----------|---------|
119
129
  | `SMOKE_TEST_SERVER_SCRIPT=dev:dev` | Default dev server; use `start` for prod-like server (runs `pnpm build` first) |
130
+ | `SMOKE_TEST_SKIP_BUILD=true` | Skip `pnpm build` when `SERVER_SCRIPT=start` (use after Vercel `next build`) |
120
131
  | `SMOKE_TEST_VERIFY_CACHE=true` | Run smoke twice; assert `x-nextjs-cache` on HTML (meaningful with `start`, soft in `next dev`) |
121
132
  | `SMOKE_TEST_AUDIT_CACHE_LOGS=true` | Pipe server/build logs and scan for 2MB cache failures, `cache skip`, and `hard refresh` |
122
133
  | `SMOKE_TEST_CACHE_SKIP_SEVERITY=warn` | `warn` or `error` for cache-skip log lines (default `warn`) |
123
134
  | `SMOKE_TEST_READY_PATH=/` | Path polled until the server responds |
135
+ | `SMOKE_TEST_USE_RUNNING_SERVER=false` | Force a fresh server (default `true` for local dev) |
124
136
 
125
137
  `LOG_CMS_FETCH=1` is set when verify-cache or audit-cache-logs is enabled. The smoke HTTP client never sends `Cache-Control: no-cache`.
126
138
 
139
+ **Deploy check** (`smoke-test-deploy-check`): post-build gate for Vercel — starts `pnpm start` without rebuilding, runs `pnpm smoke-test:run`, exits non-zero on failure. Port defaults from `smoke.cases.json`. Set `SMOKE_TEST_IGNORE=true` in Vercel env to bypass in an emergency.
140
+
141
+ ```json
142
+ {
143
+ "buildCommand": "pnpm build && pnpm smoke-test:deploy-check"
144
+ }
145
+ ```
146
+
147
+ Per-app script: `"smoke-test:deploy-check": "smoke-test-deploy-check"` (or `node ../../scripts/smoke-test-deploy-check.mjs` in the monorepo).
148
+
127
149
  ## Exit codes
128
150
 
129
151
  - `0` — Validation passed (sitemap.xml required; llms.txt and sitemap-unindexed.xml optional). If `--check-rewrites` was set, no unexpected rewrites. Every sitemap page returned 200 for its `.md` URL and files were saved (or in compare mode: all production sitemap pages exist on development and, if `--check-rewrites`, no unexpected rewrites).
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-options.d.ts","sourceRoot":"","sources":["../src/fetch-options.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,UAAU,iBAAiB;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAqBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,WAAW,CAuBvE"}
1
+ {"version":3,"file":"fetch-options.d.ts","sourceRoot":"","sources":["../src/fetch-options.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,iBAAiB;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAqBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,WAAW,CAuBvE"}
@@ -2,8 +2,7 @@
2
2
  * Build shared RequestInit (headers) for all fetch calls.
3
3
  * Supports generic -H / --header and --vercel-bypass for Vercel Deployment Protection.
4
4
  */
5
- const VERCEL_BYPASS_HEADER = 'x-vercel-protection-bypass';
6
- const VERCEL_BYPASS_ENV = 'VERCEL_AUTOMATION_BYPASS_SECRET';
5
+ import { resolveProtectionBypass, VERCEL_PROTECTION_BYPASS_HEADER } from './vercel-env.js';
7
6
  /**
8
7
  * Parse a "Name: value" header string. Handles optional quotes around value.
9
8
  */
@@ -32,10 +31,10 @@ export function buildFetchOptions(input) {
32
31
  const bypassSecret = input.vercelBypassSecret !== undefined && input.vercelBypassSecret !== null
33
32
  ? input.vercelBypassSecret
34
33
  : input.vercelBypassRequested
35
- ? (process.env[VERCEL_BYPASS_ENV] ?? '')
34
+ ? (resolveProtectionBypass() ?? '')
36
35
  : '';
37
36
  if (bypassSecret) {
38
- headers.set(VERCEL_BYPASS_HEADER, bypassSecret);
37
+ headers.set(VERCEL_PROTECTION_BYPASS_HEADER, bypassSecret);
39
38
  }
40
39
  // 2. User -H headers (override bypass if same name)
41
40
  for (const arg of input.headerArgs ?? []) {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-options.js","sourceRoot":"","sources":["../src/fetch-options.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;AAC1D,MAAM,iBAAiB,GAAG,iCAAiC,CAAC;AAW5D;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,kCAAkC;IAClC,MAAM,YAAY,GAChB,KAAK,CAAC,kBAAkB,KAAK,SAAS,IAAI,KAAK,CAAC,kBAAkB,KAAK,IAAI;QACzE,CAAC,CAAC,KAAK,CAAC,kBAAkB;QAC1B,CAAC,CAAC,KAAK,CAAC,qBAAqB;YAC3B,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;IACX,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAAC;IAClD,CAAC;IAED,oDAAoD;IACpD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"fetch-options.js","sourceRoot":"","sources":["../src/fetch-options.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAW3F;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,kCAAkC;IAClC,MAAM,YAAY,GAChB,KAAK,CAAC,kBAAkB,KAAK,SAAS,IAAI,KAAK,CAAC,kBAAkB,KAAK,IAAI;QACzE,CAAC,CAAC,KAAK,CAAC,kBAAkB;QAC1B,CAAC,CAAC,KAAK,CAAC,qBAAqB;YAC3B,CAAC,CAAC,CAAC,uBAAuB,EAAE,IAAI,EAAE,CAAC;YACnC,CAAC,CAAC,EAAE,CAAC;IACX,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,oDAAoD;IACpD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -1,6 +1,7 @@
1
+ export { createProtectedFetch, requirePreviewBaseUrl, requireProtectionBypass, requireSitemapProdUrl, resolvePreviewBaseUrl, resolveProductionSiteUrl, resolveProtectionBypass, resolveSitemapProdUrl, VERCEL_PROTECTION_BYPASS_HEADER, } from '../vercel-env.js';
1
2
  export type { CacheLogAuditMatch, CacheLogAuditOptions, CacheLogAuditResult, CacheLogAuditSeverity, } from './cache-log-audit.js';
2
3
  export { auditCacheLogs, formatCacheLogAuditReport, getCacheLogAuditExitCode, } from './cache-log-audit.js';
3
4
  export { formatSmokeTestReport, getSmokeTestExitCode, isSmokeTestCacheVerifyResult, parseNextJsCacheHeader, runSmokeTest, runSmokeTestWithCacheVerify, } from './runner.js';
4
- export { joinSmokeBaseUrl, loadStaticSmokeConfig, runStaticSmokeTest } from './static.js';
5
- export type { LoadStaticSmokeConfigOptions, NextJsCacheStatus, RunStaticSmokeTestOptions, SmokeFailureReason, SmokeTestCacheVerifyResult, SmokeTestCase, SmokeTestCaseResult, SmokeTestCategory, SmokeTestResult, SmokeTestRunnerConfig, StaticSmokeCaseDefinition, StaticSmokeConfigFile, } from './types.js';
5
+ export { joinSmokeBaseUrl, loadStaticSmokeConfig, resolveSmokePortFromConfig, runPreviewStaticSmokeTest, runStaticSmokeTest, } from './static.js';
6
+ export type { LoadStaticSmokeConfigOptions, NextJsCacheStatus, RunPreviewStaticSmokeTestOptions, RunStaticSmokeTestOptions, SmokeFailureReason, SmokeTestCacheVerifyResult, SmokeTestCase, SmokeTestCaseResult, SmokeTestCategory, SmokeTestResult, SmokeTestRunnerConfig, StaticSmokeCaseDefinition, StaticSmokeConfigFile, } from './types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/smoke-test/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC1F,YAAY,EACV,4BAA4B,EAC5B,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/smoke-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,4BAA4B,EAC5B,iBAAiB,EACjB,gCAAgC,EAChC,yBAAyB,EACzB,kBAAkB,EAClB,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -1,4 +1,5 @@
1
+ export { createProtectedFetch, requirePreviewBaseUrl, requireProtectionBypass, requireSitemapProdUrl, resolvePreviewBaseUrl, resolveProductionSiteUrl, resolveProtectionBypass, resolveSitemapProdUrl, VERCEL_PROTECTION_BYPASS_HEADER, } from '../vercel-env.js';
1
2
  export { auditCacheLogs, formatCacheLogAuditReport, getCacheLogAuditExitCode, } from './cache-log-audit.js';
2
3
  export { formatSmokeTestReport, getSmokeTestExitCode, isSmokeTestCacheVerifyResult, parseNextJsCacheHeader, runSmokeTest, runSmokeTestWithCacheVerify, } from './runner.js';
3
- export { joinSmokeBaseUrl, loadStaticSmokeConfig, runStaticSmokeTest } from './static.js';
4
+ export { joinSmokeBaseUrl, loadStaticSmokeConfig, resolveSmokePortFromConfig, runPreviewStaticSmokeTest, runStaticSmokeTest, } from './static.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/smoke-test/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/smoke-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
@@ -1,5 +1,10 @@
1
- import type { LoadStaticSmokeConfigOptions, RunStaticSmokeTestOptions, SmokeTestCacheVerifyResult, SmokeTestResult, SmokeTestRunnerConfig } from './types.js';
1
+ import type { LoadStaticSmokeConfigOptions, RunPreviewStaticSmokeTestOptions, RunStaticSmokeTestOptions, SmokeTestCacheVerifyResult, SmokeTestResult, SmokeTestRunnerConfig } from './types.js';
2
2
  export declare function joinSmokeBaseUrl(baseUrl: string, path: string): string;
3
+ export declare function resolveSmokePortFromConfig(filePath: string, options?: {
4
+ cwd?: string;
5
+ portOverride?: number;
6
+ }): number;
3
7
  export declare function loadStaticSmokeConfig(filePath: string, options?: LoadStaticSmokeConfigOptions): SmokeTestRunnerConfig;
4
8
  export declare function runStaticSmokeTest(filePath: string, options?: RunStaticSmokeTestOptions): Promise<SmokeTestResult | SmokeTestCacheVerifyResult>;
9
+ export declare function runPreviewStaticSmokeTest(filePath: string, options?: RunPreviewStaticSmokeTestOptions): Promise<SmokeTestResult>;
5
10
  //# sourceMappingURL=static.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/smoke-test/static.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,4BAA4B,EAC5B,yBAAyB,EACzB,0BAA0B,EAE1B,eAAe,EACf,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAItE;AAaD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,4BAA4B,GACrC,qBAAqB,CA0BvB;AASD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,eAAe,GAAG,0BAA0B,CAAC,CAUvD"}
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/smoke-test/static.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,4BAA4B,EAC5B,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,EAE1B,eAAe,EACf,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAItE;AAaD,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,MAAM,CAWR;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,4BAA4B,GACrC,qBAAqB,CAyBvB;AASD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,eAAe,GAAG,0BAA0B,CAAC,CAUvD;AASD,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gCAAgC,GACzC,OAAO,CAAC,eAAe,CAAC,CAiB1B"}
@@ -1,5 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
+ import { createProtectedFetch, requirePreviewBaseUrl, requireProtectionBypass, resolveProtectionBypass, } from '../vercel-env.js';
3
4
  import { runSmokeTest, runSmokeTestWithCacheVerify } from './runner.js';
4
5
  export function joinSmokeBaseUrl(baseUrl, path) {
5
6
  const normalizedBase = baseUrl.replace(/\/$/, '');
@@ -16,6 +17,18 @@ function resolvePort(config, portOverride) {
16
17
  }
17
18
  return config.port;
18
19
  }
20
+ export function resolveSmokePortFromConfig(filePath, options) {
21
+ if (options?.portOverride !== undefined) {
22
+ return options.portOverride;
23
+ }
24
+ const cwd = options?.cwd ?? process.cwd();
25
+ const absolutePath = resolve(cwd, filePath);
26
+ const raw = JSON.parse(readFileSync(absolutePath, 'utf8'));
27
+ if (!raw.port || !Number.isFinite(raw.port)) {
28
+ throw new Error(`Invalid smoke config port: ${absolutePath}`);
29
+ }
30
+ return raw.port;
31
+ }
19
32
  export function loadStaticSmokeConfig(filePath, options) {
20
33
  const cwd = options?.cwd ?? process.cwd();
21
34
  const absolutePath = resolve(cwd, filePath);
@@ -23,8 +36,7 @@ export function loadStaticSmokeConfig(filePath, options) {
23
36
  if (!raw.siteName || !raw.port || !Array.isArray(raw.cases)) {
24
37
  throw new Error(`Invalid smoke config: ${absolutePath}`);
25
38
  }
26
- const port = resolvePort(raw, options?.portOverride);
27
- const baseUrl = `http://localhost:${port}`;
39
+ const baseUrl = options?.baseUrl ?? `http://localhost:${resolvePort(raw, options?.portOverride)}`;
28
40
  const cases = raw.cases.map((entry) => ({
29
41
  category: entry.category,
30
42
  label: entry.label,
@@ -56,4 +68,26 @@ export async function runStaticSmokeTest(filePath, options) {
56
68
  }
57
69
  return runSmokeTest(runnerConfig);
58
70
  }
71
+ function resolvePreviewBaseUrl(options) {
72
+ if (options?.baseUrl) {
73
+ return options.baseUrl.replace(/\/$/, '');
74
+ }
75
+ return requirePreviewBaseUrl(options?.env);
76
+ }
77
+ export async function runPreviewStaticSmokeTest(filePath, options) {
78
+ const requireBypass = options?.requireBypass ?? true;
79
+ if (requireBypass) {
80
+ requireProtectionBypass(options?.env);
81
+ }
82
+ const baseUrl = resolvePreviewBaseUrl(options);
83
+ const config = loadStaticSmokeConfig(filePath, { ...options, baseUrl });
84
+ const bypassSecret = requireBypass
85
+ ? requireProtectionBypass(options?.env)
86
+ : resolveProtectionBypass(options?.env);
87
+ const fetchFn = createProtectedFetch(bypassSecret, options?.fetch ?? fetch);
88
+ return runSmokeTest({
89
+ ...config,
90
+ fetch: fetchFn,
91
+ });
92
+ }
59
93
  //# sourceMappingURL=static.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/smoke-test/static.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/smoke-test/static.ts"],"names":[],"mappings":"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"}
@@ -53,11 +53,18 @@ export interface SmokeTestRunnerConfig {
53
53
  export interface LoadStaticSmokeConfigOptions {
54
54
  cwd?: string;
55
55
  portOverride?: number;
56
+ /** Remote base URL (e.g. Vercel preview). When set, `port` in the JSON file is ignored for URL resolution. */
57
+ baseUrl?: string;
58
+ env?: NodeJS.ProcessEnv;
56
59
  }
57
60
  export interface RunStaticSmokeTestOptions extends LoadStaticSmokeConfigOptions {
58
61
  fetch?: typeof fetch;
59
62
  verifyCache?: boolean;
60
63
  }
64
+ export interface RunPreviewStaticSmokeTestOptions extends RunStaticSmokeTestOptions {
65
+ /** When true (default), require VERCEL_PROTECTION_BYPASS_TOKEN (or alias) in env. */
66
+ requireBypass?: boolean;
67
+ }
61
68
  export interface SmokeTestCacheVerifyResult {
62
69
  pass1: SmokeTestResult;
63
70
  pass2: SmokeTestResult;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/smoke-test/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,MAAM,GACN,oBAAoB,GACpB,SAAS,GACT,QAAQ,GACR,gBAAgB,GAChB,KAAK,GACL,0BAA0B,GAC1B,YAAY,GACZ,gBAAgB,GAChB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,yBAAyB,EAAE,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,kBAAkB,GAClB,6BAA6B,GAC7B,oBAAoB,CAAC;AAEzB,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,yBAA0B,SAAQ,4BAA4B;IAC7E,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,eAAe,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/smoke-test/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare const VERCEL_PROTECTION_BYPASS_HEADER = "x-vercel-protection-bypass";
2
+ export declare function resolveProtectionBypass(env?: NodeJS.ProcessEnv): string | undefined;
3
+ export declare function requireProtectionBypass(env?: NodeJS.ProcessEnv): string;
4
+ export declare function resolvePreviewBaseUrl(env?: NodeJS.ProcessEnv): string | undefined;
5
+ export declare function requirePreviewBaseUrl(env?: NodeJS.ProcessEnv): string;
6
+ export declare function resolveSitemapProdUrl(env?: NodeJS.ProcessEnv): string | undefined;
7
+ export declare function requireSitemapProdUrl(env?: NodeJS.ProcessEnv): string;
8
+ export declare function resolveProductionSiteUrl(env?: NodeJS.ProcessEnv): string | undefined;
9
+ export declare function createProtectedFetch(bypassSecret?: string, baseFetch?: typeof fetch): typeof fetch;
10
+ //# sourceMappingURL=vercel-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-env.d.ts","sourceRoot":"","sources":["../src/vercel-env.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,+BAA+B,CAAC;AAgB5E,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAQhG;AAED,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CASpF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAM9F;AAED,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAQlF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAM9F;AAED,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAMlF;AAED,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAMjG;AAED,wBAAgB,oBAAoB,CAClC,YAAY,CAAC,EAAE,MAAM,EACrB,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,KAAK,CAWd"}
@@ -0,0 +1,76 @@
1
+ export const VERCEL_PROTECTION_BYPASS_HEADER = 'x-vercel-protection-bypass';
2
+ const BYPASS_ENV_KEYS = [
3
+ 'VERCEL_PROTECTION_BYPASS_TOKEN',
4
+ 'VERCEL_AUTOMATION_BYPASS_SECRET',
5
+ 'VERCEL_BYPASS_TOKEN',
6
+ ];
7
+ function trimTrailingSlash(value) {
8
+ return value.replace(/\/$/, '');
9
+ }
10
+ function readEnvValue(env, key) {
11
+ return (env[key] ?? '').trim();
12
+ }
13
+ export function resolveProtectionBypass(env = process.env) {
14
+ for (const key of BYPASS_ENV_KEYS) {
15
+ const value = readEnvValue(env, key);
16
+ if (value) {
17
+ return value;
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ export function requireProtectionBypass(env = process.env) {
23
+ const value = resolveProtectionBypass(env);
24
+ if (!value) {
25
+ throw new Error('Set VERCEL_PROTECTION_BYPASS_TOKEN in .env.local (Vercel → Settings → Deployment Protection). ' +
26
+ 'Aliases VERCEL_AUTOMATION_BYPASS_SECRET and VERCEL_BYPASS_TOKEN are also accepted.');
27
+ }
28
+ return value;
29
+ }
30
+ export function resolvePreviewBaseUrl(env = process.env) {
31
+ const value = readEnvValue(env, 'PREVIEW_SITE_URL');
32
+ if (!value) {
33
+ return undefined;
34
+ }
35
+ return trimTrailingSlash(value);
36
+ }
37
+ export function requirePreviewBaseUrl(env = process.env) {
38
+ const value = resolvePreviewBaseUrl(env);
39
+ if (!value) {
40
+ throw new Error('Set PREVIEW_SITE_URL in .env.local to your Vercel develop/preview deployment URL.');
41
+ }
42
+ return value;
43
+ }
44
+ export function resolveSitemapProdUrl(env = process.env) {
45
+ const value = readEnvValue(env, 'SITEMAP_PROD_URL');
46
+ if (!value) {
47
+ return undefined;
48
+ }
49
+ return trimTrailingSlash(value);
50
+ }
51
+ export function requireSitemapProdUrl(env = process.env) {
52
+ const value = resolveSitemapProdUrl(env);
53
+ if (!value) {
54
+ throw new Error('Set SITEMAP_PROD_URL in .env.local to the public production site URL.');
55
+ }
56
+ return value;
57
+ }
58
+ export function resolveProductionSiteUrl(env = process.env) {
59
+ const value = readEnvValue(env, 'PRODUCTION_SITE_URL');
60
+ if (!value) {
61
+ return undefined;
62
+ }
63
+ return trimTrailingSlash(value);
64
+ }
65
+ export function createProtectedFetch(bypassSecret, baseFetch = fetch) {
66
+ const secret = bypassSecret ?? resolveProtectionBypass();
67
+ if (!secret) {
68
+ return baseFetch;
69
+ }
70
+ return (url, init = {}) => {
71
+ const headers = new Headers(init.headers);
72
+ headers.set(VERCEL_PROTECTION_BYPASS_HEADER, secret);
73
+ return baseFetch(url, { ...init, headers });
74
+ };
75
+ }
76
+ //# sourceMappingURL=vercel-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-env.js","sourceRoot":"","sources":["../src/vercel-env.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@se-studio/site-check",
3
- "version": "2.1.3",
3
+ "version": "2.3.0",
4
4
  "description": "Validate SE marketing sites (sitemap, llms.txt) and download markdown files preserving structure",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,12 +36,14 @@
36
36
  "bin": {
37
37
  "site-check": "./dist/cli.js",
38
38
  "site-check-screaming-frog": "./dist/screaming-frog-cli.js",
39
- "smoke-test-one": "./smoke-test-one.mjs"
39
+ "smoke-test-one": "./smoke-test-one.mjs",
40
+ "smoke-test-deploy-check": "./smoke-test-deploy-check.mjs"
40
41
  },
41
42
  "files": [
42
43
  "dist",
43
44
  "*.md",
44
- "smoke-test-one.mjs"
45
+ "smoke-test-one.mjs",
46
+ "smoke-test-deploy-check.mjs"
45
47
  ],
46
48
  "keywords": [
47
49
  "sitemap",
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-build deployment smoke check: start production server (no rebuild) and run smoke-test:run.
5
+ * Usage: smoke-test-deploy-check [port] (from app directory; port from smoke.cases.json if omitted)
6
+ *
7
+ * Env (set automatically; override if needed):
8
+ * SMOKE_TEST_SKIP_BUILD=true
9
+ * SMOKE_TEST_USE_RUNNING_SERVER=false
10
+ * SMOKE_TEST_SERVER_SCRIPT=start
11
+ * SMOKE_TEST_IGNORE=true — skip entirely (emergency bypass on Vercel)
12
+ */
13
+
14
+ import { spawn } from 'node:child_process';
15
+ import fs from 'node:fs';
16
+ import path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ const packageDir = path.dirname(fileURLToPath(import.meta.url));
20
+ const appDir = process.cwd();
21
+
22
+ function resolvePort(portArg) {
23
+ if (portArg && /^\d+$/.test(portArg)) {
24
+ return portArg;
25
+ }
26
+
27
+ const configPath = path.join(appDir, 'smoke.cases.json');
28
+ if (!fs.existsSync(configPath)) {
29
+ console.error('Usage: smoke-test-deploy-check [port]');
30
+ console.error(' Port required when smoke.cases.json is missing.');
31
+ process.exit(1);
32
+ }
33
+
34
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
35
+ if (!config.port || !Number.isFinite(config.port)) {
36
+ console.error(`Invalid port in ${configPath}`);
37
+ process.exit(1);
38
+ }
39
+
40
+ return String(config.port);
41
+ }
42
+
43
+ const port = resolvePort(process.argv[2]);
44
+ const smokeTestOnePath = path.join(packageDir, 'smoke-test-one.mjs');
45
+
46
+ const env = {
47
+ ...process.env,
48
+ SMOKE_TEST_SKIP_BUILD: 'true',
49
+ SMOKE_TEST_USE_RUNNING_SERVER: 'false',
50
+ SMOKE_TEST_SERVER_SCRIPT: 'start',
51
+ };
52
+
53
+ const child = spawn(process.execPath, [smokeTestOnePath, port], {
54
+ cwd: appDir,
55
+ stdio: 'inherit',
56
+ env,
57
+ });
58
+
59
+ child.on('error', (error) => {
60
+ console.error(error);
61
+ process.exit(1);
62
+ });
63
+
64
+ child.on('exit', (code) => {
65
+ process.exit(code ?? 1);
66
+ });
@@ -12,6 +12,7 @@
12
12
  * SMOKE_TEST_CACHE_SKIP_SEVERITY=warn — cache-skip log severity: warn | error (default warn)
13
13
  * SMOKE_TEST_READY_PATH=/ — path polled until server responds
14
14
  * SMOKE_TEST_USE_RUNNING_SERVER=true — reuse server already on port (default true)
15
+ * SMOKE_TEST_SKIP_BUILD=true — skip pnpm build when SERVER_SCRIPT=start (post-build deploy check)
15
16
  * LOG_CMS_FETCH=1 — set when VERIFY_CACHE or AUDIT_CACHE_LOGS is true
16
17
  */
17
18
 
@@ -190,11 +191,12 @@ const useRunningServer = (env.SMOKE_TEST_USE_RUNNING_SERVER ?? 'true').toLowerCa
190
191
  const readyPath = env.SMOKE_TEST_READY_PATH ?? '/';
191
192
  const readyUrl = `${baseUrl}${readyPath.startsWith('/') ? readyPath : `/${readyPath}`}`;
192
193
  const isProductionStart = serverScript === 'start';
194
+ const skipBuild = (env.SMOKE_TEST_SKIP_BUILD ?? '').toLowerCase() === 'true';
193
195
  const startTimeoutMs = isProductionStart ? 120_000 : 300_000;
194
196
 
195
197
  const logBuffer = { text: '' };
196
198
 
197
- if (isProductionStart) {
199
+ if (isProductionStart && !skipBuild) {
198
200
  console.log('Building app...');
199
201
  const buildResult = spawnSync('pnpm', ['build'], {
200
202
  cwd: appDir,