SCALRCORE-38942 #44
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: Build and Release Runner Image (EU dev GAR) | |
| # Triggered when a PR carries the `build-gar-images` label. Pushes test | |
| # builds of all three variants to the EU dev GAR mirror only — Docker | |
| # Hub and the US production mirror are never touched here (production | |
| # is reserved for the release.yaml workflow). | |
| # | |
| # Tags are derived from the PR source branch, lower-cased and prefixed | |
| # with `branch-` so they cannot collide with the semver release tags | |
| # produced by release.yaml. Example: branch `0.2.0` → `branch-0.2.0`, | |
| # not `0.2.0`. This prevents a PR from a maliciously-named branch from | |
| # overwriting an existing release image. | |
| on: | |
| pull_request: | |
| types: [labeled, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| # Required by google-github-actions/auth for workload identity federation. | |
| id-token: write | |
| jobs: | |
| build: | |
| name: Build and Push to GAR (EU dev) | |
| if: contains(github.event.pull_request.labels.*.name, 'build-gar-images') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Defense-in-depth: refuse to build on behalf of senders without | |
| # write-or-better access on this repo. Covers two paths: | |
| # - `labeled` event: the user who added the label must be trusted. | |
| # - `synchronize` event: the user who pushed must be trusted. | |
| # GitHub already strips secrets/vars for `pull_request` runs from | |
| # forks, so this is layered on top of that built-in protection. | |
| - name: Verify sender authorization | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ACTOR: ${{ github.event.sender.login }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| role=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" --jq .permission) | |
| case "$role" in | |
| admin|maintain|write) echo "OK: ${ACTOR} has ${role} on ${REPO}";; | |
| *) echo "::error::Sender ${ACTOR} has '${role}' permission; needs write or higher"; exit 1;; | |
| esac | |
| - name: Authenticate to Google Cloud | |
| id: gcp-auth | |
| uses: google-github-actions/auth@v3 | |
| with: | |
| workload_identity_provider: ${{vars.GOOGLE_WORKLOAD_IDENTITY_POOL_PROVIDER}} | |
| service_account: ${{vars.GOOGLE_SERVICE_ACCOUNT_EMAIL}} | |
| token_format: access_token | |
| - name: Login to GAR (EU dev) | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ vars.EU_DEV_MIRROR_LOCATION }}-docker.pkg.dev | |
| username: oauth2accesstoken | |
| password: ${{ steps.gcp-auth.outputs.access_token }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| # PR source branch → Docker tag. Lower-cased (downstream agents | |
| # lower-case image refs), slashes → dashes (illegal in tags), and | |
| # prefixed with `branch-` so the tag can never collide with a | |
| # semver release tag pushed by release.yaml. | |
| - name: Resolve branch tag | |
| id: branch | |
| run: | | |
| raw='${{ github.head_ref }}' | |
| sanitized="${raw,,}" | |
| sanitized="${sanitized//\//-}" | |
| echo "tag=branch-${sanitized}" | tee -a $GITHUB_OUTPUT | |
| - name: Compose GAR image path | |
| id: gar | |
| run: | | |
| echo "image=${{ vars.EU_DEV_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.EU_DEV_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT | |
| - name: Build and push images | |
| uses: docker/bake-action@v5 | |
| env: | |
| VERSION: ${{ steps.branch.outputs.tag }} | |
| with: | |
| files: | | |
| docker-bake.hcl | |
| versions.json | |
| push: true | |
| # Replace each target's tag list (`tags=` removes the Docker Hub | |
| # default from docker-bake.hcl) so the build pushes only to the EU | |
| # dev GAR mirror, which also holds the per-branch buildcache. | |
| set: | | |
| full.tags=${{ steps.gar.outputs.image }}:${{ steps.branch.outputs.tag }} | |
| python39.tags=${{ steps.gar.outputs.image }}:${{ steps.branch.outputs.tag }}-python39 | |
| slim.tags=${{ steps.gar.outputs.image }}:${{ steps.branch.outputs.tag }}-slim | |
| full.cache-from=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }} | |
| python39.cache-from=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }}-python39 | |
| slim.cache-from=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }}-slim | |
| full.cache-to=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }},mode=max | |
| python39.cache-to=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }}-python39,mode=max | |
| slim.cache-to=type=registry,ref=${{ steps.gar.outputs.image }}:buildcache-${{ steps.branch.outputs.tag }}-slim,mode=max | |
| - name: Report published images | |
| env: | |
| BRANCH: ${{ github.head_ref }} | |
| TAG: ${{ steps.branch.outputs.tag }} | |
| IMG: ${{ steps.gar.outputs.image }} | |
| run: | | |
| echo "Published GAR (EU dev) images for branch ${BRANCH}" | |
| echo "" | |
| echo " ${IMG}:${TAG}" | |
| echo " ${IMG}:${TAG}-python39" | |
| echo " ${IMG}:${TAG}-slim" | |
| { | |
| echo "## Published runner images — branch \`${BRANCH}\`" | |
| echo "" | |
| echo "**GAR — EU dev**" | |
| echo "" | |
| echo "- \`${IMG}:${TAG}\`" | |
| echo "- \`${IMG}:${TAG}-python39\`" | |
| echo "- \`${IMG}:${TAG}-slim\`" | |
| } >> "$GITHUB_STEP_SUMMARY" |