Files
cs249r_book/.github/workflows/build-linux-container.yml
Vijay Janapa Reddi 5a076da8d7 fix(workflows): prevent container builds from triggering on main branch
- Add 'branches: [dev]' to container build push triggers
- Prevents unnecessary builds when publishing to main
- Container builds should only happen during development
- Keeps scheduled weekly rebuilds and manual triggers intact
2025-08-19 15:00:59 -04:00

313 lines
11 KiB
YAML

name: '🐳 Build Linux Container'
# This workflow builds the Quarto build container and pushes it to GitHub Container Registry
# The container pre-installs all dependencies to eliminate 30-45 minute setup time
# Includes comprehensive testing to ensure all components work properly
# Prevent multiple builds running simultaneously
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
inputs:
force_rebuild:
description: 'Force rebuild even if no changes'
required: false
default: false
type: boolean
no_cache:
description: 'Disable Docker build cache (fresh build)'
required: false
default: false
type: boolean
container_registry:
description: 'Container registry URL'
required: false
default: 'ghcr.io'
type: string
container_name:
description: 'Container image name'
required: false
default: 'quarto-linux'
type: string
container_tag:
description: 'Container tag'
required: false
default: 'latest'
type: string
workflow_call:
inputs:
force_rebuild:
required: false
default: false
type: boolean
no_cache:
required: false
default: false
type: boolean
container_registry:
required: false
default: 'ghcr.io'
type: string
container_name:
required: false
default: 'quarto-linux'
type: string
container_tag:
required: false
default: 'latest'
type: string
outputs:
build-status:
description: "Container build status (success/failure/skipped)"
value: ${{ jobs.build.outputs.build-status }}
image-name:
description: "Full container image name with registry"
value: ${{ jobs.build.outputs.image-name }}
image-digest:
description: "Container image digest (SHA256)"
value: ${{ jobs.build.outputs.image-digest }}
cache-hit:
description: "Whether build used cache (true/false)"
value: ${{ jobs.build.outputs.cache-hit }}
# Re-enable automatic triggers
schedule:
- cron: '0 0 * * 0' # Weekly rebuild (Sunday at midnight)
push:
branches: [dev] # Only trigger on dev branch, not main
paths:
- 'tools/dependencies/**'
- 'docker/linux/**'
- '.github/workflows/build-linux-container.yml'
env:
# Container Registry Configuration (configurable via inputs)
REGISTRY: ${{ (github.event_name == 'workflow_dispatch' && inputs.container_registry) || 'ghcr.io' }}
IMAGE_NAME: ${{ github.repository }}/${{ (github.event_name == 'workflow_dispatch' && inputs.container_name) || 'quarto-linux' }}
CONTAINER_TAG: ${{ (github.event_name == 'workflow_dispatch' && inputs.container_tag) || 'latest' }}
# Container Build Configuration
PLATFORM: linux/amd64
DOCKERFILE_PATH: ./docker/linux/Dockerfile
CONTEXT_PATH: .
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 90 # 1.5 hour timeout for Linux builds
permissions:
contents: read
packages: write
outputs:
build-status: ${{ steps.build-summary.outputs.build-status }}
image-name: ${{ steps.build-summary.outputs.image-name }}
image-digest: ${{ steps.build-summary.outputs.image-digest }}
cache-hit: ${{ steps.build-summary.outputs.cache-hit }}
steps:
- name: 🔍 Check workflow environment
run: |
set -euo pipefail # Exit immediately on any error
echo "🔍 Checking workflow environment..."
echo "📊 Repository: ${{ github.repository }}"
echo "📊 Actor: ${{ github.actor }}"
echo "📊 Event: ${{ github.event_name }}"
echo "📊 Ref: ${{ github.ref }}"
echo "📊 SHA: ${{ github.sha }}"
echo "📊 Workflow: ${{ github.workflow }}"
echo "📊 Run ID: ${{ github.run_id }}"
echo "📊 Run Number: ${{ github.run_number }}"
# Check if we have the required permissions
echo "🔍 Checking permissions..."
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "✅ Manual workflow dispatch - should have full permissions"
elif [ "${{ github.event_name }}" = "push" ]; then
echo "✅ Push event - should have full permissions"
elif [ "${{ github.event_name }}" = "schedule" ]; then
echo "✅ Scheduled event - should have full permissions"
else
echo "⚠️ Unknown event type: ${{ github.event_name }}"
fi
# Check if secrets are available
echo "🔍 Checking secrets availability..."
if [ -n "${{ secrets.GITHUB_TOKEN }}" ]; then
echo "✅ GITHUB_TOKEN is available"
else
echo "❌ GITHUB_TOKEN is not available"
exit 1
fi
echo "✅ Environment check completed"
- name: 📥 Checkout repository
uses: actions/checkout@v4
- name: 🧹 Free up disk space
run: |
echo "🧹 Freeing up disk space for large container build..."
echo "📊 Disk space before cleanup:"
df -h /
# Remove unnecessary packages and files
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker system prune -af
echo "📊 Disk space after cleanup:"
df -h /
echo "✅ Disk cleanup complete"
- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
driver-opts: |
network=host
buildkitd-flags: |
--allow-insecure-entitlement security.insecure
--allow-insecure-entitlement network.host
buildkitd-config-inline: |
[worker.oci]
max-parallelism = 1
[registry."docker.io"]
mirrors = ["mirror.gcr.io"]
- name: 🔍 Verify Buildx Builder
run: |
echo "🔍 Checking buildx builder status..."
docker buildx ls
echo "🔍 Inspecting builder..."
docker buildx inspect --bootstrap
echo "✅ Buildx builder ready"
- name: 🔐 Log in to Container Registry
id: login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🔍 Check registry access
run: |
set -euo pipefail # Exit immediately on any error
echo "🔍 Checking container registry access..."
echo "📊 Registry: ${{ env.REGISTRY }}"
echo "📊 Repository: ${{ github.repository }}"
echo "📊 Actor: ${{ github.actor }}"
echo "📊 Event: ${{ github.event_name }}"
# Test if we can access the registry
echo "🔍 Testing Docker daemon access..."
if docker info >/dev/null 2>&1; then
echo "✅ Docker daemon is accessible"
else
echo "❌ Docker daemon not accessible"
exit 1
fi
# Test registry login with detailed error checking
echo "🔍 Testing container registry login..."
if echo "${{ secrets.GITHUB_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin; then
echo "✅ Successfully logged into container registry"
else
echo "❌ Failed to log into container registry"
echo "🔍 This could be due to:"
echo " - Missing GITHUB_TOKEN secret"
echo " - Insufficient permissions"
echo " - Registry access issues"
echo "🔍 Checking GITHUB_TOKEN availability..."
if [ -n "${{ secrets.GITHUB_TOKEN }}" ]; then
echo "✅ GITHUB_TOKEN is available"
else
echo "❌ GITHUB_TOKEN is empty or not available"
fi
exit 1
fi
# Verify we can actually push to the registry
echo "🔍 Testing registry write permissions..."
TEST_IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/test-push:latest"
if docker pull hello-world:latest >/dev/null 2>&1; then
if docker tag hello-world:latest $TEST_IMAGE >/dev/null 2>&1; then
if docker push $TEST_IMAGE >/dev/null 2>&1; then
echo "✅ Registry write permissions confirmed"
# Clean up test image
docker rmi $TEST_IMAGE >/dev/null 2>&1 || true
else
echo "❌ Registry write permissions failed"
exit 1
fi
else
echo "❌ Failed to tag test image"
exit 1
fi
else
echo "❌ Failed to pull hello-world image for testing"
exit 1
fi
- name: 🏷️ Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ env.CONTAINER_TAG }}
- name: 🐳 Build Linux container
id: build
uses: docker/build-push-action@v5
with:
context: ${{ env.CONTEXT_PATH }}
file: ${{ env.DOCKERFILE_PATH }}
load: true # Keep local copy for testing
push: true # Also push to registry
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
no-cache: ${{ github.event_name == 'workflow_dispatch' && inputs.no_cache || false }} # Use cache unless explicitly disabled
platforms: ${{ env.PLATFORM }}
provenance: false # Disable provenance for better compatibility
sbom: false # Disable SBOM for better compatibility
cache-from: ${{ (github.event_name != 'workflow_dispatch' || !inputs.no_cache) && 'type=gha' || '' }}
cache-to: ${{ (github.event_name != 'workflow_dispatch' || !inputs.no_cache) && 'type=gha,mode=max' || '' }}
outputs: type=docker
- name: Build Complete
run: |
echo "✅ Linux container build completed successfully!"
echo "📊 Container: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.CONTAINER_TAG }}"
- name: 📊 Build Summary
id: build-summary
if: always()
run: |
# Determine build status
if [ "${{ steps.build.outcome }}" = "success" ]; then
BUILD_STATUS="success"
else
BUILD_STATUS="failure"
fi
# Extract build information
IMAGE_NAME="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.CONTAINER_TAG }}"
IMAGE_DIGEST="${{ steps.build.outputs.digest }}"
CACHE_HIT="${{ steps.build.outputs.cache-hit }}"
echo "build-status=$BUILD_STATUS" >> $GITHUB_OUTPUT
echo "image-name=$IMAGE_NAME" >> $GITHUB_OUTPUT
echo "image-digest=$IMAGE_DIGEST" >> $GITHUB_OUTPUT
echo "cache-hit=$CACHE_HIT" >> $GITHUB_OUTPUT
echo "📊 Build Status: $BUILD_STATUS"
echo "🐳 Image: $IMAGE_NAME"
echo "🔍 Digest: $IMAGE_DIGEST"
echo "💾 Cache Hit: $CACHE_HIT"