ci: interface-sync guard for frontend Candid declarations#403
Draft
marc0olo wants to merge 1 commit into
Draft
Conversation
…r .did Part of #402. The frontend SDK bundles generated Candid declarations (idlFactory + types) that must track the canister .did files; nothing currently fails CI if a .did changes and the declarations aren't regenerated. This adds an interface-sync guard: - Pin the bindgen version in make_did_bindings.sh so regeneration is reproducible (an unpinned `npx` resolves to whatever is latest and produces spurious diffs on cosmetic bindgen changes). - Add a SKIP_EXTRACT_CANDID=1 mode that regenerates declarations from the committed .did without rebuilding it from Rust source, so the guard depends only on the pinned bindgen + committed .did (no wasm/extractor toolchain needed). - Add .github/workflows/interface-sync.yml: regenerate and fail on any diff in src/declarations. The Rust <-> Motoko backend contract is already enforced behaviorally (the Motoko canister wasm is run against the Rust canister's integration tests), so this guard focuses on the otherwise-unguarded frontend <-> canister seam. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — first of three PRs for #402 (DX: canister-integration helpers + interface-contract enforcement).
What
Adds a CI guard that fails if the frontend's generated Candid declarations (
idlFactory+ types underfrontend/ic_vetkeys/src/declarations) drift from the canister.didfiles.make_did_bindings.sh— an unpinnednpx @icp-sdk/bindgenresolves to whatever is latest and emits spurious diffs on cosmetic changes (confirmed: 0.3.0 → 0.4.0 adds doc-comments with no interface change).SKIP_EXTRACT_CANDID=1mode — regenerate declarations from the committed.didwithout rebuilding from Rust source, so the guard depends only on the pinned bindgen + committed.did(no wasm/candid-extractor toolchain, fast and reproducible)..github/workflows/interface-sync.yml— regenerate +git diff --exit-code.Why
The frontend SDK bundles a fixed
idlFactory; if a.didchanges and the declarations aren't regenerated, nothing currently catches it. This closes that seam.The Rust ↔ Motoko backend contract is already enforced behaviorally — the Motoko canister is compiled to wasm and the Rust canister's integration tests run against it (
backend/mo/canisters/*/Makefile,backend-motoko.yml). So this guard deliberately targets only the otherwise-unguarded frontend ↔ canister seam.Verification (local)
.didwith pinned bindgen yields no diff..didmakes the guard fail as intended; reverting restores green.Sequencing
First of three (recommended A → B → C):
moc 1.9.0compiles mixins and emits their endpoints into the Candid interface).Follow-up noted (not in this PR)
The committed
.didfiles are slightly stale vs. Rust source —make extract-candidnow emits domain doc-comments the committed artifacts predate (interface shape unchanged). Refreshing them (and optionally guarding source→.did) is left as a separate change to keep this guard reproducible and toolchain-light.🤖 Generated with Claude Code