mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-04-30 01:29:07 -05:00
Add separator and action-specific emojis to make it easier to visually distinguish between workflow types (Build/Publish/Validate) at a glance. Pattern: Category emoji + Name · Action emoji + Action - 🔨 Build - 📤 Publish - 🔍 Validate - 🐳 Container - 🧹 Cleanup - 🔗 Link Check - ❤️ Health Check
246 lines
8.4 KiB
YAML
246 lines
8.4 KiB
YAML
name: '🔧 Infra · 🐳 Container (Windows)'
|
|
|
|
# This workflow builds the Windows Quarto build container
|
|
# Windows containers are more complex but provide performance benefits
|
|
|
|
# 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-windows'
|
|
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-windows'
|
|
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 2 * * 0' # Weekly rebuild (Sunday at 2am - after Linux container)
|
|
push:
|
|
branches: [dev] # Only trigger on dev branch, not main
|
|
paths:
|
|
- 'book/tools/dependencies/**'
|
|
- 'book/docker/windows/**'
|
|
- '.github/workflows/book-build-windows-container.yml'
|
|
|
|
env:
|
|
# =============================================================================
|
|
# PATH CONFIGURATION - Uses GitHub Repository Variables (Settings > Variables)
|
|
# =============================================================================
|
|
# MLSysBook content lives under book/ to accommodate TinyTorch at root
|
|
# Use ${{ vars.BOOK_ROOT }}, ${{ vars.BOOK_DOCKER }}, etc. in workflow steps
|
|
# Variables: BOOK_ROOT, BOOK_DOCKER, BOOK_TOOLS, BOOK_QUARTO, BOOK_DEPS
|
|
|
|
# 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-windows' }}
|
|
CONTAINER_TAG: ${{ (github.event_name == 'workflow_dispatch' && inputs.container_tag) || 'latest' }}
|
|
|
|
# Container Build Configuration
|
|
# Using vars.BOOK_DOCKER (repository variable) - works in all contexts
|
|
DOCKERFILE_PATH: ./${{ vars.BOOK_DOCKER }}/windows/Dockerfile
|
|
CONTEXT_PATH: .
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: windows-latest
|
|
if: github.repository_owner == 'harvard-edge'
|
|
timeout-minutes: 180 # takes about 2 hours to build on Windows
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
outputs:
|
|
build-status: ${{ steps.build.outputs.build-status }}
|
|
image-name: ${{ steps.build.outputs.image-name }}
|
|
image-digest: ${{ steps.build.outputs.image-digest }}
|
|
cache-hit: ${{ steps.build.outputs.cache-hit }}
|
|
|
|
steps:
|
|
- name: 📥 Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
# Skip Docker Buildx for Windows containers - use native Docker engine
|
|
# Buildx doesn't properly support Windows containers on GitHub Actions
|
|
# - 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
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
tags: |
|
|
type=raw,value=${{ env.CONTAINER_TAG }}
|
|
|
|
- name: 🐳 Build and Push Windows container
|
|
id: build
|
|
shell: pwsh
|
|
# Use native Docker instead of book/docker/build-push-action for Windows containers
|
|
# Buildx has compatibility issues with Windows containers on GitHub Actions
|
|
run: |
|
|
# Extract image name and tag from metadata
|
|
$IMAGE_TAG = "${{ steps.meta.outputs.tags }}"
|
|
$NO_CACHE = "${{ github.event_name == 'workflow_dispatch' && inputs.no_cache || false }}"
|
|
|
|
Write-Host "🔨 Building Windows container..."
|
|
Write-Host "📊 Image: $IMAGE_TAG"
|
|
Write-Host "📊 Context: ${{ env.CONTEXT_PATH }}"
|
|
Write-Host "📊 Dockerfile: ${{ env.DOCKERFILE_PATH }}"
|
|
Write-Host "📊 No Cache: $NO_CACHE"
|
|
|
|
# Build the container using native Docker
|
|
$buildArgs = @(
|
|
"build",
|
|
"--file", "${{ env.DOCKERFILE_PATH }}",
|
|
"--tag", $IMAGE_TAG
|
|
)
|
|
|
|
# Add no-cache flag if requested
|
|
if ($NO_CACHE -eq "true") {
|
|
$buildArgs += "--no-cache"
|
|
Write-Host "🚫 Cache disabled - building from scratch"
|
|
} else {
|
|
Write-Host "💾 Using Docker cache"
|
|
}
|
|
|
|
# Add labels from metadata
|
|
$labels = "${{ steps.meta.outputs.labels }}"
|
|
if ($labels) {
|
|
$labels -split "`n" | ForEach-Object {
|
|
if ($_.Trim()) {
|
|
$buildArgs += "--label", $_.Trim()
|
|
}
|
|
}
|
|
}
|
|
|
|
# Add context path
|
|
$buildArgs += "${{ env.CONTEXT_PATH }}"
|
|
|
|
Write-Host "🔨 Running: docker $($buildArgs -join ' ')"
|
|
& docker @buildArgs
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Host "❌ Docker build failed with exit code $LASTEXITCODE"
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
Write-Host "✅ Build completed successfully"
|
|
|
|
# Push the container
|
|
Write-Host "📤 Pushing container to registry..."
|
|
& docker push $IMAGE_TAG
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Host "❌ Docker push failed with exit code $LASTEXITCODE"
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
Write-Host "✅ Push completed successfully"
|
|
|
|
# Get image digest for output
|
|
$DIGEST = & docker inspect --format='{{index .RepoDigests 0}}' $IMAGE_TAG 2>$null
|
|
if ($DIGEST -match '@(.+)$') {
|
|
$DIGEST = $matches[1]
|
|
} else {
|
|
$DIGEST = "unknown"
|
|
}
|
|
|
|
# Set outputs for build summary
|
|
"digest=$DIGEST" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
"cache-hit=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
|
|
- name: 📊 Build Summary
|
|
id: build-summary
|
|
if: always()
|
|
shell: pwsh
|
|
run: |
|
|
# Determine build status
|
|
if ("${{ steps.build.outcome }}" -eq "success") {
|
|
$BUILD_STATUS = "success"
|
|
} else {
|
|
$BUILD_STATUS = "failure"
|
|
}
|
|
|
|
# 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 }}"
|
|
|
|
"build-status=$BUILD_STATUS" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
"image-name=$IMAGE_NAME" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
"image-digest=$IMAGE_DIGEST" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
"cache-hit=$CACHE_HIT" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
|
|
Write-Host "📊 Build Status: $BUILD_STATUS"
|
|
Write-Host "🐳 Image: $IMAGE_NAME"
|
|
Write-Host "🔍 Digest: $IMAGE_DIGEST"
|
|
Write-Host "💾 Cache Hit: $CACHE_HIT"
|