diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa25a5a733..fe4a7d1f02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,30 +16,200 @@ jobs: uses: ./.github/workflows/test-build.yml secrets: inherit - # Build and push images (ECR for staging, ECR + GHCR for main) - build-images: - name: Build Images - needs: test-build - if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') - uses: ./.github/workflows/images.yml - secrets: inherit - permissions: - contents: read - packages: write - id-token: write - - # Deploy Trigger.dev (after builds complete) + # Deploy Trigger.dev FIRST (right after test-build, before images) trigger-deploy: name: Deploy Trigger.dev - needs: build-images + needs: test-build if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') uses: ./.github/workflows/trigger-deploy.yml secrets: inherit - # Process docs embeddings if needed + # Build AMD64 images and push to ECR immediately (+ GHCR for main) + build-amd64: + name: Build AMD64 + needs: trigger-deploy + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') + runs-on: blacksmith-4vcpu-ubuntu-2404 + permissions: + contents: read + packages: write + id-token: write + strategy: + fail-fast: false + matrix: + include: + - dockerfile: ./docker/app.Dockerfile + ghcr_image: ghcr.io/simstudioai/simstudio + ecr_repo_secret: ECR_APP + - dockerfile: ./docker/db.Dockerfile + ghcr_image: ghcr.io/simstudioai/migrations + ecr_repo_secret: ECR_MIGRATIONS + - dockerfile: ./docker/realtime.Dockerfile + ghcr_image: ghcr.io/simstudioai/realtime + ecr_repo_secret: ECR_REALTIME + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.AWS_ROLE_TO_ASSUME || secrets.STAGING_AWS_ROLE_TO_ASSUME }} + aws-region: ${{ github.ref == 'refs/heads/main' && secrets.AWS_REGION || secrets.STAGING_AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GHCR + if: github.ref == 'refs/heads/main' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: useblacksmith/setup-docker-builder@v1 + + - name: Generate tags + id: meta + run: | + ECR_REGISTRY="${{ steps.login-ecr.outputs.registry }}" + ECR_REPO="${{ secrets[matrix.ecr_repo_secret] }}" + GHCR_IMAGE="${{ matrix.ghcr_image }}" + + # ECR tags (always build for ECR) + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + ECR_TAG="latest" + else + ECR_TAG="staging" + fi + ECR_IMAGE="${ECR_REGISTRY}/${ECR_REPO}:${ECR_TAG}" + + # Build tags list + TAGS="${ECR_IMAGE}" + + # Add GHCR tags only for main branch + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + GHCR_AMD64="${GHCR_IMAGE}:latest-amd64" + GHCR_SHA="${GHCR_IMAGE}:${{ github.sha }}-amd64" + TAGS="${TAGS},$GHCR_AMD64,$GHCR_SHA" + fi + + echo "tags=${TAGS}" >> $GITHUB_OUTPUT + + - name: Build and push images + uses: useblacksmith/build-push-action@v2 + with: + context: . + file: ${{ matrix.dockerfile }} + platforms: linux/amd64 + push: true + tags: ${{ steps.meta.outputs.tags }} + provenance: false + sbom: false + + # Build ARM64 images for GHCR (main branch only, runs in parallel) + build-ghcr-arm64: + name: Build ARM64 (GHCR Only) + needs: trigger-deploy + runs-on: linux-arm64-8-core + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + include: + - dockerfile: ./docker/app.Dockerfile + image: ghcr.io/simstudioai/simstudio + - dockerfile: ./docker/db.Dockerfile + image: ghcr.io/simstudioai/migrations + - dockerfile: ./docker/realtime.Dockerfile + image: ghcr.io/simstudioai/realtime + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: useblacksmith/setup-docker-builder@v1 + + - name: Generate ARM64 tags + id: meta + run: | + IMAGE="${{ matrix.image }}" + echo "tags=${IMAGE}:latest-arm64,${IMAGE}:${{ github.sha }}-arm64" >> $GITHUB_OUTPUT + + - name: Build and push ARM64 to GHCR + uses: useblacksmith/build-push-action@v2 + with: + context: . + file: ${{ matrix.dockerfile }} + platforms: linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + provenance: false + sbom: false + + # Create GHCR multi-arch manifests (only for main, after both builds) + create-ghcr-manifests: + name: Create GHCR Manifests + runs-on: blacksmith-4vcpu-ubuntu-2404 + needs: [build-amd64, build-ghcr-arm64] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + packages: write + strategy: + matrix: + include: + - image: ghcr.io/simstudioai/simstudio + - image: ghcr.io/simstudioai/migrations + - image: ghcr.io/simstudioai/realtime + + steps: + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push manifests + run: | + IMAGE_BASE="${{ matrix.image }}" + + # Create latest manifest + docker manifest create "${IMAGE_BASE}:latest" \ + "${IMAGE_BASE}:latest-amd64" \ + "${IMAGE_BASE}:latest-arm64" + docker manifest push "${IMAGE_BASE}:latest" + + # Create SHA manifest + docker manifest create "${IMAGE_BASE}:${{ github.sha }}" \ + "${IMAGE_BASE}:${{ github.sha }}-amd64" \ + "${IMAGE_BASE}:${{ github.sha }}-arm64" + docker manifest push "${IMAGE_BASE}:${{ github.sha }}" + + # Process docs embeddings (only needs ECR images from build-amd64) process-docs: name: Process Docs - needs: [build-images, trigger-deploy] + needs: build-amd64 if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') uses: ./.github/workflows/docs-embeddings.yml secrets: inherit