Skip to content

CI: clippy_check uses archived actions-rs/clippy-check@v1 — same failure class that kept DataBucket red for months #174

Description

@pathscale

Summary

.github/workflows/rust.yml's clippy_check job uses actions-rs/clippy-check@v1 (plus actions-rs/toolchain@v1). Both actions have been archived and unmaintained since October 2023. The job is green today, but only by luck of token configuration: this is the exact setup that kept pathscale/DataBucket CI red on every push from April to July 2026 while its code was lint-clean the whole time.

Mechanism

actions-rs/clippy-check does not merely run clippy — after running it, it POSTs to the GitHub Checks API to create a Check Run with inline annotations. That API call requires the job token to have checks: write. When the token lacks it, the API returns 403 and the action fails the whole job with ##[error]Resource not accessible by integration — even when clippy found nothing. The lint result is irrelevant; the failure is the annotation upload.

Evidence from DataBucket (identical job definition):

  • Failing runs, every push, months apart: run 25128967124 (Apr), run 25129013462 (Apr), run 30222021476 (Jul) — all clippy_check: failure with Resource not accessible by integration, all with clippy itself clean (the build job passed, and running CI's exact command locally produced zero lints).
  • Fixed by replacing the action with a plain cargo invocation: pathscale/DataBucket@943b402 — CI green since.

Why WorkTable is currently green — and three concrete ways it flips red

This workflow has no permissions: block, so the job token inherits the repository/organization default workflow permissions, which are currently permissive enough to include checks: write. That is the only thing keeping the job green. Three realistic triggers, ranked:

1. Any pull request from a fork (reproducible today, no settings change needed).
The workflow triggers on pull_request. For PRs from forks, GitHub force-downgrades GITHUB_TOKEN to read-only regardless of repo/org defaults — checks: write is never granted. Reproduction:

gh repo fork pathscale/WorkTable --clone   # as any account without push access
cd WorkTable && git checkout -b test-ci && git commit --allow-empty -m "ci probe"
git push origin test-ci
gh pr create --repo pathscale/WorkTable --head <fork-owner>:test-ci --title "CI probe"

The clippy_check job on that PR will fail with Resource not accessible by integration while build passes. Practical consequence: the first outside contribution — e.g. a patch from Handy-caT's fork or anyone in the indexset orbit — arrives pre-stamped with a red X for reasons that have nothing to do with their code. (Recent PRs #170#173 were all same-repo branches, which is why this has not fired yet.)

2. Security hardening of the workflow.
Adding a least-privilege permissions: block — standard practice, recommended by GitHub's own hardening guide, and exactly what DataBucket's workflow had (contents: read, pull-requests: write) — turns every push red permanently. Whoever adds it will have no reason to suspect it breaks clippy.

3. Flipping the org/repo Actions default.
Settings → Actions → General → Workflow permissions → "Read repository contents and packages permissions" (GitHub's recommended default for new orgs) removes checks: write org-wide. This breaks the job without any commit to this repository, which makes the eventual failure maximally confusing to bisect.

Secondary rot, already visible in the logs: the archived actions run on deprecated Node runtimes ("target Node.js 20 but are being forced to run on Node.js 24"), and actions-rs/toolchain is equally archived — both are on borrowed time independent of the token issue.

Fix

Same as DataBucket: let the cargo exit code gate the job and drop the Checks-API dependency entirely. The inline annotations the action provided are barely a loss — the failure log shows the lints, and the job status is what gates merges.

  clippy_check:
    runs-on: ubicloud-standard-2
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: "true"
          add-job-id-key: "false"
      - name: Clippy (deny warnings)
        run: cargo clippy --all-targets --all-features -- -D warnings

(Also bumps actions/checkout v3 → v4 and drops the actions-rs/toolchain step — the runner's stable toolchain is what the build job already uses. If inline PR annotations are wanted later, the maintained pattern is cargo clippy --message-format=json piped to a problem-matcher, or giraffate/clippy-action — but the plain command is the boring, durable choice.)

One caveat when making the swap: the plain command actually enforces -D warnings, which the current job silently does not on the paths where it 403s before reporting. Run cargo clippy --all-targets --all-features -- -D warnings locally first (it was clean on the current tree as of the fix series) so the swap does not surface a backlog at an awkward time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions