release acceptance matrix: tools/acceptance.ts runs every user-facing command from the packed npm tarball (npx --package=<tgz> on Node 20 / 22, bun x --bun after bun add <tgz>) in fresh temp folders with a fresh HOME, real piped stdin (n, EOF) and per-cell fake stores over HTTP (STOREBOUND_STORE_MOCK, loopback only); a cell passes only with the expected exit code and no crash text; report -> markdown matrix. Prompts go through stdinIsTTY (STOREBOUND_ASSUME_TTY drives them with piped stdin), STOREBOUND_DESKTOP_APP=none for the install prompt on a machine with the app. release.yml: required acceptance job matrix (Linux + Windows x node20/node22/bun) and report, the matrix attached to the release; ci.yml: the quick subset on Linux and Windows. Scan fixtures for React Native and Expo
This commit is contained in:
parent
ae681e3ecd
commit
f58e192001
26 changed files with 926 additions and 15 deletions
32
cli/lib/store-mock-env.ts
Normal file
32
cli/lib/store-mock-env.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// STOREBOUND_STORE_MOCK=http://127.0.0.1:<port>: every request to a store host (App Store Connect, Google APIs, the
|
||||
// public store pages, the example.com placeholders) goes to that local double instead, as
|
||||
// <mock>/__host/<host>/<path>. The release acceptance matrix (tools/acceptance.ts) runs the packed npm tarball this
|
||||
// way against the fake stores of tests/helpers/fake-stores.ts, on every platform and runtime. Only a loopback address
|
||||
// (with an optional path: the matrix gives every cell its own store) is accepted, so the variable can never send store keys or tokens to another machine. Unset: nothing changes.
|
||||
|
||||
const STORE_HOST = /^(?:[a-z0-9-]+\.)*(?:apple\.com|googleapis\.com|google\.com|example\.com)$/i;
|
||||
const LOOPBACK = /^http:\/\/(?:127\.0\.0\.1|localhost|\[::1\]):\d{1,5}(?:\/[\w.-]+)*$/;
|
||||
|
||||
/** The URL a request goes to under the mock (unchanged for hosts that are not store hosts). */
|
||||
export function mockedUrl(url: string, base: string): string {
|
||||
let u: URL;
|
||||
try { u = new URL(url); } catch { return url; }
|
||||
if (u.protocol !== 'https:' || !STORE_HOST.test(u.hostname)) return url;
|
||||
return `${base}/__host/${u.hostname}${u.pathname}${u.search}`;
|
||||
}
|
||||
|
||||
/** Installs the redirect when STOREBOUND_STORE_MOCK is set; throws on a non-loopback value. */
|
||||
export function installStoreMock(env: Record<string, string | undefined> = process.env): boolean {
|
||||
const base = env.STOREBOUND_STORE_MOCK?.replace(/\/+$/, '');
|
||||
if (!base) return false;
|
||||
if (!LOOPBACK.test(base)) throw new Error(`STOREBOUND_STORE_MOCK must be a loopback address like http://127.0.0.1:8080 (got ${JSON.stringify(base)})`);
|
||||
const real = globalThis.fetch;
|
||||
globalThis.fetch = ((input: string | URL | Request, init?: RequestInit) => {
|
||||
if (input instanceof Request) {
|
||||
const to = mockedUrl(input.url, base);
|
||||
return real(to === input.url ? input : new Request(to, input), init);
|
||||
}
|
||||
return real(mockedUrl(String(input), base), init);
|
||||
}) as typeof fetch;
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue