Skip to content

Feature: Packaging check should detect cargo-dist (axodotdev) Rust release workflows #5145

Description

@SebTardif

Is your feature request related to a problem? Please describe.

The Packaging check reports "packaging workflow not detected" (-1) for many Rust repositories that publish multi-platform binaries (and often crates) via cargo-dist / the dist CLI in GitHub Actions. That is a false negative for a mainstream Rust packaging layout.

Scorecard already has a Rust matcher:

// checks/fileparser/github_workflow.go (IsPackagingWorkflow)
{
  // Rust packages. https://doc.rust-lang.org/cargo/reference/publishing.html
  Steps: []*JobMatcherStep{
    {
      Run: "cargo.*publish",
    },
  },
  LogText: "candidate rust publishing workflow using cargo",
},

cargo-dist workflows typically do not put a bare cargo publish step in the same top-level workflow that builds and attaches release artifacts. They use dist plan / dist build (and sometimes a separate reusable workflow for crates.io).

Concrete example

Repo: https://github.com/patchloom/patchloom
Workflow: .github/workflows/release.yml (cargo-dist plan/build + GitHub Releases + Homebrew/Scoop/npm installers + crates publish)

Public Scorecard API historically reported Packaging -1 / "packaging workflow not detected" for this project even while:

  • Multi-arch binaries are built with dist plan / dist build and uploaded to GitHub Releases
  • crates.io publish runs via cargo publish --locked --package patchloom in a reusable workflow (.github/workflows/publish-crates.yml, on: workflow_call only)
  • Homebrew formula / Scoop / npm installer packages are published from the same release pipeline

Related project note: https://github.com/patchloom/patchloom/blob/main/SECURITY.md (section "OpenSSF Scorecard notes") documents Packaging as a known cargo-dist false negative.

Why current matchers miss cargo-dist

  1. No matcher for cargo-dist / dist CLI.
    There is no JobMatcher for:

    • dist plan / dist build / dist publish (or cargo dist ...)
    • install/use of axodotdev cargo-dist binaries
    • common cargo-dist-generated workflow job shapes
  2. cargo publish in workflow_call-only reusable workflows often never credits Packaging.
    In checks/raw/github/packaging.go, after a workflow matches a packaging pattern, Scorecard requires:

    runs, err := c.RepoClient.ListSuccessfulWorkflowRuns(filepath.Base(fp))
    // ...
    if len(runs) > 0 { /* success */ }
    // else: "GitHub publishing workflow not used in runs: ..."

    For patchloom:

    Workflow file Pattern match Successful runs (API)
    release.yml cargo-dist dist plan/dist build (no matcher today); also may match npm if present Many
    publish-crates.yml cargo publish matches 0 (on: workflow_call only; runs are attributed to the caller, not this file)

    So pure "cargo-dist + reusable cargo publish" layouts can still fail Packaging even when crates and binaries are published on every release.

Observed behavior (live recheck)

Local scorecard --checks=Packaging on 2026-07-27 against github.com/patchloom/patchloom currently scores 10 because release.yml also has an npm publish job that matches the existing npm matcher (actions/setup-node + registry-url: https://registry.npmjs.org + npm.*publish) around job publish-npm (~line 706).

That does not mean cargo-dist is detected. A Rust-only cargo-dist project without npm (very common) still gets Packaging -1. Relying on npm as the only packaging signal for a Rust binary/crates release pipeline is incorrect.

Describe the solution you'd like

  1. Primary: add cargo-dist packaging matchers in IsPackagingWorkflow (same family as goreleaser / cargo publish), for example:

    • Run regex covering dist plan, dist build, dist publish (and optionally cargo dist ...)
    • Log text like: candidate rust publishing workflow using cargo-dist
    • Unit tests with fixture YAML modeled on cargo-dist-generated release.yml jobs
  2. Secondary (related correctness): reusable workflow_call publish jobs
    When a packaging pattern matches a workflow_call-only file with no standalone successful runs, either:

    • credit Packaging if a caller workflow with successful runs references that reusable workflow, or
    • document that cargo publish must appear in a workflow that has its own run history

    This is the same class of gap as other "matcher exists but detector never sees reality" Packaging bugs (e.g. ko dual-setup issue BUG: Packaging check's ko matcher requires BOTH setup-ko spellings in one job, so ko publishing is never detected #5133, goreleaser fork Feature: Packaging check should detect step-security/goreleaser-action (maintained fork of goreleaser/goreleaser-action) #5131, changesets Feature: Support changesets for the Packaging check #5096).

  3. Docs: mention cargo-dist under Packaging in docs/checks.md / beginner docs once matchers land.

Default remains non-breaking

Adding matchers only expands detection; repos already scoring 10 stay 10.

Alternatives considered

  • Project-side workaround: keep a dummy cargo publish step in a workflow that has standalone successful runs — fragile and dishonest packaging signal.
  • Depend only on npm matcher: wrong for Rust-only cargo-dist projects.
  • Ignore Packaging −1 forever: fine for local SECURITY.md notes, but leaves a systemic false negative for a large Rust ecosystem segment.

Additional context

Happy to open a PR adding the cargo-dist JobMatcher + fixtures if maintainers agree on the regex / step shape.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions