Skip to content

test-coverage workflow fails on fork PRs: fake GitHub server returns HTTP 401 in github-tools tests #467

Description

@schloerke

Summary

The test-coverage workflow (uncovr::test()) fails on pull requests from forks. Every test in tests/testthat/test-github-tools.R errors or fails because the in-process fake GitHub GraphQL server (gh_app() in R/gh-app.R) responds with HTTP 401 "Bad credentials" — i.e. the Authorization header produced by type_github_get_headers() does not satisfy re_gh_auth() in that job's environment.

First observed on the test-coverage job of #466 (a fork PR). It is not caused by that PR — see "Why this is independent" below.

Symptoms (from the failing run)

  • First failure is an error, not a snapshot diff:
    • Error ('test-github-tools.R:4:3'): type_github_get_data, sha, description
    • ! Bad GitHub credentials, make sure that your GitHub token is valid.
    • Caused by error in stop(http_error(resp)): Unauthorized (HTTP 401).
    • The request URL in the condition is the local fake server (http://127.0.0.1:<port>//graphql), so this is the fake server's auth middleware rejecting the token, not real GitHub.
  • All remaining github-tools failures are snapshot mismatches that are downstream of that 401 (each now contains an extra + Caused by error in stop(http_error(resp)) line).
  • Net: github-tools reports ~15 failures; the job exits non-zero.

Failing run: https://github.com/r-lib/pkgdepends/actions/runs/26966219572/job/79569428678

What passes (scoping)

  • All R-CMD-check matrix jobs (macOS / Ubuntu / Windows, release + oldrels) on the same fork PRgithub-tools passes there.
  • test-coverage on main push events (e.g. the 2026-06-01 run).
  • uncovr::test() locallygithub-tools passes; only unrelated environmental failures occur (test-assertions, type-standard/type-bioc new-R snapshots, scan-deps tempdir).

So the failure is specific to test-coverage (uncovr/covr) + fork-PR environment. Both R-CMD-check.yaml and test-coverage.yaml set the identical GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}, so the differentiator is the coverage harness, not the token env declaration alone. This is the first fork PR to trigger test-coverage (the workflow was added 2026-05-21), which is why it has not surfaced before.

Likely area

type_github_get_headers() (R/type-github.R) selects a token (CI_GITHUB_TOKENgitcreds_get() → bundled PAT), and the fake server's auth middleware in gh_app() rejects it via re_gh_auth() (^token (gh[pousr]_[A-Za-z0-9_]{36,251}|[[:xdigit:]]{40})$). In the fork-PR coverage environment the resulting Authorization value evidently doesn't match. Needs reproduction in that specific environment to confirm the exact token value.

Possible fixes (for a follow-up PR)

  • Set CI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} in test-coverage.yaml (so a known-good token is used), or
  • Make the fake server's auth check tolerant of the token form seen in this environment, or
  • Skip the auth check / github-tools snapshot tests when no usable token is available.

Why this is independent of #466

#466 does not modify the auth middleware, re_gh_auth(), type_github_get_headers(), the token-selection path, or the github-tools tests. Its only github-tools change is the snapshot file, which is compared after the (failing) request, so it cannot cause a 401.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions