Skip to content

Cleanup PR Artifacts: package cleanup never runs (PAT lacks packages scope) #20

Open

Description

@cratis-direct

Describe the bug

The Cleanup PR Artifacts workflow run for PR #18
(https://github.com/Cratis/Common/actions/runs/36643592564) failed with:

X API GET failed (HTTP 403)
X Process completed with exit code 1.

Cratis/Common's workflow file itself
(.github/workflows/cleanup-pr-artifacts.yml) is a thin, correct caller of the
reusable workflow in Cratis/Workflows:

jobs:
  cleanup:
    uses: Cratis/Workflows/.github/workflows/cleanup-pr-artifacts.yml@main
    with:
      pull_request: ${{ github.event.pull_request.number }}
    secrets: inherit

There is nothing to change in this file: the reusable workflow never consumes
GITHUB_TOKEN for package deletion, so adding a permissions: block here
would have no effect. All of its GitHub Packages API calls authenticate with
the secrets.PAT_WORKFLOWS (or optional secrets.PACKAGE_CLEANUP_TOKEN)
classic PAT.

Root cause

At the commit that was live for this run
(Cratis/Workflows@c46f3bcd, "Fix PR package cleanup with fail-closed
inventory and approved retries", 2026-09-09), the cleanup script treated any
non-2xx response from the GitHub Packages API — including an HTTP 401/403 from
GET orgs/Cratis/packages — as a fatal CleanupError, failing the whole job.
That 403 means the token used for cleanup (PAT_WORKFLOWS, since this
repository has no PACKAGE_CLEANUP_TOKEN) is not authorized to list the
organization's packages (missing read:packages scope, missing package-admin
rights, or missing SSO authorization for the org).

This was not a bug in Cratis/Common, and it has since been fixed upstream
in Cratis/Workflows across three commits merged 2026-09-30 → 2026-10-05:

  • 841cf815 — pin actions/upload-artifact to v7.0.1
  • 5435636f — report an unauthorized package inventory as a neutral warning
    instead of failing the job
  • 193b80c9 / c64bc9bc — add the dedicated PACKAGE_CLEANUP_TOKEN secret
    and strip whitespace from it

With today's main of the reusable workflow, the exact scenario that failed
this run (HTTP 401/403 on the organization package inventory) now reports
"Could not run: package inventory not authorized" as a warning and exits
successfully — but it still deletes nothing, per the Cratis/Workflows
README:

HTTP 401/403 from the organization package inventory reports could not
run: package inventory not authorized
as a neutral warning and deletes
nothing for reusable calls, scheduled runs and dry runs... This is not a
completed cleanup.

What's actually wrong (and why I can't fix it myself)

So, re-running the workflow today would no longer fail the build, but PR
package cleanup for this repository is still a no-op: whatever token backs
PAT_WORKFLOWS lacks the scope the GitHub Packages API requires, and there is
no PACKAGE_CLEANUP_TOKEN secret configured as a fallback-free alternative.
PR-scoped container/NuGet package versions are never actually deleted; they
just accumulate quietly instead of erroring loudly.

Fixing this requires provisioning a classic PAT with read:packages,
delete:packages, package-admin rights, and organization SSO authorization
(fine-grained PATs aren't supported for these endpoints — see the
Cratis/Workflows README), and storing it as the PACKAGE_CLEANUP_TOKEN
organization secret, or widening PAT_WORKFLOWS's scopes. That's a
credential-provisioning action outside what I can or should do from here.

Suggested next step

An org owner should either:

  1. Grant PAT_WORKFLOWS read:packages + delete:packages + package-admin
    rights with SSO authorization, or
  2. Create a dedicated classic PAT with those scopes and store it as the
    PACKAGE_CLEANUP_TOKEN organization secret (per the Cratis/Workflows
    README), then confirm a real PR-close run actually deletes its tagged
    package versions rather than warning.

Activity

  1. added theissue type on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions