Skip to content

fix(analyze): a spent GitHub quota at preflight skips the forge pass instead of failing the run - #341

Merged
0x73746F66 merged 1 commit into
mainfrom
fix/analyze-preflight-rate-limit
Nov 13, 2026
Merged

0x73746F66 merged 1 commit into
mainfrom
fix/analyze-preflight-rate-limit

Conversation

@0x73746F66

Copy link
Copy Markdown
Member

What

  • forge.Check now returns forge.ErrRateLimited when the /user or repository read fails with a rate-limit error. Before, it was reported through repoAccessError as "the GitHub token ... cannot read /".
  • analyze.Check treats ErrRateLimited like --no-forge. The forge pass is skipped, its metrics are reported as not measured with that reason, and the run continues.
  • IsRateLimit uses errors.As, so it also recognises wrapped rate-limit errors.
  • The analyze help text says a spent quota skips GitHub.

Why

The first push to main after #340 ran analyze with v4.24.30 (run 43453552319). The repository's installation quota was still spent from earlier runs. The preflight repository read got 403 API rate limit exceeded for installation, and analyze exited with "the GitHub token from GITHUB_TOKEN is valid (authenticated as repository-scoped token) but cannot read Vulnetix/cli". That is the wrong diagnosis, and it lost the whole report, including the git, file, dependency and trust metrics that do not need GitHub at all. #339 bounds what analyze spends. This PR makes analyze survive when other jobs have already spent the quota.

How verified

  • New tests:
    • TestCheck_ExhaustedQuotaIsNotAnAccessError: user token, with and without a repository.
    • TestCheck_RepositoryScopedTokenWithExhaustedQuota: the GITHUB_TOKEN path, where /user is a plain 403 and the repository read hits the limit.
    • TestIsRateLimit_Wrapped.
  • The existing access-error tests are unchanged and pass.
  • go test ./internal/analyze/... ./cmd/ pass. just lint (golangci-lint v2.14.0) reports 0 issues.

…instead of failing the run

When the job token's quota was already spent by other jobs, the preflight repository read got 403 'API rate limit exceeded for installation'. repoAccessError reported that as 'cannot read Vulnetix/cli', and analyze exited without a report. A rate-limit error at preflight is now forge.ErrRateLimited, and analyze.Check skips the forge pass: its metrics are not measured, and the git, file, dependency and trust metrics are still reported. IsRateLimit also matches wrapped errors.
@github-actions

Copy link
Copy Markdown
Contributor

Vulnetix config plan

Manager gitops:vulnetix/cli, prune off, plan hash a8bd984f1753c68b180298051dd9e2524ab644d2ebe9e4c7c811ff4126753b5f

Object Action Changes
~ QualityGate/default update (adopt) severity: null -> "high"

0 to create, 1 to update, 0 to delete, 0 unchanged

@0x73746F66
0x73746F66 merged commit 7612e34 into main Nov 13, 2026
31 of 34 checks passed
0x73746F66 added a commit that referenced this pull request Nov 13, 2026
… the repository's API quota (#342)

On the push that merged #341 the analyze preflight saw 4,913 of 5,000
requests left; by 16:08:18, three and a half minutes later, SCA's own SARIF
upload failed with "GitHub API rate limit exhausted", and the forge pass
found 0 left. The scan jobs' licence lookups spent it:

- 46 of the 72 names a licence pass asked GitHub about cannot be
  repositories ($/sbom from a workflow's `uses: $/sbom`, a glob, "<your").
- Each name went through about 14 requests through gh, then 12 more with
  GITHUB_TOKEN as a "PAT fallback", though gh already sends that token.
- Six processes per push repeat this: sca (two steps), license, sbom, and
  the sbom prior steps of the upload and bom-validate extras.

The lookups now:
- skip names GitHub cannot hold (validOwnerRepo);
- run repository, /license, then root listing, ending at a repository 404,
  with no blind file fetches and no duplicate token pass: 1-4 requests;
- spend from internal/ghquota, the forge budget moved to a shared package,
  seeded from the free /rate_limit, keeping 80% of the limit inside GitHub
  Actions (above the forge pass's half);
- stop on a rate-limit answer, leave unchecked licences UNKNOWN and say how
  many, and log each batch's request count in Actions.

gha init gives no token to a scanner run as an extra's prior step, which
publishes nothing; vulnetix.yml is regenerated.
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.

1 participant