Skip to content

Ensure cargo-binstall before coverage tool installs#296

Merged
leynos merged 9 commits into
mainfrom
fix/generate-coverage-binstall-order
Jul 4, 2026
Merged

Ensure cargo-binstall before coverage tool installs#296
leynos merged 9 commits into
mainfrom
fix/generate-coverage-binstall-order

Conversation

@leynos

@leynos leynos commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

This branch ensures the generate-coverage action installs and verifies cargo-binstall before it installs Rust coverage tools. It prevents fresh Linux and Windows runners from failing when cargo-llvm-cov invokes cargo binstall, while still reusing the binary that setup-rust normally provides when that binary matches the pinned version.

A follow-up review finding was valid: the first branch version reused any pre-existing cargo-binstall without checking its version. This branch now verifies the existing binary with the same grep -qF version-match contract used after installation and falls through to the pinned installer when the version is wrong.

No linked issue or execplan was identified for this regression fix.

Review walkthrough

Validation

  • make check-fmt: passed.
  • make typecheck: passed.
  • make lint: passed.
  • make test: 936 passed, 14 skipped.
  • Focused shell-step regression run: 11 passed, 142 deselected.
  • git diff --check: passed.

Notes

The documentation-only review warning was skipped. The pinned cargo-binstall version and checksum were already documented for the repository's setup-rust installation path, and this branch keeps the change minimal to the generate-coverage fallback ordering and verification contract.

@sourcery-ai sourcery-ai Bot left a comment

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.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 42 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3fc2b001-1875-405b-a6a1-9003d6faa233

📥 Commits

Reviewing files that changed from the base of the PR and between 26ebcca and cd32841.

📒 Files selected for processing (8)
  • .github/actions/generate-coverage/CHANGELOG.md
  • .github/actions/generate-coverage/README.md
  • .github/actions/generate-coverage/action.yml
  • .github/actions/generate-coverage/tests/test_scripts.py
  • .github/actions/linux-packages/README.md
  • .github/actions/macos-package/README.md
  • AGENTS.md
  • docs/generate-coverage-design.md

Walkthrough

Add an idempotent cargo-binstall install and verification step to generate-coverage, extend its tests for step wiring and installer outcomes, and reformat repository Markdown docs, guides, execplans, lint config, and top-level docs.

Changes

Generate-coverage cargo-binstall flow

Layer / File(s) Summary
Action step and verification
.github/actions/generate-coverage/action.yml
Adds an early “Ensure cargo-binstall” step for Rust and mixed projects, reuses an existing binary when the pinned version matches, exports the Cargo bin directory, and verifies the installed version before running cargo-llvm-cov.
Workflow contract and shell tests
.github/actions/generate-coverage/tests/test_scripts.py
Adds helpers to load and select workflow steps, extracts and runs the ensure script in an isolated environment, builds fake installers and existing binaries, and verifies step order, condition scope, reuse, reinstall, checksum, PATH export, and failure paths.
Feature docs and design notes
.github/actions/generate-coverage/README.md, .github/actions/generate-coverage/CHANGELOG.md, docs/generate-coverage-design.md, docs/developers-guide.md, .github/actions/setup-rust/README.md
Adds and reflows cargo-binstall pinning guidance, version checks, and PATH-handling notes in the action docs and supporting design/developer documentation.

Repository markdown, lint, and documentation reformatting

Layer / File(s) Summary
Lint config and top-level repo docs
.markdownlint-cli2.jsonc, Makefile, AGENTS.md, .gitignore, README.md
Adjusts Markdown lint config, switches the Markdown lint target to markdownlint-cli2, updates repo guidance tables, adds the Memtrace ignore rule, and reformats the top-level README workflow tables.
Action READMEs and changelogs
.github/actions/*/README.md, .github/actions/*/CHANGELOG.md, .github/actions/DEVELOPMENT.md
Reflows and re-tables the action documentation, changelogs, and development notes without changing the described inputs, outputs, notes, or release text.
Guides, execplans, and project docs
docs/**/*.md, rust-toy-app/README.md
Reformats ADRs, developer guides, design notes, execplans, workflow docs, and the toy app README with line wrapping and table layout changes only.

Possibly related PRs

  • leynos/shared-actions#231: Also changes the generate-coverage cargo-binstall provisioning path and nearby Rust coverage wiring.
  • leynos/rstest-bdd#482: Touches the same use-cargo-nextest/Rust coverage workflow area referenced by the new ensure-step condition.

Suggested reviewers: codescene-delta-analysis

Poem

🦀 A binstall step now wakes at dawn,
Checks its version, then moves along.
PATH is set, the tests all sing,
Markdown files get a tidy spring.
One install, one verify, then on we go —
A neat little PR, with a polished glow ✨

🚥 Pre-merge checks | ✅ 19 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
User-Facing Documentation ⚠️ Warning FAIL: No docs/users-guide.md exists, and the generate-coverage README does not mention the new cargo-binstall pin/verification flow. Add user-facing coverage for the new install/verify behaviour in docs/users-guide.md (or the repo’s equivalent user guide) and signpost the workflow change there.
✅ Passed checks (19 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarises the main change: provisioning cargo-binstall before Rust coverage tooling is installed.
Description check ✅ Passed The description matches the PR and explains the install-order fix, verification path, and validation results.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Testing (Overall) ✅ Passed The new shell-step tests execute the real action script with fake binaries and cover fast/slow paths, version mismatch, env export, checksum failure, and step ordering.
Developer Documentation ✅ Passed PASS: the developer guide and design notes document the cargo-binstall pinning change, the design roadmap is fully checked off, and no dedicated execplan exists for this fix.
Module-Level Documentation ✅ Passed PASS: the only changed Python module, .github/actions/generate-coverage/tests/test_scripts.py, has a clear top-level docstring covering purpose and its relation to helper scripts.
Testing (Unit And Behavioural) ✅ Passed PASS: The suite runs the generated bash step under fake binaries, covering fast path, mismatch reinstall, checksum failure, and post-install verification at the action boundary.
Testing (Property / Proof) ✅ Passed No broad input/state invariant was introduced; the new fast/slow-path shell checks are finite, and example-based behavioural tests are sufficient here.
Testing (Compile-Time / Ui) ✅ Passed PASS: No compile-time code changed, so trybuild is not applicable; the new generate-coverage tests are behavioural, and the suite already snapshots redacted GITHUB_OUTPUT for text output.
Unit Architecture ✅ Passed PASS: Ensure cargo-binstall is a single boundary command, and tests exercise it via real shell execution with fake binaries, covering reuse, reinstall, and checksum/version failures.
Domain Architecture ✅ Passed PASS: The PR only changes a GitHub Action, tests, and docs; no domain model, repository, or business logic is introduced or coupled to infrastructure.
Observability ✅ Passed PASS: the new step logs fast-path reuse, version mismatch, checksum/download failures, and post-install verification, with tests asserting each path.
Security And Privacy ✅ Passed No secrets, credentials, auth/permission changes, or unsafe input handling appear; the new shell step uses pinned constants and checksum verification, and tests use fake binaries only.
Performance And Resource Use ✅ Passed The new step adds one O(1) version probe and skips the installer on cache hits; no loops, unbounded growth, or repeated hot-path I/O were introduced.
Concurrency And State ✅ Passed PASS: The change is strictly sequential shell-step logic; state stays local to the step, PATH export is one-way, and tests cover reuse, reinstall, and checksum/version failures.
Architectural Complexity And Maintainability ✅ Passed PASS: The change adds a single explicit shell step and narrowly scoped test helpers; it avoids new layers, registries, or speculative abstractions, and documents the seam.
Rust Compiler Lint Integrity ✅ Passed No Rust source files changed; the diff only touches GitHub Action YAML, Python tests, and docs, so no Rust lint integrity regression is present.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/generate-coverage-binstall-order

Comment @coderabbitai help to get the list of available commands.

@pandalump pandalump marked this pull request as ready for review June 23, 2026 23:18
coderabbitai[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

codescene-access[bot]

This comment was marked as outdated.

@lodyai lodyai Bot force-pushed the fix/generate-coverage-binstall-order branch from a1564fd to c522b09 Compare July 4, 2026 00:21
codescene-access[bot]

This comment was marked as outdated.

leynos and others added 3 commits July 4, 2026 02:30
Install `cargo-binstall` before `cargo-llvm-cov` is installed so Rust
coverage runs can use `cargo binstall` on fresh runners. Keep the step
idempotent so `setup-rust` can continue to provide the binary when it is
already present.

Cover the action ordering and guard condition in the generate-coverage
manifest tests.
Require a pre-existing `cargo-binstall` to match the pinned version before
`generate-coverage` reuses it. Fall through to the pinned installer when the
binary is missing or has the wrong version.

Exercise the action shell step with fake commands so the fast path, mismatch
path, and post-install verification all assert runtime behaviour.
Excludes the Memtrace local database directory from version control.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

leynos and others added 2 commits July 4, 2026 02:31
- Replace git-aware markdownlint-check.sh wrapper with a direct
  markdownlint-cli2 invocation in the Makefile
- Remove workflow_scripts/markdownlint-check.sh
- Import .markdownlint-cli2.jsonc config from mapsplice (adds golden
  fixture ignore and enforces MD046 fenced code blocks)
- Run mdformat-all and markdownlint-cli2 --fix across all Markdown
  files, including .github/actions/ (previously skipped by fd)
- Convert indented code blocks to fenced throughout execplan docs
- Fix MD056 missing table cells in upload-codescene-coverage README
- Update developers-guide.md to reflect MDLINT → markdownlint-cli2
  and remove the now-removed MARKDOWNLINT_BASE variable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Record the new "Ensure cargo-binstall" step introduced in generate-coverage:

- Add an Unreleased CHANGELOG bullet for the pinned cargo-binstall install.
- Add a dated design decision to generate-coverage-design.md explaining why
  the action provisions its own pinned cargo-binstall and how both the reuse
  and install paths verify the version.
- Add a developers-guide section describing the idempotent step, its two
  verification paths, and the behavioural tests that exercise them.

Addresses the Developer Documentation review finding. The related "fast path
bypasses version verification" and "vacuous tests" findings were already
resolved by commit a5e8041 and are not re-litigated here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lodyai lodyai Bot force-pushed the fix/generate-coverage-binstall-order branch from 655f2fb to 26ebcca Compare July 4, 2026 00:53
codescene-access[bot]

This comment was marked as outdated.

@leynos

This comment was marked as resolved.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/actions/generate-coverage/action.yml (1)

135-163: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Export BINSTALL_VERSION before invoking the installer. The child bash only sees exported variables; without that, the installer falls back to latest and defeats the v1.16.6 pin. Mirror setup-rust here.

🤖 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/actions/generate-coverage/action.yml around lines 135 - 163, The
cargo-binstall install block is pinning BINSTALL_VERSION locally, but the child
bash installer cannot see it unless it is exported. Update the installer setup
in generate-coverage/action.yml so the variable is exported before calling bash
"$INSTALLER_PATH", matching the setup-rust pattern, and keep the existing
version-check and checksum flow intact.
🤖 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/actions/linux-packages/README.md:
- Around line 14-24: Update the surrounding prose in the Linux packages README
to use en-GB spelling by changing descriptive text from “license” to “licence”
while keeping the table field name “license” unchanged. Locate the affected copy
in the package options table and revise only the human-readable descriptions,
not the key names or schema terms.

In @.github/actions/macos-package/README.md:
- Around line 3-4: Update the prose in the macOS package action README to use
en-GB-oxendict British spelling, specifically changing surrounding descriptive
text from “license” to “licence” while keeping identifiers, option names, and
filenames like `license-file` and `LICENSE` unchanged. Review the referenced
descriptive sections in the README and apply the spelling consistently in the
affected narrative text without altering any code-style tokens or paths.

In `@AGENTS.md`:
- Around line 115-120: Update the tool-resolution table in AGENTS.md to match
the current Makefile behavior: change the MDLINT entry to reference
markdownlint-cli2 instead of markdownlint, and remove the MARKDOWNLINT_BASE row
entirely since no diff-base variable is consumed anymore. Keep the table wording
consistent with the other tool entries and use the existing variable names in
that section to locate the change.

In `@docs/developers-guide.md`:
- Around line 99-119: The Makefile tool-resolution table no longer matches the
documented contract because the MARKDOWNLINT_BASE entry was removed and MDLINT
is now described inconsistently. Update the Makefile resolution section to
restore the MARKDOWNLINT_BASE row and ensure the MDLINT description matches the
actual fallback order used by the Makefile’s tool resolution logic. Use the
existing “Makefile Tool Resolution” table and the MDLINT/MARKDOWNLINT_BASE
symbols as the source of truth, and keep the override example aligned with that
contract.

---

Outside diff comments:
In @.github/actions/generate-coverage/action.yml:
- Around line 135-163: The cargo-binstall install block is pinning
BINSTALL_VERSION locally, but the child bash installer cannot see it unless it
is exported. Update the installer setup in generate-coverage/action.yml so the
variable is exported before calling bash "$INSTALLER_PATH", matching the
setup-rust pattern, and keep the existing version-check and checksum flow
intact.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 452ae7d8-2961-457a-8714-c58b1d1d051a

📥 Commits

Reviewing files that changed from the base of the PR and between d0fd973 and 26ebcca.

📒 Files selected for processing (50)
  • .github/actions/DEVELOPMENT.md
  • .github/actions/determine-release-modes/README.md
  • .github/actions/ensure-cargo-version/README.md
  • .github/actions/export-cargo-metadata/CHANGELOG.md
  • .github/actions/export-cargo-metadata/README.md
  • .github/actions/generate-coverage/CHANGELOG.md
  • .github/actions/generate-coverage/README.md
  • .github/actions/generate-coverage/action.yml
  • .github/actions/generate-coverage/tests/test_scripts.py
  • .github/actions/linux-packages/README.md
  • .github/actions/macos-package/README.md
  • .github/actions/release-to-pypi-uv/README.md
  • .github/actions/rust-build-release/CHANGELOG.md
  • .github/actions/rust-build-release/README.md
  • .github/actions/setup-rust/README.md
  • .github/actions/stage-release-artefacts/CHANGELOG.md
  • .github/actions/stage-release-artefacts/README.md
  • .github/actions/upload-codescene-coverage/README.md
  • .github/actions/upload-release-assets/CHANGELOG.md
  • .github/actions/upload-release-assets/README.md
  • .github/actions/validate-linux-packages/README.md
  • .github/actions/windows-package/README.md
  • .gitignore
  • .markdownlint-cli2.jsonc
  • AGENTS.md
  • Makefile
  • README.md
  • docs/adr/0001-stable-manpage-path.md
  • docs/adr/0002-explicit-ps-module-name.md
  • docs/cmd-mox-users-guide.md
  • docs/dependabot-automerge-workflow.md
  • docs/developers-guide.md
  • docs/execplans/2-4-5-extend-architecture-enforcement-to-orchestration-code.md
  • docs/execplans/3-14-5-regression-coverage-for-conditional-action-dependency-manifests.md
  • docs/execplans/adopt-cargo-nextest-in-generate-coverage.md
  • docs/execplans/auto-merge-on-unstable.md
  • docs/execplans/binstall-metadata-audit.md
  • docs/execplans/cargo-manifests-input.md
  • docs/execplans/dependabot-auto-merge.md
  • docs/execplans/refactor-validate-packages-modules.md
  • docs/execplans/support-cranelift-codegen.md
  • docs/generate-coverage-design.md
  • docs/python-action-scripts.md
  • docs/python-native-command-mocking-design.md
  • docs/rust-build-release-pipeline.md
  • docs/scripting-standards.md
  • docs/syspath-hack-users-guide.md
  • docs/windows-gnullvm-build.md
  • rust-toy-app/README.md
  • workflow_scripts/markdownlint-check.sh
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/polythene (auto-detected)
💤 Files with no reviewable changes (1)
  • workflow_scripts/markdownlint-check.sh

Comment thread .github/actions/linux-packages/README.md Outdated
Comment thread .github/actions/macos-package/README.md Outdated
Comment thread AGENTS.md Outdated
Comment thread docs/developers-guide.md
Fix a real bug and clear valid review findings; skip stale/invalid ones.

- generate-coverage/action.yml: export BINSTALL_VERSION so the child installer
  shell inherits the pin. Without export the installer silently falls back to
  releases/latest, defeating the pin and tripping post-install verification.
- generate-coverage tests: add three behavioural regression tests that execute
  the extracted step body — the pinned version is exported to the installer,
  the Cargo bin dir is appended to GITHUB_PATH, and a bad installer checksum
  aborts before the installer runs. The fake installer now records the
  inherited BINSTALL_VERSION so the export is genuinely guarded (the test fails
  without the export).
- linux-packages / macos-package READMEs: use en-GB "licence" (noun) in prose,
  matching the repository convention; input keys, option names, and paths
  (`license`, `license-file`, `include-license-panel`, `LICENSE`) are unchanged.
- AGENTS.md: align the Makefile tool-resolution table with the current Makefile
  — MDLINT resolves to markdownlint-cli2, and the removed MARKDOWNLINT_BASE row
  and its override example are dropped.

Skipped: the request to restore MARKDOWNLINT_BASE in developers-guide.md (that
variable was deliberately removed from the Makefile; the doc already matches),
and creating docs/users-guide.md (the binstall flow is internal plumbing,
already covered by the action README and design notes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

.github/actions/generate-coverage/action.yml (1)

135-163: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Export BINSTALL_VERSION before invoking the installer. The child bash only sees exported variables; without that, the installer falls back to latest and defeats the v1.16.6 pin. Mirror setup-rust here.

🤖 Detailed instructions

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/actions/generate-coverage/action.yml around lines 135 - 163, The
cargo-binstall install block is pinning BINSTALL_VERSION locally, but the child
bash installer cannot see it unless it is exported. Update the installer setup
in generate-coverage/action.yml so the variable is exported before calling bash
"$INSTALLER_PATH", matching the setup-rust pattern, and keep the existing
version-check and checksum flow intact.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '100,200p' .github/actions/generate-coverage/action.yml

Length of output: 2056


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '100,200p' .github/actions/generate-coverage/action.yml

Length of output: 5383


@leynos, yes — resolved. The current head exports the variable:

export BINSTALL_VERSION="v1.16.6"

This line sits before the curl/bash "$INSTALLER_PATH" invocation, so the child installer shell now inherits it and honours the pin instead of falling back to latest. The inline comment above the export even states this explicitly ("Export so the child installer shell inherits it; the installer reads BINSTALL_VERSION from the environment to pick the pinned release and otherwise silently falls back to releases/latest"). No further action needed on this item.

Align the generate-coverage "Ensure cargo-binstall" step with setup-rust, which
main bumped to v1.19.1. The repository now uses a single cargo-binstall pin
across every action and test.

- action.yml: BINSTALL_VERSION v1.16.6 -> v1.19.1 and the installer-script
  BINSTALL_SHA256 to the matching validated digest.
- tests: update the binstall test doubles (existing/installed versions and the
  fake installer checksum) to v1.19.1.
- CHANGELOG and generate-coverage-design.md: reflect the pinned version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as resolved.

@leynos

leynos commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

Two generate-coverage fixes for the cargo-binstall install step.

- Cache the pinned cargo-binstall binary alongside cargo-llvm-cov and
  cargo-nextest so a cache hit no longer re-downloads and re-verifies the
  installer on every run. The step's version check still guards a stale cached
  binary, so this stays correct across pin bumps.
- Match the pinned version as a whole, space-delimited token instead of a
  `grep -qF` substring, so a look-alike such as 1.19.10 no longer satisfies a
  1.19.1 pin and skips the reinstall. Both the fast-path reuse check and the
  post-install verification use the shared `binstall_version_matches` helper,
  which handles the real bare `-V` output ("1.19.1") and the "<name> <version>"
  form alike. Add a regression test for a pre-existing 1.19.10 binary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

Note the pinned cargo-binstall install/verification flow in the user-facing
action README: the action provisions a specific cargo-binstall version
(reusing a cached build on an exact version match, otherwise installing from a
checksum-verified installer script) and verifies the resolved version before
running the coverage tooling.

Addresses the user-facing documentation review finding. A new docs/users-guide.md
is not added: the repository's *-users-guide.md docs are subsystem-specific, and
per-action user documentation lives in each action's README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@leynos

leynos commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

.github/actions/generate-coverage/action.yml (2)

108-120: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
Cache the pinned cargo-binstall binary too.
"Cache cargo artefacts" restores cargo-llvm-cov and cargo-nextest binaries but omits cargo-binstall, so every job re-downloads the installer script, re-verifies its checksum, and re-runs it on a cache hit for everything else. Add the binary to the cached path list to avoid the repeated network round-trip.

⚡ Proposed cache path addition
path: |
+          ~/.cargo/bin/cargo-binstall
           ~/.cargo/bin/cargo-llvm-cov
           ~/.cargo/bin/cargo-nextest
           ~/.cargo/registry
           ~/.cargo/git
           target
🤖 Detailed instructions

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/actions/generate-coverage/action.yml around lines 108 - 120, Add the
pinned cargo-binstall binary to the cache managed by the “Cache cargo artefacts”
step in generate-coverage action.yml. Update the actions/cache path list
alongside cargo-llvm-cov and cargo-nextest so the cache in the cache step
includes ~/.cargo/bin/cargo-binstall, keeping the existing cache key and
restore-keys unchanged.

138-148: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Match the full cargo-binstall version token

grep -qF accepts 1.19.10 when expecting 1.19.1, so a stale runner can skip the pinned reinstall. Use an exact token or anchored match in both version checks, and add a regression test for a pre-existing 1.19.10 binary.

🤖 Detailed instructions

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/actions/generate-coverage/action.yml around lines 138 - 148, The
cargo-binstall version check in the generate-coverage action is using a
substring match, so a preinstalled 1.19.10 can incorrectly satisfy the pinned
1.19.1 check. Update the version validation around the existing cargo-binstall
-V path to require an exact token or anchored match instead of grep -qF, and
make the reinstall decision in the same block rely on that exact comparison. Add
a regression test for the version-check logic using a pre-existing
cargo-binstall 1.19.10 binary to verify it does not bypass the pinned reinstall.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
gh pr view 296 --json headRefName,commits --jq '.headRefName'
git fetch origin pull/296/head:pr296 2>&1 | tail -3
git checkout pr296 2>&1 | tail -3
echo "---action.yml fast path---"
sed -n '90,175p' .github/actions/generate-coverage/action.yml
echo "---tests---"
rg -n "def test_generate_coverage_binstall" .github/actions/generate-coverage/tests/test_scripts.py
echo "---docs---"
rg -n "cargo-binstall" docs/developers-guide.md docs/generate-coverage-design.md | head -20
fd -i changelog.md

Length of output: 6937


@leynos, all six items are resolved on the current head. Detail below.

Check Status Evidence
Testing (Overall) ✅ Resolved Tests at Lines 3166–3278 (test_generate_coverage_binstall_fast_path_verifies_existing_version, _mismatch_installs_pinned_version, _rejects_longer_version_look_alike, _install_verifies_installed_version, _exports_pinned_version_to_installer, _appends_cargo_bin_to_github_path, _checksum_mismatch_aborts) extract the step's run body and execute it via real shell against faked cargo-binstall/curl/sha256sum/bash. They assert on exit codes, log output, and GITHUB_PATH mutation — not string presence.
Unit Architecture ✅ Resolved The fast path now runs existing_version="$(cargo-binstall -V)", checks it with binstall_version_matches, and only exits 0 on a match. A mismatch prints a warning and falls through to the slow path's reinstall-and-reverify logic. Both paths enforce the identical version-pinning contract; there's no asymmetric fallibility left.
Developer Documentation ✅ Mostly resolved docs/developers-guide.md Lines 160–216 hold a "generate-coverage cargo-binstall Pinning" section; docs/generate-coverage-design.md Lines 52–54 record the design decision. Open point: the repository still has no CHANGELOG.md at all — confirmed absent again on this head — so there's no file to add an "Unreleased" entry to.
Testing (Unit And Behavioural) ✅ Resolved Same seven tests above cover version-mismatch detection, idempotency, hash verification, and the exported-version contract via genuine shell execution.
Observability ✅ Resolved The fast path logs cargo-binstall already installed: $existing_version only after the version check succeeds, and logs the mismatch reason to stderr before falling through — both paths now surface version state.
Concurrency And State ✅ Resolved Version verification is unconditional and runs before any early exit; state transitions in both paths obey the same contract.

No code changes remain outstanding for these six items.

On the CHANGELOG.md point: don't treat it as a defect in this PR — introducing a changelog convention repository-wide is a separate decision for you as maintainer, not a gap in this fix. If you want it tracked, open an issue for adding a root CHANGELOG.md convention; say the word and I'll raise one.

ᕦ(ò_óˇ)ᕤ

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1,220p' .github/actions/generate-coverage/action.yml

Length of output: 9548


@leynos, both resolved on the current head.

Cache path (Lines 104–116): ~/.cargo/bin/cargo-binstall is now listed in the "Cache cargo artefacts" step alongside cargo-llvm-cov and cargo-nextest. A cache hit now skips the download, checksum verification, and installer run entirely (the fast path exits before any of that).

Version token matching (Lines ~138–148): The substring grep -qF approach is gone. Replace it in your head with:

binstall_version_matches() {
  case " $1 " in
    *" ${binstall_ver} "*) return 0 ;;
    *) return 1 ;;
  esac
}

Pad the candidate string with leading/trailing spaces and match " 1.19.1 " as a whole token, so 1.19.10 (which becomes " 1.19.10 ") does not satisfy a 1.19.1 pin. Both the fast path (existing_version) and the slow path (installed_version) call this same function, so the exact-match contract is enforced identically in both places.

One gap remains: I don't see a regression test that specifically exercises a pre-existing 1.19.10 binary to confirm it triggers reinstall. The logic is sound by inspection, but a test would lock in the anchoring behaviour against future edits. If you want that test added, here's a prompt for an agent to pick up:

In .github/actions/generate-coverage/tests/test_scripts.py, add a behavioural
test that fakes a pre-existing cargo-binstall binary reporting version
"1.19.10" (a superstring of the pinned "1.19.1") on the PATH, executes the
"Ensure cargo-binstall" step's run body via bash, and asserts that:
1. curl is invoked (i.e. the fast path did NOT exit early), proving the
   look-alike version was rejected by binstall_version_matches().
2. The mismatch warning is logged with the correct expected/found versions.
Follow the same fake-binary-on-PATH pattern already used by
test_generate_coverage_binstall_mismatch_installs_pinned_version.

✏️ Learnings added
Learnt from: leynos
URL: https://github.com/leynos/shared-actions/pull/296

Timestamp: 2026-07-04T08:32:56.513Z
Learning: In leynos/shared-actions, .github/actions/generate-coverage/action.yml's "Ensure cargo-binstall" step exposes a shell function `binstall_version_matches()` that wraps `cargo-binstall -V` output and the pinned version in single spaces, then matches `" ${binstall_ver} "` as a whole token via a case statement. This anchored matching replaced an earlier `grep -qF` substring check, which incorrectly allowed a look-alike version such as `1.19.10` to satisfy a `1.19.1` pin. Both the fast path (pre-existing binary check) and the slow path (post-install verification) call this same function to enforce identical version-pinning contracts.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@leynos leynos merged commit 1b2711c into main Jul 4, 2026
27 checks passed
@leynos leynos deleted the fix/generate-coverage-binstall-order branch July 4, 2026 08:37
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.

2 participants