Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions .github/workflows/docker-runtimes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
# GitHub Actions Workflow: Build and Push HCA Runtime Docker Images
#
# This workflow builds multi-platform Docker images for HCA runtime containers
# and pushes them to GitHub Container Registry (ghcr.io).
#
# Build Strategy:
# - Push/Release: Build base → wait for registry → build runtimes with digest reference
# - Pull Request: Build base only (validation) - runtimes skipped since base isn't pushed
#
# Triggers:
# - Push to master branch (when Dockerfile or config changes)
# - Pull requests (base build validation only)
# - Release publications (tags with version)
# - Manual dispatch

name: Build HCA Runtime Containers

on:
push:
branches: [master]
paths:
- 'impl/mvp/docker/runtimes/**'
- '.github/workflows/docker-runtimes.yml'
pull_request:
branches: [master]
paths:
- 'impl/mvp/docker/runtimes/**'
- '.github/workflows/docker-runtimes.yml'
release:
types: [published]
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ghcr.io/ardaglobal/hca-runtime

jobs:
# ==========================================================================
# Build Base Image First (all others depend on this)
# ==========================================================================
build-base:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
digest: ${{ steps.build.outputs.digest }}
image-ref: ${{ steps.image-ref.outputs.ref }}

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata for base
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-base
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push base image
uses: docker/build-push-action@v5
id: build
with:
context: ./impl/mvp/docker/runtimes/base
file: ./impl/mvp/docker/runtimes/base/Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=base
cache-to: type=gha,mode=max,scope=base

- name: Set image reference output
id: image-ref
run: |
if [ "${{ github.event_name }}" != "pull_request" ]; then
# Use digest for immutable reference (immediately available after push)
echo "ref=${{ env.IMAGE_PREFIX }}-base@${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT
else
echo "ref=" >> $GITHUB_OUTPUT
fi

# ==========================================================================
# Build Runtime Images (depend on base, skip on PRs)
# ==========================================================================
build-runtimes:
needs: build-base
# Skip runtime builds on PRs since base image isn't pushed to registry
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

strategy:
fail-fast: false
matrix:
runtime:
- name: rust
port: 4100
- name: typescript
port: 4101
- name: python
port: 4102
- name: generic
port: 4103
- name: infrastructure
port: 4104

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Wait for base image availability
run: |
BASE_REF="${{ needs.build-base.outputs.image-ref }}"
echo "Waiting for base image: $BASE_REF"

for i in {1..30}; do
if docker pull "$BASE_REF" 2>/dev/null; then
echo "✅ Base image available after $i attempt(s)"
exit 0
fi
echo "⏳ Attempt $i/30: Base image not yet available, waiting 10s..."
sleep 10
done

echo "❌ Base image not available after 5 minutes"
exit 1

- name: Extract metadata for ${{ matrix.runtime.name }}
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-${{ matrix.runtime.name }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push ${{ matrix.runtime.name }} image
uses: docker/build-push-action@v5
id: build
with:
context: ./impl/mvp/docker/runtimes/${{ matrix.runtime.name }}
file: ./impl/mvp/docker/runtimes/${{ matrix.runtime.name }}/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ matrix.runtime.name }}
cache-to: type=gha,mode=max,scope=${{ matrix.runtime.name }}
build-args: |
BASE_IMAGE=${{ needs.build-base.outputs.image-ref }}

- name: Generate build summary
if: success()
run: |
echo "## 🐳 ${{ matrix.runtime.name }} Runtime Build" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Image | \`${{ env.IMAGE_PREFIX }}-${{ matrix.runtime.name }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Base | \`${{ needs.build-base.outputs.image-ref }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Port | ${{ matrix.runtime.port }} |" >> $GITHUB_STEP_SUMMARY
echo "| Platforms | linux/amd64, linux/arm64 |" >> $GITHUB_STEP_SUMMARY
echo "| Digest | \`${{ steps.build.outputs.digest }}\` |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Pull & Run" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull ${{ env.IMAGE_PREFIX }}-${{ matrix.runtime.name }}:latest" >> $GITHUB_STEP_SUMMARY
echo "docker run -d -p ${{ matrix.runtime.port }}:4096 \\" >> $GITHUB_STEP_SUMMARY
echo " -e OPENROUTER_API_KEY=\$OPENROUTER_API_KEY \\" >> $GITHUB_STEP_SUMMARY
echo " ${{ env.IMAGE_PREFIX }}-${{ matrix.runtime.name }}:latest" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

# ==========================================================================
# Summary Job
# ==========================================================================
summary:
needs: [build-base, build-runtimes]
runs-on: ubuntu-latest
if: always() && github.event_name != 'pull_request'

steps:
- name: Generate workflow summary
run: |
echo "# 🚀 HCA Runtime Containers Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Images Built" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Runtime | Image | Port |" >> $GITHUB_STEP_SUMMARY
echo "|---------|-------|------|" >> $GITHUB_STEP_SUMMARY
echo "| Base | \`${{ env.IMAGE_PREFIX }}-base\` | - |" >> $GITHUB_STEP_SUMMARY
echo "| Rust | \`${{ env.IMAGE_PREFIX }}-rust\` | 4100 |" >> $GITHUB_STEP_SUMMARY
echo "| TypeScript | \`${{ env.IMAGE_PREFIX }}-typescript\` | 4101 |" >> $GITHUB_STEP_SUMMARY
echo "| Python | \`${{ env.IMAGE_PREFIX }}-python\` | 4102 |" >> $GITHUB_STEP_SUMMARY
echo "| Generic | \`${{ env.IMAGE_PREFIX }}-generic\` | 4103 |" >> $GITHUB_STEP_SUMMARY
echo "| Infrastructure | \`${{ env.IMAGE_PREFIX }}-infrastructure\` | 4104 |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Quick Start" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "# Pull all images" >> $GITHUB_STEP_SUMMARY
echo "for rt in base rust typescript python generic infrastructure; do" >> $GITHUB_STEP_SUMMARY
echo " docker pull ${{ env.IMAGE_PREFIX }}-\$rt:latest" >> $GITHUB_STEP_SUMMARY
echo "done" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
env:
IMAGE_PREFIX: ghcr.io/ardaglobal/hca-runtime

# ==========================================================================
# PR Validation Summary
# ==========================================================================
pr-summary:
needs: [build-base]
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'

steps:
- name: Generate PR summary
run: |
echo "# 🔍 PR Validation Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Base Image" >> $GITHUB_STEP_SUMMARY
echo "✅ Base image builds successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Runtime Images" >> $GITHUB_STEP_SUMMARY
echo "⏭️ Skipped (only built on push to master)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Runtime images will be built and pushed when this PR is merged." >> $GITHUB_STEP_SUMMARY
Loading