From d95007b6d94e4042091c41d2abbf6fc22268e98b Mon Sep 17 00:00:00 2001 From: Biplov Bhandari <4207677+biplovbhandari@users.noreply.github.com> Date: Fri, 28 Aug 2026 00:16:33 -0400 Subject: [PATCH] Add GHCR publish and prune workflows --- .dockerignore | 5 +- .github/workflows/build-dev-images.yml | 78 ++++++++++++++++++++++++++ .github/workflows/prune-dev-images.yml | 55 ++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-dev-images.yml create mode 100644 .github/workflows/prune-dev-images.yml diff --git a/.dockerignore b/.dockerignore index fc8b034..ab7a785 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,8 +17,10 @@ experiments/ .cursor/ # Infrastructure and planning (not needed in container) -terraform/ +infra/ plan/ +tests/ +notebooks/ # Python and conda cache __pycache__/ @@ -40,6 +42,7 @@ dist/ *.egg # Docs and misc +docs/ *.md !README.md .DS_Store diff --git a/.github/workflows/build-dev-images.yml b/.github/workflows/build-dev-images.yml new file mode 100644 index 0000000..1f2d1c4 --- /dev/null +++ b/.github/workflows/build-dev-images.yml @@ -0,0 +1,78 @@ +name: Build and Publish Dev Images + +on: + push: + branches: [main] + paths: + - "Dockerfile" + - "environment.yaml" + - "src/**" + - "scripts/**" + - "utils/**" + - ".github/workflows/build-dev-images.yml" + workflow_dispatch: + +# Keep the floating `dev` tag honest: if two pushes land in quick succession, +# cancel the older run so `dev` can't point at the earlier commit. +# The sha- tags are immutable, so nothing is lost by cancelling. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + REGISTRY: ghcr.io + +permissions: {} + +jobs: + build: + name: Build inference + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Derive tags and labels + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository }}/inference + tags: | + type=sha,prefix=sha-,format=short + type=raw,value=dev,enable={{is_default_branch}} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64 + provenance: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Summarize published tags + run: | + { + echo "### Published inference image" + echo '```' + echo "${{ steps.meta.outputs.tags }}" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/prune-dev-images.yml b/.github/workflows/prune-dev-images.yml new file mode 100644 index 0000000..69986f5 --- /dev/null +++ b/.github/workflows/prune-dev-images.yml @@ -0,0 +1,55 @@ +name: Prune Dev Images + +on: + schedule: + # Runs at 03:00 UTC, only on Monday + - cron: "0 3 * * 1" + workflow_dispatch: + inputs: + dry-run: + description: "Log what would be deleted without deleting anything" + type: boolean + default: true + +permissions: {} + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +jobs: + prune: + name: Prune inference + runs-on: ubuntu-latest + + permissions: + packages: write + + steps: + - name: Prune old sha- images + uses: dataaxiom/ghcr-cleanup-action@d52806a0dc70b430571a37da1fde39733ffd640f # v1.2.2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + owner: ${{ github.repository_owner }} + package: ${{ github.event.repository.name }}/inference + + # Only touch images older than two weeks. + older-than: 2 weeks + + # Always keep the newest tagged image even if it's older than + # two weeks. Prevents removing the last build if main is quiet. + keep-n-tagged: 1 + + # Reap dangling manifests orphaned each time the dev tag moves. + delete-untagged: true + + # Protected tags. sha- carries no dots so it stays + # eligible for pruning. + exclude-tags: dev,latest,*.*.*,*.*,v* + + # Verify no multi-arch image was left without platform children. + validate: true + + # Scheduled runs delete for real. Manual runs default to dry run + # so the filters can be eyeballed before anything is destroyed. + dry-run: ${{ inputs.dry-run || false }}