Skip to content

fix(ci): anchor native-change detection to package.json's version, not the latest tag#2128

Merged
carlos-alm merged 2 commits into
mainfrom
fix/ci-detect-native-changes-stale-tag
Jul 20, 2026
Merged

fix(ci): anchor native-change detection to package.json's version, not the latest tag#2128
carlos-alm merged 2 commits into
mainfrom
fix/ci-detect-native-changes-stale-tag

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Problem

All 8 currently-open dependabot PRs (#2119-#2126) are failing CI identically on Engine parity (all 3 OSes) and Test Node 22 (all 3 OSes), regardless of what each PR actually bumps — including PRs that only touch GitHub Actions versions (setup-go, setup-node, claude-code-action) with zero npm/Rust changes.

Root cause

  • The v3.16.0 release attempt (commit 2e0e94f, 2026-07-17) tagged the release, but its Pre-publish benchmark gate failed on a genuine build-time regression (filed as build-perf regression blocking v3.16.0: full build +42%, incremental rebuild +53-83% #2127), so publish/publish-dev never ran. package.json on main is still 3.15.0, and npm still serves 3.15.0 — nothing was actually published under the v3.16.0 tag.
  • detect-changes in ci.yml picks "the most recent vX.Y.Z git tag" as its proxy for "last published release." That's now the dangling v3.16.0 tag, which is current main HEAD — diffing HEAD against itself trivially finds zero native-relevant changes, so native-host-build gets skipped.
  • With native build skipped, test/parity jobs fall back to whatever npm install resolves for the platform packages — the actually published 3.15.0 binary, which is 56 native-relevant files (extractors, builder pipeline, db layer) behind HEAD.
  • Native (stale 3.15.0) vs. WASM (fresh HEAD) now disagree on real extraction behavior — exactly the parity failures seen on every open PR (TS/PHP AST-count mismatches, JS/TS callback-gating mismatches, C# edge/role mismatches).

Fix

Anchor detect-changes's diff base to the version package.json currently declares, instead of "the most recent semver-shaped tag." A tag can exist without a successful publish (exactly what happened here); package.json's version cannot drift from what's published without the release job itself changing it.

Verified against the current repo state: the fix now correctly resolves to v3.15.0 and detects the 56 native-relevant files changed since, which would set native_changed=true and restore the fresh-native-build path.

Not in scope here

The underlying build-perf regression that blocked the v3.16.0 release is tracked separately in #2127.

…t the latest tag

The v3.16.0 release attempt tagged the release but failed its pre-publish
benchmark gate (#2127) before publish ran, so package.json on main is still
3.15.0 and nothing was actually published under that tag. detect-changes
picked the dangling v3.16.0 tag as "last published release" and diffed it
against itself, finding no native-relevant changes and skipping the fresh
native build — causing every PR's Engine-parity/Test jobs to fall back to
the real published 3.15.0 binary, which is 56 native-relevant files behind
HEAD. Anchoring to package.json's declared version instead of "the most
recent semver-shaped tag" ties the check to what's actually checked out.
@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a CI regression where all open Dependabot PRs were failing parity and test jobs because detect-changes was diffing HEAD against a dangling v3.16.0 tag — a tag created by a GitHub Release that subsequently failed its pre-publish benchmark gate, leaving no matching npm publish. The fix replaces the "most recent semver tag" lookup with the version declared in package.json, which is the actual source of truth for what has been published.

  • detect-changes diff base: Changed from git tag --sort=-version:refname | head -1 to node -p "require('./package.json').version", constructing the tag name v$CURRENT_VERSION to use as the git diff base. The previous comment about grep-based parsing has already been addressed with this node -p approach.
  • Fallback guard: Preserved — if CURRENT_VERSION is empty or the constructed tag doesn't exist in git, the job still fails open to native_changed=true, triggering a full native build rather than silently skipping it.

Confidence Score: 5/5

Safe to merge — single focused change to a CI change-detection heuristic, with a correct fail-open fallback preserved

The change is minimal and precisely targeted: one variable assignment is replaced with node -p, and the fallback guard remains intact. No production code is touched.

No files require special attention

Important Files Changed

Filename Overview
.github/workflows/ci.yml Replaces the most-recent-semver-tag heuristic with package.json-anchored version lookup for the native-change diff base; logic and fallback guard are correct

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[detect-changes job runs] --> B["CURRENT_VERSION = node -p require('./package.json').version"]
    B --> C[LAST_TAG = v$CURRENT_VERSION]
    C --> D{CURRENT_VERSION empty OR\ngit cat-file -e LAST_TAG fails?}
    D -->|Yes| E["native_changed=true (fail open)"]
    D -->|No| F["git diff --name-only LAST_TAG HEAD\ngrep native-relevant paths"]
    F -->|Match found| G[native_changed=true]
    F -->|No match| H[native_changed=false]
    G --> I[native-host-build runs on all 3 OSes]
    E --> I
    H --> J[native-host-build skipped\nfalls back to published npm binary]
    I --> K[test / parity jobs use fresh native build]
    J --> L[test / parity jobs use published npm binary]

    style E fill:#f9c74f
    style G fill:#90be6d
    style H fill:#f94144
Loading
%%{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[detect-changes job runs] --> B["CURRENT_VERSION = node -p require('./package.json').version"]
    B --> C[LAST_TAG = v$CURRENT_VERSION]
    C --> D{CURRENT_VERSION empty OR\ngit cat-file -e LAST_TAG fails?}
    D -->|Yes| E["native_changed=true (fail open)"]
    D -->|No| F["git diff --name-only LAST_TAG HEAD\ngrep native-relevant paths"]
    F -->|Match found| G[native_changed=true]
    F -->|No match| H[native_changed=false]
    G --> I[native-host-build runs on all 3 OSes]
    E --> I
    H --> J[native-host-build skipped\nfalls back to published npm binary]
    I --> K[test / parity jobs use fresh native build]
    J --> L[test / parity jobs use published npm binary]

    style E fill:#f9c74f
    style G fill:#90be6d
    style H fill:#f94144
Loading

Reviews (2): Last reviewed commit: "fix: parse package.json version via node..." | Re-trigger Greptile

Comment thread .github/workflows/ci.yml Outdated
# matching publish, which made this job wrongly report "unchanged"
# against a fallback binary that was actually several releases
# stale (#2127).
CURRENT_VERSION=$(grep -m1 '"version"' package.json | sed -E 's/.*: *"([^"]*)".*/\1/')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Using grep -m1 '"version"' could theoretically match an embedded "version" key in a non-standard package.json section (e.g., inside an engines object or a pre-fields comment block) before the top-level field. node -p or jq would parse the JSON unambiguously and is guaranteed to be available on every GitHub-hosted runner.

Suggested change
CURRENT_VERSION=$(grep -m1 '"version"' package.json | sed -E 's/.*: *"([^"]*)".*/\1/')
CURRENT_VERSION=$(node -p "require('./package.json').version")

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — replaced the grep/sed extraction with node -p "require('./package.json').version" for unambiguous JSON parsing.

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm
carlos-alm merged commit 94c0af1 into main Jul 20, 2026
28 of 32 checks passed
@carlos-alm
carlos-alm deleted the fix/ci-detect-native-changes-stale-tag branch July 20, 2026 04:11
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant