Skip to content

Commit c3d64fc

Browse files
committed
ci: regenerate from the committed spec so the drift check is hermetic
1 parent 4321d1f commit c3d64fc

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ jobs:
2929

3030
- run: composer install --prefer-dist --no-interaction
3131

32+
# Hermetic: regenerates from the committed spec, so this verifies that the committed
33+
# generated code still reproduces from it, with no network dependency. Refreshing the
34+
# spec itself is the release workflow's job.
3235
- name: Codegen drift check
3336
if: matrix.php == '8.2'
37+
env:
38+
ROXYAPI_SPEC_FILE: specs/openapi.json
3439
run: |
3540
node scripts/generate.mjs
3641
git diff --exit-code -- specs/openapi.json src/Generated src/Roxy.php src/Version.php tests/Generated \

scripts/generate.mjs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,25 @@ async function fetchSpec(url, attempts = 5) {
5353
}
5454
}
5555

56-
console.log(`[generate] fetching ${SPEC_URL}`);
57-
const spec = await fetchSpec(SPEC_URL);
56+
/**
57+
* Load the spec from disk when `ROXYAPI_SPEC_FILE` is set, from `SPEC_URL` otherwise.
58+
*
59+
* @remarks
60+
* Orthogonal to `ROXYAPI_OPENAPI_URL`, which points the fetch at a different server. This one skips
61+
* the network entirely, keeping generation offline and byte-reproducible, which is what the codegen
62+
* drift check in CI relies on.
63+
*/
64+
async function loadSpec() {
65+
const file = process.env.ROXYAPI_SPEC_FILE;
66+
if (file) {
67+
console.log(`[generate] reading ${file} (offline, ROXYAPI_SPEC_FILE)`);
68+
return JSON.parse(await fs.readFile(file, 'utf8'));
69+
}
70+
console.log(`[generate] fetching ${SPEC_URL}`);
71+
return fetchSpec(SPEC_URL);
72+
}
73+
74+
const spec = await loadSpec();
5875

5976
// Patch server URL to absolute production URL so the connector works without
6077
// users supplying a baseUrl (matches the TS + Python SDKs).

0 commit comments

Comments
 (0)