π§ Infra Β· π³ Container (Windows) #54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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@v6 | |
| # 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" |