Docker Cleanup #141
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docker Cleanup | |
| on: | |
| pull_request: | |
| types: [closed] | |
| branches: ["main", "develop"] | |
| schedule: | |
| # Cleanup obsolete images daily at 2:00 AM UTC | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| env: | |
| DOCKERHUB_IMAGE: johandevl/export-trakt-4-letterboxd | |
| GITHUB_REGISTRY: ghcr.io | |
| GITHUB_IMAGE: ghcr.io/johandevl/export_trakt_4_letterboxd | |
| jobs: | |
| cleanup-pr: | |
| name: Cleanup PR Docker Images | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Delete PR Docker image from GitHub Container Registry | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const pr_number = context.payload.pull_request.number; | |
| const tag = `PR-${pr_number}`; | |
| const imageName = '${{ github.repository }}'.toLowerCase(); | |
| console.log(`Attempting to delete GitHub Container Registry image with tag: ${tag}`); | |
| try { | |
| const { data: versions } = await github.rest.packages.getAllPackageVersionsForPackageOwnedByAuthenticatedUser({ | |
| package_type: 'container', | |
| package_name: imageName, | |
| }); | |
| const versionToDelete = versions.find(version => | |
| version.metadata.container.tags.includes(tag) | |
| ); | |
| if (versionToDelete) { | |
| console.log(`Found version: ${versionToDelete.id} with tag ${tag}`); | |
| await github.rest.packages.deletePackageVersionForAuthenticatedUser({ | |
| package_type: 'container', | |
| package_name: imageName, | |
| package_version_id: versionToDelete.id | |
| }); | |
| console.log(`Successfully deleted GitHub Container Registry image with tag: ${tag}`); | |
| } else { | |
| console.log(`No GitHub Container Registry image found with tag: ${tag}`); | |
| } | |
| } catch (error) { | |
| console.log(`Error deleting GitHub Container Registry image: ${error.message}`); | |
| } | |
| - name: Delete PR Docker image from Docker Hub | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr_number = context.payload.pull_request.number; | |
| const tag = `PR-${pr_number}`; | |
| console.log(`Attempting to delete Docker Hub image with tag: ${tag}`); | |
| try { | |
| const response = await fetch(`https://hub.docker.com/v2/repositories/${{ env.DOCKERHUB_IMAGE }}/tags/${tag}/`, { | |
| method: 'DELETE', | |
| headers: { | |
| 'Authorization': `Bearer ${{ secrets.DOCKERHUB_TOKEN }}` | |
| } | |
| }); | |
| if (response.ok) { | |
| console.log(`Successfully deleted Docker Hub image with tag: ${tag}`); | |
| } else if (response.status === 404) { | |
| console.log(`No Docker Hub image found with tag: ${tag}`); | |
| } else { | |
| console.log(`Error deleting Docker Hub image: ${response.statusText}`); | |
| } | |
| } catch (error) { | |
| console.log(`Error deleting Docker Hub image: ${error.message}`); | |
| } | |
| - name: Summary | |
| run: | | |
| echo "🧹 Cleanup completed for PR-${{ github.event.pull_request.number }} Docker images" | |
| cleanup-obsolete: | |
| name: Cleanup Obsolete Docker Images | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get active PR numbers | |
| id: active-prs | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open' | |
| }); | |
| const activePRs = prs.map(pr => `PR-${pr.number}`); | |
| console.log('Active PR tags:', activePRs.join(', ')); | |
| return activePRs; | |
| - name: Cleanup obsolete GitHub Container Registry images | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const activePRs = ${{ steps.active-prs.outputs.result }}; | |
| const imageName = '${{ github.repository }}'.toLowerCase(); | |
| const protectedTags = ['latest', 'main', 'develop']; | |
| console.log('Protected tags:', protectedTags.join(', ')); | |
| console.log('Active PR tags:', activePRs.join(', ')); | |
| try { | |
| const { data: versions } = await github.rest.packages.getAllPackageVersionsForPackageOwnedByAuthenticatedUser({ | |
| package_type: 'container', | |
| package_name: imageName, | |
| }); | |
| let deletedCount = 0; | |
| for (const version of versions) { | |
| const tags = version.metadata.container.tags; | |
| // Skip if no tags | |
| if (!tags || tags.length === 0) continue; | |
| // Check if any tag is protected | |
| const hasProtectedTag = tags.some(tag => | |
| protectedTags.includes(tag) || | |
| tag.match(/^v\d+\.\d+\.\d+$/) || // Semantic version tags | |
| activePRs.includes(tag) | |
| ); | |
| if (!hasProtectedTag) { | |
| console.log(`Deleting version ${version.id} with tags: ${tags.join(', ')}`); | |
| try { | |
| await github.rest.packages.deletePackageVersionForAuthenticatedUser({ | |
| package_type: 'container', | |
| package_name: imageName, | |
| package_version_id: version.id | |
| }); | |
| deletedCount++; | |
| } catch (error) { | |
| console.log(`Failed to delete version ${version.id}: ${error.message}`); | |
| } | |
| } else { | |
| console.log(`Keeping version ${version.id} with protected tags: ${tags.join(', ')}`); | |
| } | |
| } | |
| console.log(`Cleanup completed. Deleted ${deletedCount} obsolete image versions.`); | |
| } catch (error) { | |
| console.log(`Error during cleanup: ${error.message}`); | |
| } | |
| - name: Summary | |
| run: | | |
| echo "🧹 Cleanup of obsolete Docker images completed" |