snok / container-retention-policy

GitHub action for pruning old GHCR container image versions.
MIT License
178 stars 29 forks source link

Github app tokens being conflated with personal access token #94

Open sondrelg opened 1 month ago

sondrelg commented 1 month ago

Created from @amoosbr's comment in the v3 issue:

Hi, not sure if my question belongs to the v3 release or not. Just wanted to let you know, about my experience, when I tried to use v3.0.0 with a GitHub App token.

Based on the README image-names section, I expected to use a GitHub App for cleanup a image name like bla/* Readme snippet:

These operators are only available for personal- and GitHub app-tokens. See the token parameter section for more info.

Unfortunately, when I tried to use it as documented in the GitHub App token sample, I got the following response:

2024-07-29T09:34:18.768949Z DEBUG container_retention_policy: Logging initialized
2024-07-29T09:34:18.769670Z DEBUG parse input: container_retention_policy::cli::models: Recognized token as temporal token
2024-07-29T09:34:18.770018Z DEBUG parse input: container_retention_policy::client::builder: Constructing base urls
2024-07-29T09:34:18.770047Z DEBUG parse input: container_retention_policy::client::builder: Constructing HTTP headers
2024-07-29T09:34:18.770065Z DEBUG parse input: container_retention_policy::client::builder: Creating rate-limited services
2024-07-29T09:34:18.770328Z DEBUG fetch rate limit: container_retention_policy::client::client: Retrieving Github API rate limit
2024-07-29T09:34:18.842278Z DEBUG fetch rate limit: container_retention_policy::client::client: There are [15](https://github.com/bosch-adas-genai/actions/actions/runs/10141744949/job/28039764262#step:4:16)000 requests remaining in the rate limit
thread 'main' panicked at src/client/client.rs:46:17:
Restrictions in the Github API prevent us from listing packages when using a $GITHUB_TOKEN token. Because of this, filtering with '!' and '*' are not supported for this token type. Image name cache/* is therefore not valid.

Looking at the latest history, I saw a commit, that mentions GitHub App tokens behave like temporal tokens. I tried using building and running the 3.0.0 release candidate, where the GitHub App tokens was not treated as temporal token. Then my GitHub App token didn't have the needed scopes:

The token does not have the scopes needed. Tokens need `read:packages` and `delete:packages`. The scopes found were none.

My GitHub App has packages:write permission and is installed on the org with access to all repositories. I didn't find a packages:delete option for GitHub Apps.

I'm not 100% sure, if I just used the action wrong or my App has wrong settings. But if it is not possible to have wildcard image names with GitHub App tokens, perhaps the README can be updated.

As soon as I switched to using a classical PAT, the workflow stated to work as expected.

Originally posted by @amoosbr in https://github.com/snok/container-retention-policy/issues/84#issuecomment-2255734729

sondrelg commented 1 month ago

@amoosbr, this is the line you're hitting: https://github.com/snok/container-retention-policy/blob/148a83bf35cd75e909559585e6112d787a0d4b09/src/client/client.rs#L465. It's possible we could just remove this check. It's mainly there so that users with personal access tokens without permissions, get a clearer error than the one they would get from making the request with lacking permissions. Since we're inferring the token type from the token prefix, I can't immediately think of a good way to differentiate between a classic PAT and an app token 🤔

amoosbr commented 1 month ago

I did some further test and I'm not able to list container packages using my GitHub App token. Not sure, if it is at all possible to use an GitHub App to list packages or not. At least I wasn't able to list any container packages via direct curl request to the GitHub API

# get token for GitHub App using: https://github.com/Link-/gh-token
❯ token=$(gh token generate --key /path/to/key.pem --app-id 111111 --installation-id 2222222)
❯ echo $token
{
  "token": "ghs_....",
  "expires_at": "2024-07-29T17:01:47Z",
  "permissions": {
    "contents": "read",
    "metadata": "read",
    "packages": "write"
  }
}

❯ token=$(jq -r ".token" <<< $token)

❯ curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer $token" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  "https://api.github.com/orgs/ORG/packages?package_type=container"
{
  "message": "Invalid argument.",
  "documentation_url": "https://docs.github.com/rest/packages/packages#list-packages-for-an-organization",
  "status": "400"
}

I also forked this repo and adjusted all temporal token checks and also got the same error response:

2024-07-29T15:11:35.381497Z DEBUG select packages: container_retention_policy::client::client: Fetching data from https://api.github.com/orgs/ORG/packages?package_type=container&per_page=100
thread 'main' panicked at src/client/client.rs:59:14:
Failed to fetch packages: Failed to deserialize paginated response: {"message":"Invalid argument.","documentation_url":"https://docs.github.com/rest/packages/packages#list-packages-for-an-organization","status":"400"}. The error was invalid type: map, expected a sequence at line 1 column 0.

Will stick with the PAT tokens until GitHub adjusts it's API.

sondrelg commented 1 month ago

There's a working example of a Github token being used, here: https://github.com/snok/container-retention-policy/blob/main/.github/workflows/live_test.yaml#L40:L59, so I think it should be possible. You do need to install the app into your org., and so on.