fix(ci): skip native-host-build when no native-relevant paths changed - #2116
Conversation
native-host-build, test, parity, and pre-publish-benchmark all ran a full 3-OS Rust build (via native-host-build) unconditionally on every push/PR, even for pure-TS/docs changes that can't affect the native addon. Add a detect-changes job that diffs against the PR base (or previous push SHA) for crates/**, Cargo.toml/lock, and the native addon loader. When none of those changed, native-host-build is skipped entirely (fail-open: any detection failure still builds, so a broken detector can't hide a real Rust regression). test/parity/pre-publish-benchmark keep running on all 3 OSes regardless — they just fall back to the last-published native binary via npm install instead of a freshly PR-built one, preserving full cross-platform test/parity coverage while cutting the redundant rebuild.
Greptile SummaryThis PR adds a
Confidence Score: 5/5Safe to merge — the fail-open design ensures correctness in all edge cases, and no downstream job can silently use a stale binary when native code has changed. The logic is sound and the control flow is well-reasoned: detect-changes can only suppress native-host-build when it positively confirms no native paths changed since the last release tag, and every other outcome keeps the build running. The one limitation — that the skip only fires when no unreleased native commits exist — is intentional, documented, and correct from a safety standpoint. Only .github/workflows/ci.yml changed. The detect-changes script block (lines 76-90) is the section worth re-reading — specifically the tag-based diff logic and the comment explaining why a PR-base diff was rejected. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([push / pull_request]) --> DC[detect-changes\ngit diff LAST_TAG HEAD]
DC -->|script fails / no usable tag| NHB_RUN
DC -->|native_changed=true| NHB_RUN[native-host-build\n3-OS matrix]
DC -->|native_changed=false| NHB_SKIP[native-host-build\nSKIPPED]
NHB_RUN -->|success| DL[Download + install\nPR-built .node artifact]
NHB_SKIP -->|skipped| PUB[Use published npm\nbinary as fallback]
DL --> TEST[test / parity / pre-publish-benchmark\nrun on all 3 OSes]
PUB --> TEST
NHB_RUN -->|failure| SKIP_DOWN[test / parity / benchmark\nSKIPPED via failure guard]
TEST --> CP[ci-pipeline\nfail on any failure/cancelled]
SKIP_DOWN --> CP
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A([push / pull_request]) --> DC[detect-changes\ngit diff LAST_TAG HEAD]
DC -->|script fails / no usable tag| NHB_RUN
DC -->|native_changed=true| NHB_RUN[native-host-build\n3-OS matrix]
DC -->|native_changed=false| NHB_SKIP[native-host-build\nSKIPPED]
NHB_RUN -->|success| DL[Download + install\nPR-built .node artifact]
NHB_SKIP -->|skipped| PUB[Use published npm\nbinary as fallback]
DL --> TEST[test / parity / pre-publish-benchmark\nrun on all 3 OSes]
PUB --> TEST
NHB_RUN -->|failure| SKIP_DOWN[test / parity / benchmark\nSKIPPED via failure guard]
TEST --> CP[ci-pipeline\nfail on any failure/cancelled]
SKIP_DOWN --> CP
Reviews (2): Last reviewed commit: "fix(ci): diff native-relevant changes ag..." | Re-trigger Greptile |
native-host-build was skipping based on a diff against the PR base SHA (or previous push SHA), which only answers whether *this* change touched native code. It says nothing about whether the published npm binary that test/parity/pre-publish-benchmark fall back to has already drifted from HEAD. That binary is pinned to the last workflow_dispatch release and only gets rebuilt on demand — native-relevant commits routinely land on main between releases (62 since v3.15.0 at time of writing) without republishing. Diff against the last release tag instead, so native-host-build correctly reruns whenever the fallback binary would be stale, not just when the current PR/push touched crates/.
|
Thanks for the review — confirming the fail-open design and the tag-based diff are intentional, as noted. CI on 485dd63 now shows |
Summary
Why
Part of the broader CI/CD cost-reduction effort (#2108). This is the biggest single lever in that effort — most day-to-day PRs in this repo don't touch `crates/**`, so they were paying for a 6-leg macOS/Windows/Linux native rebuild (plus `cargo test` on each) for no reason. 880 CI runs in the last 30 days were all paying this cost unconditionally.
Closes #2111
Test plan