GitHub Action
Ghcr.io Cleanup Action
A workflow action that cleans up images in the GitHub Container Registry (ghcr.io)
It includes the following features:
- Automatic GitHub user/organization repository support
- Removing by tags, including untagging multi tagged images
- Multi architecture image support
- Referrers/Attestation support (OCIv1 tag approach)
- Keeping a number of untagged images
- Keeping a number of tagged images
- Supports wildcard syntax for tag/exclude tag options
- Multi architecture & Referrers image validation mode
Test the cleanup action first by setting the "dry-run: true" option on the action and then reviewing the workflow log. This mode will simulate the cleanup action but will not delete any images/packages. This is especially important when using a wildcard syntax to select images.
To allow the injected GITHUB_TOKEN to have access to delete the images/packages ensure it's permissions have been setup correctly, either by:
-
In project Settings > Actions > General set the Workflow permissions option to "Read and write permissions"
-
Set the permissions directly in the workflow by setting the packages value to write.
jobs: delete-untagged-images: name: Delete Untagged Images runs-on: ubuntu-latest permissions: packages: write
Option | Required | Defaults | Description |
---|---|---|---|
token | yes | Token used to connect with ghcr.io and the package API | |
tags | no | Comma separated list of tags to delete (supports wildcard syntax) | |
exclude-tags | no | Comma separated list of tags to exclude (supports wildcard syntax) | |
keep-n-untagged | no | Number of untagged images to keep, sorted by date | |
keep-n-tagged | no | Number of tagged images to keep, sorted by date | |
dry-run | no | false | Simulate cleanup action, does not make changes (true/false) |
validate | no | false | Validate all multi architecture images in the registry after cleanup |
owner | no | project owner | The repository owner, can be organization or user type |
repository | no | repository name | The repository name |
package | no | repository name | The package name |
If the tags, keep-n-untagged or keep-n-tagged options are not set then all untagged images will be deleted.
The keep-n-untagged and keep-n-tagged options can not be set at the same time.
To cleanup all untagged images in a image repository only the token is required to be set. It will use the current repository information to setup the owner and package name.
jobs:
- name: ghcr.io cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
Set the tags option to delete specific tags
jobs:
- name: ghcr.io cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: mytag,mytag2
token: ${{ secrets.GITHUB_TOKEN }}
If the tag links to an image with multiple tags, the action will unlink the tag before is deleted, effetively untagging the image, but the underlying image will not be deleted unless all tags are deleted.
Keeps all tagged images and removes all untagged images except for the number of "keep-n-untagged" images (sorted by date). It supports multi-architecture images so the number of untagged images showing after running the action may be higher then the keep-n-untagged value set. May be combined with tags option to delete those tags too.
jobs:
- name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
keep-n-untagged: 3
token: ${{ secrets.GITHUB_TOKEN }}
Keeps a number (keep-n-tagged) of tagged images and then deletes the rest. Tags are sorted by date. Additional exclude-tags values are not include the total count.
jobs:
- name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
keep-n-tagged: 3
token: ${{ secrets.GITHUB_TOKEN }}
name: Cleanup Pull Request Images
on:
pull_request:
types: [closed]
jobs:
ghcr-cleanup-image:
name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- name: Delete image
uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: pr-${{github.event.pull_request.number}}
token: ${{ secrets.GITHUB_TOKEN }}
name: Daily Image Cleanup
on:
# every day at 01:30am
schedule:
- cron: '30 1 * * *'
# or manually
workflow_dispatch:
jobs:
ghcr-cleanup-image:
name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
The default settings will use the current project to determine the owner, repository and package name but for cross project and multiple package support these can be overriden by setting owner, repository and package values.
jobs:
- name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: mytag,mytag2
owner: dataaxiom
repository: tiecd
package: tiecd
token: ${{ secrets.GITHUB_TOKEN }}
The tags and exclude-tags options can use a wildcard syntax, using the ?, * and ** characters. (Utilizes the wildcard-match library)
jobs:
- name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
keep-n-tagged: 3
exclude-tags: 'v*,dev,latest'
token: ${{ secrets.GITHUB_TOKEN }}
Simulates how to keep 10 tagged images as well as the dev-image.
jobs:
- name: ghcr cleanup action
runs-on: ubuntu-latest
steps:
- name: 'Clean up docker images'
uses: dataaxiom/ghcr-cleanup-action@v1
with:
keep-n-tagged: 10
exclude-tags: dev
dry-run: true
token: ${{ secrets.GITHUB_TOKEN }}
GitHub has a package restoration API capability. The package IDs are printed in the workflow log where the ghcr-cleanup-action is run.
Multi architecture images which have no underlying platform packages are automatically removed for the keep-n-untagged and keep-n-tagged modes and not included in their count. Partially corrupt images are not removed by default, use the validate option to be able to identify and then fix them.
Set the validate option to true to enable a full scan of the image repository at the end of the execution to check that all multi architecture images have no missing platform images. Warnings will be outputted if there are missing packages.