Files
Byparr/.github/workflows/docker-cleanup.yml
T
ThePhaselessandClaude c45a464462 Add Building Feature (#276)
* feat: Build Docker images for PRs with branch name labels

- Remove condition preventing PR builds
- Add branch name extraction and sanitization
- Add branch labels to Docker images (org.opencontainers.image.branch and branch)
- Enable pushing of PR Docker images
- Sanitize branch names for Docker tags (replace / with -)

This allows PR images to be built and tagged with their branch names,
making it easier to test specific PR builds.

* feat: Add path filters to Docker workflow

Only build Docker images when relevant files change:
- Source code (src/**, main.py, tests/**)
- Docker configuration (Dockerfile, compose.yaml)
- Dependencies (pyproject.toml, uv.lock)
- Workflow file itself

This prevents unnecessary builds when only documentation or
other non-functional files are changed.

* feat: Add automatic cleanup of PR Docker images

Create a new workflow that automatically deletes Docker images
when a PR is closed or merged. This prevents accumulation of
old PR images in the container registry.

Features:
- Triggers on PR close/merge events
- Deletes images tagged with PR number and SHA
- Handles both architecture variants (amd64, arm64)
- Supports both organization and user repositories
- Provides detailed logging of cleanup operations

* refactor: Remove redundant branch label preparation

Remove duplicate branch name preparation step in merge-and-push job.
Branch labels are already added during the build step, so no need
to add them again when creating the manifest.

* refactor: Remove redundant label configurations

Remove custom label configurations from docker-publish workflow.
The docker/metadata-action already sets standard OCI labels by
default, so explicit label configuration is unnecessary.

Also removed unused BRANCH_TAG variable preparation.

* refactor: Use PR number for Docker image tags instead of SHA

Changed Docker image tagging strategy for pull requests:
- Use pr-{number}-{arch} for individual platform builds
- Use pr-{number} for final manifest
- Non-PR builds still use SHA-based tags

Benefits:
- Simpler, more readable tags for PRs
- Easier to identify which PR an image belongs to
- Cleanup script simplified to match only PR number tags

Updated cleanup workflow to match new tag pattern.

* docs: Add PR Docker image tags to README

Document the pr-{number} tag pattern used for pull request images.
These images are automatically built for PRs and cleaned up when
the PR is closed.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-20 01:25:00 +01:00

108 lines
3.7 KiB
YAML

name: Cleanup PR Docker Images
on:
pull_request:
types: [closed]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
cleanup:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Delete PR Docker images
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner.toLowerCase();
const repo = context.repo.repo.toLowerCase();
const prNumber = context.payload.pull_request.number;
// Get the package
const packageName = `${repo}`;
console.log(`Cleaning up images for PR #${prNumber}`);
// Check if owner is an org or user
let isOrg = false;
try {
await github.rest.orgs.get({ org: owner });
isOrg = true;
console.log(`Repository owner is an organization`);
} catch (error) {
console.log(`Repository owner is a user account`);
}
try {
// Get all versions of the package
let versions;
if (isOrg) {
versions = await github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg({
package_type: 'container',
package_name: packageName,
org: owner,
per_page: 100
});
} else {
versions = await github.rest.packages.getAllPackageVersionsForPackageOwnedByUser({
package_type: 'container',
package_name: packageName,
username: owner,
per_page: 100
});
}
// Filter versions that match this PR (pr-123, pr-123-amd64, pr-123-arm64)
const prVersions = versions.data.filter(version => {
const tags = version.metadata?.container?.tags || [];
// Match tags like: pr-123, pr-123-amd64, pr-123-arm64
return tags.some(tag =>
tag === `pr-${prNumber}` ||
tag === `pr-${prNumber}-amd64` ||
tag === `pr-${prNumber}-arm64`
);
});
console.log(`Found ${prVersions.length} image version(s) to delete`);
// Delete each version
for (const version of prVersions) {
console.log(`Deleting version ${version.id} with tags: ${version.metadata?.container?.tags?.join(', ')}`);
try {
if (isOrg) {
await github.rest.packages.deletePackageVersionForOrg({
package_type: 'container',
package_name: packageName,
org: owner,
package_version_id: version.id
});
} else {
await github.rest.packages.deletePackageVersionForUser({
package_type: 'container',
package_name: packageName,
username: owner,
package_version_id: version.id
});
}
console.log(`✓ Deleted version ${version.id}`);
} catch (error) {
console.error(`Failed to delete version ${version.id}:`, error.message);
}
}
console.log('Cleanup completed');
} catch (error) {
if (error.status === 404) {
console.log('No package found - nothing to clean up');
} else {
console.error('Error during cleanup:', error.message);
throw error;
}
}