Skip to content

Enforce the DL API contract in CI; drop the dead fields it caught - #179

Open
Alvin-Nahabwe wants to merge 1 commit into
feat/gradcam-uifrom
feat/api-contract-check
Open

Enforce the DL API contract in CI; drop the dead fields it caught#179
Alvin-Nahabwe wants to merge 1 commit into
feat/gradcam-uifrom
feat/api-contract-check

Conversation

@Alvin-Nahabwe

Copy link
Copy Markdown
Contributor

Stacked on #178 (gradcam-ui → #174#173). Diff collapses to just this change as the stack merges. Companion PR on no-code-transformers adds the contract generator + freshness check.

What

CI now proves the R client only sends fields the DL API accepts.

  • scripts/dl_api_contract.json — vendored contract (per endpoint, the exact accepted form fields), generated from the API's OpenAPI schema by no-code-transformers/scripts/dump_contract.py.
  • scripts/check_api_contract.py — stdlib-only checker that parses server/deep_learning.R, extracts every dl_request() %>% req_body_multipart() field, and fails if any isn't in the contract.
  • .github/workflows/contract.yml — runs it on every push/PR. (Separate file from CI: R parse check and secret scan #176's ci.yml to avoid a conflict; they can be merged later.)

This is the permanent gate for the drift class of bug that broke the platform (weight_decay vs weight_decay_hf, data_zip vs data_file, the dead ASR surface): it now fails the build, not production.

It immediately caught real drift

On first run the checker flagged 23 dead fields across all three training calls — num_proc, fp16, push_to_hub, hub_user_id, log_to_wandb, wandb_project, wandb_entity (+ OD's max_grad_norm, force_preprocess). The API silently ignores every one.

Resolution: removed them from the request bodies and removed the UI controls that fed them (three "Hub & Logging" panels, fp16/num_proc/max-grad-norm/force-preprocess inputs). A control whose value is silently discarded misleads users. This also answers the open question from #174 about the dead W&B/Hub panels — reinstate when the API actually implements those features. Net: −74/+7 in the DL module, meaningfully decluttering the training sidebar.

Verification

  • ✅ Checker passes on the cleaned client (8 requests validated)
  • ✅ Deliberately reintroducing the historical weight_decay bug → caught, exit 1 (regression-proof)
  • ✅ Both R files parse() clean; workflow YAML valid
  • ⚠️ Not visually verified — no bootable Shiny env here (app startup compiles OHDSI deps from source; see comment in CI: R parse check and secret scan #176). Please click through the three training panels before merge.

Keeping the contract fresh

The API repo commits dl_api_contract.json and CI there fails if it's stale. When the API changes its fields: regenerate there (python scripts/dump_contract.py > dl_api_contract.json), copy here, and this CI tells you if the client needs updating.

🤖 Generated with Claude Code

scripts/check_api_contract.py parses server/deep_learning.R and verifies
every field sent by dl_request()/req_body_multipart() pipelines exists in
the vendored API contract (scripts/dl_api_contract.json, generated by
no-code-transformers' scripts/dump_contract.py from the FastAPI OpenAPI
schema). A new CI workflow runs it on every push/PR, so the drift class
of bug that broke the platform (weight_decay vs weight_decay_hf, data_zip
vs data_file) now fails the build instead of production.

Running the checker immediately caught real drift: all three training
calls sent fields the API ignores (num_proc, fp16, push_to_hub,
hub_user_id, log_to_wandb, wandb_project, wandb_entity; OD also
max_grad_norm and force_preprocess - 23 fields total). Removed them from
the request bodies, and removed the UI controls that fed them (the three
Hub & Logging panels plus the fp16 / num_proc / max-grad-norm /
force-preprocess inputs): a control whose value is silently discarded is
worse than no control. This also resolves the open question on the ASR
PR about the dead W&B/Hub panels. Reinstate them if and when the API
implements those features.

Verified: checker passes on the cleaned client (8 requests), catches the
historical weight_decay bug when deliberately reintroduced (exit 1), and
both R files parse. The checker is stdlib-only Python.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant