File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2626
2727 - run : uv sync --locked --all-extras --dev
2828
29+ # Hermetic: regenerates from the committed spec, so this verifies that the committed
30+ # generated code still reproduces from it, with no network dependency. Refreshing the
31+ # spec itself is the release workflow's job.
2932 - name : Codegen drift check
3033 if : matrix.python == '3.12'
34+ env :
35+ ROXYAPI_SPEC_FILE : specs/openapi.json
3136 run : |
3237 uv run python generate.py
3338 git diff --exit-code -- specs/openapi.json src/roxy_sdk/factory.py \
Original file line number Diff line number Diff line change 77"""
88
99import json
10+ import os
1011import shutil
1112import subprocess
1213import sys
@@ -35,9 +36,22 @@ def _fetch_with_retry(url: str, attempts: int = 5) -> bytes:
3536 raise RuntimeError ("unreachable" )
3637
3738
38- def fetch_spec () -> dict :
39+ def _load_raw_spec () -> bytes :
40+ """Read the spec from disk when ROXYAPI_SPEC_FILE is set, fetch it otherwise.
41+
42+ Reading from a file keeps generation offline and byte-reproducible, which is what the
43+ codegen drift check in CI relies on.
44+ """
45+ spec_file = os .environ .get ("ROXYAPI_SPEC_FILE" )
46+ if spec_file :
47+ print (f"Reading OpenAPI spec from { spec_file } (offline, ROXYAPI_SPEC_FILE)" )
48+ return Path (spec_file ).read_bytes ()
3949 print (f"Fetching OpenAPI spec from { SPEC_URL } " )
40- spec = json .loads (_fetch_with_retry (SPEC_URL ))
50+ return _fetch_with_retry (SPEC_URL )
51+
52+
53+ def fetch_spec () -> dict :
54+ spec = json .loads (_load_raw_spec ())
4155
4256 # Patch server URL to absolute prod URL
4357 if spec .get ("servers" ) and spec ["servers" ][0 ].get ("url" ) == "/api/v2" :
You can’t perform that action at this time.
0 commit comments