@@ -67,7 +67,7 @@ The [mise](https://mise.jdx.dev/) configuration pins `openapi-python-client`,
6767The ` generate ` task runs ` generator/scripts/generate.sh ` on the checked-in
6868` generator/openapi/spec.json ` (no download). It refuses to overwrite uncommitted
6969changes in ` upcloud_api/ ` unless you pass ` mise run generate --force ` .
70- ` mise run regenerate ` runs ` generate ` , then the ` check ` gate , and stops at the
70+ ` mise run regenerate ` runs ` generate ` , then ` check ` , and stops at the
7171first failure with a non-zero exit. The generated changes stay in place for
7272investigation. Neither task changes ` pyproject.toml ` or ` uv.lock ` . A stale lock
7373fails the ` uv ` commands, and only ` mise run lock ` and ` mise run version:set ` update it.
@@ -111,66 +111,51 @@ UV_PYTHON=pypy3.11 mise run test:unit
111111| --- | --- |
112112| ` setup ` | Install locked development dependencies. |
113113| ` lint ` | Run pre-commit: ruff, shellcheck, and actionlint. |
114- | ` test:tools ` | L1: test the shared shell scripts offline with bats. |
115- | ` test:preprocess ` | L2: test schema-title filtering ( ` test_strip_schema_titles.py ` ) , overlay fixes, and the endpoint checker. |
116- | ` test:unit ` | L4: test the generated SDK and the contract-case derivation offline . |
117- | ` check:generated ` | L3: regenerate and fail if ` upcloud_api/ ` or ` spec.patched.json ` changes. |
118- | ` check:endpoints ` | L3: check that every spec operation has a generated method/path contract . |
119- | ` test:contract ` | L5: run generated sync/async SDK calls against a local Wiretap mock. |
120- | ` check ` | Integrity gate : ` lint ` , ` test:tools ` , ` test:preprocess ` , ` test:unit ` , ` check:generated ` . Must be green . Alias: ` test ` . |
121- | ` findings ` | Findings gate: ` check:endpoints ` and ` test:contract ` , run even if one fails. Red on known defects . |
122- | ` validate ` | Run ` check ` and ` findings ` , even if ` check ` fails. Kept for one release. |
114+ | ` test:tools ` | Test the shell scripts offline with bats. |
115+ | ` test:preprocess ` | Test schema-title filtering, overlay fixes, and the endpoint checker. |
116+ | ` test:unit ` | Run offline unit tests for the SDK and Wiretap test cases . |
117+ | ` check:generated ` | Regenerate and fail if ` upcloud_api/ ` or ` spec.patched.json ` changes. |
118+ | ` check:endpoints ` | Check that every spec operation has generated code . |
119+ | ` test:contract ` | Run generated sync/async SDK calls against a local Wiretap mock. |
120+ | ` check ` | Run required checks : ` lint ` , ` test:tools ` , ` test:preprocess ` , ` test:unit ` , ` check:generated ` . Alias: ` test ` . |
121+ | ` findings ` | Run ` check:endpoints ` and ` test:contract ` ( fails on known spec and generator issues) . |
122+ | ` validate ` | Run ` check ` and ` findings ` , even if ` check ` fails. |
123123| ` build ` | Build a wheel and source distribution into ` dist/ ` , then run ` twine check ` . |
124124| ` generate [--force] ` | Regenerate the SDK from the checked-in spec. |
125125| ` regenerate ` | Run ` generate ` , then ` check ` , and stop at the first failure. |
126126| ` lock ` | Update ` uv.lock ` . |
127- | ` version:set <version> ` | Explicitly change ` [project].version ` in ` pyproject.toml ` and ` uv.lock ` with ` uv version --no-sync ` . |
127+ | ` version:set <version> ` | Set ` [project].version ` in ` pyproject.toml ` and ` uv.lock ` with ` uv version --no-sync ` . |
128128| ` spec:download <version> <asset_url> ` | Download a released spec using ` SPECS_ACCESS_PAT ` (used by the regeneration workflow). |
129- | ` examples [name...] ` | L6: run live mdtest documents , all four by default. |
129+ | ` examples [name...] ` | Run live mdtest examples , all four by default. |
130130
131- ### Test layers and gates
131+ ### Checks and contract tests
132132
133- Every check belongs to one layer, and every defect fails exactly one check.
133+ ` check ` runs the required static, unit, and generation checks. It blocks builds,
134+ releases, and regeneration PRs.
134135
135- | Layer | Guards | Members |
136- | --- | --- | --- |
137- | L1 tools | The shared shell scripts behave safely. | ` generator/scripts/tests/*.bats ` |
138- | L2 preprocess | Overlay fixes and title filtering are correct and idempotent. | ` generator/tests/test_strip_schema_titles.py ` , ` test_openapi_overlay.py ` , ` test_endpoint_coverage.py ` |
139- | L3 generation | Committed output equals generator output, and every spec operation is generated. | ` check:generated ` , ` check:endpoints ` |
140- | L4 SDK unit | Generated imports, enums, ` client.py.jinja ` behavior, contract-case derivation. | ` tests/test_sdk_smoke.py ` , ` tests/test_wiretap_cases.py ` |
141- | L5 contract | SDK calls match the spec on the wire. | ` tests/test_wiretap.py ` via ` wiretap.sh ` |
142- | L6 live | Real API behavior. | ` examples/**/*.md ` via mdtest |
143-
144- There are two gates. ` check ` (integrity) must always be green: a red ` check `
145- means the pipeline itself is broken. It blocks builds, releases, and regeneration
146- PRs. ` findings ` covers the known spec and generator defects: a red ` findings `
147- means the spec or generator still has a known defect. It always runs and uploads
148- its diagnostics, but it does not block releases. Regeneration PRs are opened as
149- drafts while it fails.
136+ ` findings ` runs ` check:endpoints ` and ` test:contract ` to report known spec and
137+ generator issues without blocking releases. Regeneration PRs are opened as
138+ drafts when ` findings ` fails.
150139
151140` mise install ` installs every pinned tool, including ` wiretap ` , ` bats ` ,
152141` shellcheck ` , ` actionlint ` , ` twine ` , and ` mdtest ` (built with the pinned Go).
153142Wiretap runs as a local binary in mock mode and doesn't need Docker or Podman.
154143No task except ` examples ` needs UpCloud credentials or makes real UpCloud requests,
155144but the first run needs network access to install tools and dependencies.
156145
157- The existing endpoint and Wiretap findings remain strict failures, not exemptions.
158- ` generator/scripts/wiretap.sh ` starts Wiretap, sends a deliberately invalid canary
159- request, runs the Python tests, and then fails if the report is missing, lacks the
160- canary, or contains any other violation. It writes ` wiretap.log ` and
161- ` wiretap-report.json ` . The Python tests add the ` coverage.json ` case inventory,
162- which lists operations without generated code under ` missing ` (` check:endpoints `
163- reports them as failures). All three go to ` validation-artifacts/ ` (override with
164- ` VALIDATION_ARTIFACTS ` ). CI uploads these diagnostics.
146+ ` generator/scripts/wiretap.sh ` starts Wiretap, sends an invalid probe request to
147+ verify validation is active, runs the Python tests, and fails if the report is
148+ missing or contains any other violation. It writes ` wiretap.log ` ,
149+ ` wiretap-report.json ` , and ` coverage.json ` to ` validation-artifacts/ ` (override
150+ with ` VALIDATION_ARTIFACTS ` ).
165151
166- ### Task names across SDK repositories
152+ ### Shared scripts across SDK repositories
167153
168- The task names, their inputs, and their exit semantics are the portable interface :
154+ The task names are shared across the Python, Go, and PHP SDK repositories :
169155` setup ` , ` lint ` , ` generate ` , ` test:tools ` , ` test:preprocess ` , ` test:unit ` ,
170156` check:generated ` , ` check:endpoints ` , ` test:contract ` , ` check ` , ` findings ` ,
171- ` build ` , ` spec:download ` , ` regenerate ` , ` examples ` , and ` version:set ` . Go and PHP
172- SDK repositories can use the same names. Only the ` run ` bodies are
173- language-specific.
157+ ` build ` , ` spec:download ` , ` regenerate ` , ` examples ` , and ` version:set ` . Only the
158+ ` run ` commands are language-specific.
174159
175160Scripts with the header line ` Copied unchanged into each UpCloud SDK repository `
176161don't depend on the SDK language. They need only ` bash ` , ` git ` , ` curl ` , ` tar ` , and
0 commit comments