Skip to content

chore: proof of concept wip #253

chore: proof of concept wip

chore: proof of concept wip #253

Workflow file for this run

# =============================================================================
# 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