ci(solidity): run contracts CI on stacked PRs, and filter it by path - #4217
ci(solidity): run contracts CI on stacked PRs, and filter it by path#4217mswilkison wants to merge 1 commit into
Conversation
Both contracts workflows only triggered on `pull_request` targeting `main`, so a PR based on another branch got no solidity CI at all. Every PR in a stack is therefore unverified until the moment it is retargeted, which is the moment it merges -- the least useful time to find out. Opening the trigger alone would run both suites on every PR to the repo, including client-only Go changes, because `contracts-detect-changes` was a stub that echoed `path-filter=true` unconditionally. Worse, nothing consumed the output: none of the four jobs had an `if:` referencing it, so the filter has been decorative for as long as it has existed. So this does three things together, since any one alone is wrong: - drops the `branches: [main]` restriction, - replaces the stub with a real `dorny/paths-filter@v2` scoped to the package the workflow builds, matching the two contracts-*-docs workflows and client.yml, - adds the `if:` that actually consumes the result, in the form client.yml already uses, so `workflow_dispatch` runs continue to be unconditional. Filtering per package is safe: `ecdsa` depends on `@keep-network/random-beacon` through the npm `development` tag, not the local sources, so a random-beacon-only change cannot alter an ecdsa build. Deployment jobs are untouched. They gate on `github.event_name == 'workflow_dispatch'` and need `contracts-build-and-test`, which still runs unconditionally for that event. This PR edits both workflow files, so it exercises both filters. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe ECDSA and random-beacon contract workflows now run for pull requests targeting any branch, detect relevant file changes with ChangesContract workflow filtering
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.github/workflows/contracts-ecdsa.yml (1)
38-39: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winRemove the unnecessary checkout from both PR detector jobs.
dorny/paths-filtercan use the pull-request API directly; explicitly grantpull-requests: read, and disable credential persistence on any checkout that remains.
.github/workflows/contracts-ecdsa.yml#L38-L39: remove or harden the detector checkout..github/workflows/contracts-random-beacon.yml#L38-L39: remove or harden the detector checkout.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/contracts-ecdsa.yml around lines 38 - 39, Remove the conditional detector checkout from the PR detector jobs in .github/workflows/contracts-ecdsa.yml lines 38-39 and .github/workflows/contracts-random-beacon.yml lines 38-39, relying on dorny/paths-filter’s pull-request API access instead. Explicitly grant pull-requests: read permission in both jobs; if either checkout remains, set credential persistence to false.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/contracts-ecdsa.yml:
- Line 40: Update the dorny/paths-filter action in
.github/workflows/contracts-ecdsa.yml at line 40 and
.github/workflows/contracts-random-beacon.yml at line 40 from the legacy v2
Node16 release to a current Node20+/Node24 release, and pin each action
reference immutably to its commit SHA rather than using a mutable version tag.
---
Nitpick comments:
In @.github/workflows/contracts-ecdsa.yml:
- Around line 38-39: Remove the conditional detector checkout from the PR
detector jobs in .github/workflows/contracts-ecdsa.yml lines 38-39 and
.github/workflows/contracts-random-beacon.yml lines 38-39, relying on
dorny/paths-filter’s pull-request API access instead. Explicitly grant
pull-requests: read permission in both jobs; if either checkout remains, set
credential persistence to false.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7be31235-2508-4225-9703-0e7719469314
📒 Files selected for processing (2)
.github/workflows/contracts-ecdsa.yml.github/workflows/contracts-random-beacon.yml
| run: echo "path-filter=true" >> $GITHUB_OUTPUT | ||
| - uses: actions/checkout@v3 | ||
| if: github.event_name == 'pull_request' | ||
| - uses: dorny/paths-filter@v2 |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Tracked workflow files matching dorny/paths-filter:"
for f in $(git ls-files '.github/workflows/*.yml' '.github/workflows/*.yaml'); do
if grep -q 'dorny/paths-filter' "$f"; then
echo "### $f"
grep -n 'dorny/paths-filter' "$f"
fi
done
echo
echo "Relevant dorny/paths-filter blocks:"
for f in .github/workflows/contracts-ecdsa.yml .github/workflows/contracts-random-beacon.yml; do
if [ -f "$f" ]; then
echo "### $f"
nl -ba "$f" | sed -n '34,46p'
else
echo "missing $f"
fi
done
echo
echo "Check whether refs exist locally or via public repo metadata:"
if command -v gh >/dev/null 2>&1; then
for ref in dorny/paths-filter:v2 dorny/paths-filter:v3; do
echo "ref $ref"
gh api repos/dorny/paths-filter/git/refs/tags/${ref#*:} --jq '{ref, object_type: .object.type, object_sha: .object.sha}' || true
sha=${ref#*:}
if [ "$sha" = "$ref" ]; then
# not a tag with tag prefix ok
true
fi
done
else
echo "gh command not available"
fi
echo
echo "Public release/tag availability from GitHub (lightweight probe):"
curl -fsSL -o /tmp/paths-tags.json "https://api.github.com/repos/dorny/paths-filter/tags" && jq '.[0:10] | map({name, commit_sha: .commit.sha})' /tmp/paths-tags.json || trueRepository: threshold-network/keep-core
Length of output: 798
🌐 Web query:
dorny paths-filter GitHub release v2 latest
💡 Result:
The latest version of the dorny/paths-filter GitHub action as of July 27, 2026, is v4.0.2 [1]. The project has evolved significantly beyond version 2 [2][3]. Version 4 represents a major update that includes support for Node 24 and contains breaking changes compared to previous versions [4][5][6]. Users are encouraged to use the latest release (v4.x) for current projects [4]. Version 2 is now considered a legacy major version [2][3].
Citations:
- 1: https://github.com/dorny/paths-filter/releases/tag/v4.0.2
- 2: https://github.com/dorny/paths-filter/blob/HEAD/CHANGELOG.md
- 3: https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md
- 4: https://github.com/dorny/paths-filter
- 5: https://github.com/marketplace/actions/paths-changes-filter
- 6: https://github.com/dorny/paths-filter/releases/tag/v4.0.0
🌐 Web query:
dorny/paths-filter v3 v2 Node version action.yml
💡 Result:
The dorny/paths-filter GitHub Action uses different Node.js runtimes depending on the major version selected in the action.yml configuration [1][2]. - Version v4.x (current): Uses node24 [3][4][2]. This transition was implemented in v4.0.0 to support the GitHub Actions migration to Node 24 [3][4]. - Version v3.x: Uses node20 [5][6][2]. This was the standard for v3.x releases [5][6]. - Version v2.x: Uses node16 [5]. This is the legacy runtime for v2.x [5]. You can verify the specific runtime used by an installed version by inspecting the runs section in the action.yml file within the respective release tag or branch [2]. The update from node20 to node24 in v4.0.0 was a non-functional change intended to maintain compatibility with GitHub's runner environment deprecation schedule [4].
Citations:
- 1: https://github.com/dorny/paths-filter/releases
- 2: dorny/paths-filter@ce10459
- 3: https://github.com/dorny/paths-filter/releases/tag/v4.0.0
- 4: feat: update action runtime to node24 dorny/paths-filter#294
- 5: Node.js 16 actions are deprecated dorny/paths-filter#214
- 6: https://github.com/dorny/paths-filter/blob/HEAD/CHANGELOG.md
🌐 Web query:
GitHub Actions JavaScript v1/v2 node16 deprecation date
💡 Result:
Node.js 16 reached its end of life within GitHub Actions on November 12, 2024 [1]. Following the end of Node.js 16 support, GitHub Actions removed Node.js 16 from the runner environment, meaning actions configured to run on Node 16 (often associated with older v1 or v2 versions of GitHub Actions) ceased to function correctly on that date [1]. To resolve issues related to this deprecation, users must update their workflow definitions to use newer versions of actions (typically v3 or v4+) that are configured to run on newer Node.js runtimes (such as Node 20 or Node 24) [2][1][3]. While GitHub previously provided an environment variable (ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true) as a temporary opt-out to allow continued use of Node 16 during the transition period, that option is no longer valid following the November 2024 cutoff [1][4]. For context, GitHub has since moved on to deprecating Node.js 20, which is scheduled to reach its end of life on GitHub Actions runners on June 16, 2026, with a transition to Node 24 [2].
Citations:
- 1: https://github.blog/changelog/2024-09-25-end-of-life-for-actions-node16/
- 2: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
- 3: ci: update deprecated GitHub Actions to v4 bytenode/bytenode#260
- 4: https://github.blog/changelog/2024-05-17-updated-dates-for-actions-runner-using-node20-instead-of-node16-by-default/
🌐 Web query:
dorny paths-filter Node 20 Node 24 support v4 action.yml master
💡 Result:
As of July 27, 2026, the dorny/paths-filter action supports Node 24, which was introduced in version 4.0.0 [1]. The action was updated to use node24 in its action.yml file to maintain compatibility with GitHub Actions runners [2][3]. This change was part of a major version bump to v4.0.0 on March 12, 2026, which replaced the previous node20 runtime [1][2][3]. Users are encouraged to use version 4.0.0 or higher to avoid deprecation warnings and ensure compatibility with GitHub's updated environment [4][5]. You can verify this in the repository's action.yml file, which specifies using: 'node24' [3].
Citations:
- 1: https://github.com/dorny/paths-filter/releases/tag/v4.0.0
- 2: feat: update action runtime to node24 dorny/paths-filter#294
- 3: dorny/paths-filter@ce10459
- 4: Upgrade from Node.js 20 to Node.js 24 dorny/paths-filter#296
- 5: Node20 is deprecated, please update to Node24 to continue to support GitHub Actions dorny/paths-filter#286
Update dorny/paths-filter to a current Node20+/Node24 release.
dorny/paths-filter@v2 is a legacy node16 action; v3 uses Node20 and v4 is Node24. Pin current releases immutably instead of moving tags.
.github/workflows/contracts-ecdsa.yml.github/workflows/contracts-random-beacon.yml
🧰 Tools
🪛 actionlint (1.7.12)
[error] 40-40: the runner of "dorny/paths-filter@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
📍 Affects 2 files
.github/workflows/contracts-ecdsa.yml#L40-L40(this comment).github/workflows/contracts-random-beacon.yml#L40-L40
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/contracts-ecdsa.yml at line 40, Update the
dorny/paths-filter action in .github/workflows/contracts-ecdsa.yml at line 40
and .github/workflows/contracts-random-beacon.yml at line 40 from the legacy v2
Node16 release to a current Node20+/Node24 release, and pin each action
reference immutably to its commit SHA rather than using a mutable version tag.
Source: Linters/SAST tools
Both contracts workflows only trigger on
pull_requesttargetingmain:So a PR based on any other branch gets no solidity CI at all. That is currently true of the entire in-flight stack — #4203, #4206, #4207 and #4208 have not run a single contracts job between them. #4207 adds a
tsc --noEmitgate tocontracts-lint; that gate has never executed in CI.Each PR only gets verified when it is retargeted to
main, which is the moment it merges — the least useful time to find out.Why this is three changes and not one
Opening the trigger on its own is wrong.
contracts-detect-changeswas a stub:Unconditionally true, so both suites would then run on every PR to the repo, including client-only Go changes. And it turns out nothing consumed the output — none of the four jobs carried an
if:referencing it, so the filter has been decorative for as long as it has existed. Wiring a real filter without adding those conditions would have changed nothing at all.So:
branches: [main]restriction.dorny/paths-filter@v2, scoped to the package the workflow builds — matchingcontracts-ecdsa-docs.yml,contracts-random-beacon-docs.ymlandclient.yml, which all already do this.if:that consumes the result, in the exact formclient.ymluses:The
github.event_name != 'pull_request'half keepsworkflow_dispatchruns unconditional, since the filter step is skipped for those and the output would be empty.Two things checked rather than assumed
Filtering per package is safe.
ecdsadepends on@keep-network/random-beaconthrough the npmdevelopmentdist-tag, not the local sources, so a random-beacon-only change cannot affect an ecdsa build.Deployment jobs are untouched.
contracts-deployment-testnetandcontracts-dapp-development-deployment-testnetgate ongithub.event_name == 'workflow_dispatch'and needcontracts-build-and-test, which still runs unconditionally for that event.Verification
Both files parse (
js-yaml),pull_requestresolves to the bare all-branches form, all four jobs in each workflow are gated, andcontracts-detect-changesnow runsactions/checkout+dorny/paths-filter.Beyond that, this PR is its own test case: it edits both workflow files, and both are named in their own filters, so both suites should run here. If they do, the trigger and the filter are both correct.
Summary by CodeRabbit