Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Removing untagged images can damage tagged multi-arch images #76

Open
jr01 opened this issue Sep 7, 2023 · 6 comments
Open

Removing untagged images can damage tagged multi-arch images #76

jr01 opened this issue Sep 7, 2023 · 6 comments

Comments

@jr01
Copy link

jr01 commented Sep 7, 2023

To publish an image we use something like:

- uses: docker/build-push-action@v4
  with:
     context: .
     push: true
     tags: |
       my-image: v0.0.1

And we were pruning any untagged images with something like:

- uses: vlaurin/action-ghcr-prune@v0.5.0
  with:
     token: ${{ secrets.MY_TOKEN }}
     organization: myorg
     container: mycontainer
     prune-untagged: true

We noticed that after pruning a docker pull ghcr.io/myorg/mycontainer:v0.0.1 would return error: manifest unknown.

We found snok/container-retention-policy#63 that explains the issue.

We aren't using multi-arch and can use the provenance: false workaround.

MentalFS added a commit to MentalFS/linuxserver-docker-mods that referenced this issue Jan 14, 2024
@daltonv
Copy link

daltonv commented Mar 1, 2024

I actually do use multi-arch images so this is a problem for me & my team.

I did fork the repo and add this ability at https://github.com/daltonv/action-ghcr-prune/tree/dv_multi_arch

However I saw the similar #75 was closed due to it being out of scope. My fix is I think a bit more precise and is off by default. I can make a pr, @vlaurin, if you think this is a more maintainable solution.

@emmahsax
Copy link

emmahsax commented Apr 10, 2024

@daltonv To clarify, your modification is such that we wouldn't have to tidy up untagged and tagged images. Instead, we should change our code to simply delete any tagged image, and then if it is multi-arch, your change would also delete the untagged images that correspond to it.

Is that correct?

And here's an example of the changes that'd be required:

  jobs:
-   delete-untagged-packages:
-     runs-on: ubuntu-latest
-     steps:
-       - uses: vlaurin/action-ghcr-prune@v0.6.0
-         with:
-           container: ${{ github.event.repository.name }}
-           dry-run: false
-           keep-last: 12
-           organization: ${{ github.repository_owner }}
-           prune-untagged: true
-           token: ${{ secrets.GITHUB_TOKEN }}
-
    delete-tagged-packages:
      runs-on: ubuntu-latest
      steps:
-       - uses: vlaurin/action-ghcr-prune@v0.6.0
+       - uses: daltonv/action-ghcr-prune@v0.1.0
          with:
            container: ${{ github.event.repository.name }}
            dry-run: false
            keep-last: 5
            keep-tags-regexes: |
              ^latest$
            organization: ${{ github.repository_owner }}
+           prune-multi-platform: true
            prune-tags-regexes: |
              .+
            token: ${{ secrets.GITHUB_TOKEN }}

And then even with these changes, when I run it, I get an API failure:

Run daltonv/action-ghcr-prune@v0.1.0
  with:
    container: my-repo
    dry-run: true
    keep-last: 0
    keep-tags-regexes: ^latest$
  
    organization: my-org
    prune-multi-platform: true
    prune-tags-regexes: .+
  
    token: ***
    older-than: 0
    keep-younger-than: 0
    prune-untagged: false
    untagged: false
Crawling through all versions to build pruning list...
Found 5 versions to prune out of [2](https://github.com/my-org/my-repo/actions/runs/8635358189/job/23672892553#step:3:2)1 on page 1
Crawling through pruning list for multi-platform images...
Error: Docker API request at https://ghcr.io/v2/my-org/my-repo/manifests/pre-release-d2f02[8](https://github.com/my-org/my-repo/actions/runs/8635358189/job/23672892553#step:3:8)0 was not successful

Did I miss something? Am I supposed to use the ${{ secrets.GITHUB_TOKEN }} or a different PAT?

@emmahsax
Copy link

I ended up expanding on what @daltonv worked with even further. I adjusted @daltonv's code so that it worked with my images, and then I made it so that when pruning untagged images, it'll never try to prune any image that is a part of a multi-arch image at all: https://github.com/emmahsax/action-ghcr-prune/tree/main

So now, we can call my variation of the action like this:

jobs:
  delete-old-packages:
    runs-on: ubuntu-latest
    steps:
      # Delete all tagged packages except `latest` and the last other 5 (so 6 tagged packages left over
      # at the end). Also delete the untagged variants of the tagged packages that are deleted.
      - name: Delete Old Tagged Packages
        uses: emmahsax/action-ghcr-prune@main
        with:
          container: ${{ github.event.repository.name }}
          dry-run: true
          keep-last: 5
          keep-tags-regexes: |
            ^latest$
          organization: ${{ github.repository_owner }}
          prune-tags-regexes: |
            .+
          remove-multi-platform: true
          token: ${{ secrets.GITHUB_TOKEN }}

      # After the first step finishes, then go through and delete all other untagged packages
      # UNLESS they are a part of a multi-arch image that is left around from the first step.
      - name: Delete Old Untagged Packages
        uses: emmahsax/action-ghcr-prune@main
        with:
          container: ${{ github.event.repository.name }}
          dry-run: true
          keep-last: 0
          organization: ${{ github.repository_owner }}
          prune-untagged: true
          token: ${{ secrets.GITHUB_TOKEN }}

@daltonv
Copy link

daltonv commented Apr 18, 2024

Ah good finds @emmahsax. It looks like you found two things I did not consider with my change:

Your code looks to only support v1 of the docker manifest though. So its the opposite of my bug. We need to instead detect the version of the manifest used. However, I'm not 100% sure the auth error you got was just because you I wasn't specifically Accepting a v1 manifest. If that is the problem we aught to just retry the auth with v1 header.

@emmahsax
Copy link

Yeah, I definitely built the version I did solely for the projects that I wanted to manage. Sometime soon, maybe I'll work to try to make another PR on my version that can detect the different versions.

I'll also test out some of the original code you had when it comes to the auth token. Honestly I don't even remember the train of thoughts I went down to get where mine ended up haha.

@rohanmars
Copy link

I just made (yet another) cleanup implementation that focuses on multi-arch cleanup: https://github.com/dataaxiom/ghcr-cleanup-action. At any rate it shows the approach/complexity of the requirement.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants