chore: proof of concept wip #253
Workflow file for this run
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
| # ============================================================================= | |
| # CI: Build & Push Docker Images | |
| # ============================================================================= | |
| # | |
| # What this does: | |
| # 1. Builds Docker image for Intel (amd64) and ARM (arm64) separately | |
| # 2. Combines them into a single "manifest" (so docker pull auto-picks the right one) | |
| # | |
| # Result after push to "main": | |
| # - deeploy:main-amd64 (Intel version) | |
| # - deeploy:main-arm64 (ARM version) | |
| # - deeploy:main (manifest pointing to both) | |
| # - deeploy:latest (only for version tags v*) | |
| # | |
| # Why separate builds instead of one multi-platform build? | |
| # → Single multi-platform creates untagged sha256 images that pile up as garbage | |
| # → Separate builds create tagged images that get overwritten = no garbage | |
| # → Cleanup step removes any leftover untagged images after each build | |
| # | |
| # ============================================================================= | |
| name: CI | |
| on: | |
| push: | |
| branches: ["**"] # All branches | |
| tags: ["v*"] # Version tags like v1.0.0 | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: deeploy-sh/deeploy | |
| # ============================================================================= | |
| # JOB 1: Build Intel (amd64) version | |
| # ============================================================================= | |
| jobs: | |
| build-amd64: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # Convert branch name: feature/foo → feature-foo (Docker tags can't have /) | |
| - name: Get tag name | |
| id: tag | |
| run: | | |
| TAG="${{ github.ref_name }}" | |
| TAG="${TAG//\//-}" | |
| echo "name=$TAG" >> $GITHUB_OUTPUT | |
| - name: Build and push (amd64) | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| push: true | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-amd64 | |
| build-args: VERSION=${{ github.ref_name }} | |
| cache-from: type=gha,scope=amd64 | |
| cache-to: type=gha,mode=max,scope=amd64 | |
| # =========================================================================== | |
| # JOB 2: Build ARM (arm64) version | |
| # =========================================================================== | |
| build-arm64: | |
| runs-on: ubuntu-24.04-arm # GitHub's ARM runner | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Get tag name | |
| id: tag | |
| run: | | |
| TAG="${{ github.ref_name }}" | |
| TAG="${TAG//\//-}" | |
| echo "name=$TAG" >> $GITHUB_OUTPUT | |
| - name: Build and push (arm64) | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/arm64 | |
| push: true | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-arm64 | |
| build-args: VERSION=${{ github.ref_name }} | |
| cache-from: type=gha,scope=arm64 | |
| cache-to: type=gha,mode=max,scope=arm64 | |
| # =========================================================================== | |
| # JOB 3: Create manifest (combines amd64 + arm64) | |
| # =========================================================================== | |
| # A manifest is like a menu: "I have Intel and ARM versions, pick the right one" | |
| # When someone does `docker pull deeploy:main`, Docker reads the manifest | |
| # and automatically downloads the correct version for their CPU. | |
| # =========================================================================== | |
| manifest: | |
| needs: [build-amd64, build-arm64] # Wait for both builds | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Get tag name | |
| id: tag | |
| run: | | |
| TAG="${{ github.ref_name }}" | |
| TAG="${TAG//\//-}" | |
| echo "name=$TAG" >> $GITHUB_OUTPUT | |
| # Create manifest: deeploy:main → points to deeploy:main-amd64 + deeploy:main-arm64 | |
| - name: Create manifest | |
| run: | | |
| docker buildx imagetools create \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-amd64 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-arm64 \ | |
| --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }} | |
| # Only version tags get the "latest" tag (stable releases) | |
| - name: Create latest tag | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| docker buildx imagetools create \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-amd64 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.name }}-arm64 \ | |
| --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |