Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
14149ff
SCALRCORE-38392 update tools:
mermoldy May 12, 2026
64daa8b
SCALRCORE-38392 update software versions; add checksums verification …
mermoldy May 13, 2026
4c71ee9
SCALRCORE-38392 pin debian base via versions file
mermoldy May 13, 2026
76a1b70
SCALRCORE-38392 use docker-backe for build matrix
mermoldy May 25, 2026
f08e62c
SCALRCORE-38392 bump versions
mermoldy May 25, 2026
a802126
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
6ff8013
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
f86d008
SCALRCORE-38392 bump versions
mermoldy May 25, 2026
de814b0
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
09d6f7f
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
1437793
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
36123bf
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
a88e888
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
00dfa59
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
3df580d
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
8733a20
SCALRCORE-38392 add workflow to publish gar images
mermoldy May 25, 2026
2ccfc67
SCALRCORE-38392 setup GAR build pipeline
mermoldy May 25, 2026
f1ad382
SCALRCORE-38392 setup GAR build pipeline
mermoldy May 25, 2026
58879b2
SCALRCORE-38392 pin older gloud 564.0.0 for python39 image
mermoldy May 25, 2026
efcea23
SCALRCORE-38392 updated readme
mermoldy May 25, 2026
24a7b05
SCALRCORE-38392 setup GAR build pipeline
mermoldy May 25, 2026
b48b81c
SCALRCORE-38392 setup GAR build pipeline
mermoldy May 25, 2026
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
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Default-deny: ignore everything, then re-include only what the build needs.
# The Dockerfile currently uses no COPY/ADD, so the build context can be empty.
*

# Keep Dockerfile itself accessible to buildx.
!Dockerfile
69 changes: 25 additions & 44 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,24 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Read Versions
id: versions
run: |
echo "kubectl=$(grep '^kubectl=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "gcloud=$(grep '^gcloud=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "aws_cli=$(grep '^aws_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "azure_cli=$(grep '^azure_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "scalr_cli=$(grep '^scalr_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "python=$(grep '^python=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "python_release=$(grep '^python_release=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT

- name: Build Docker image
uses: docker/build-push-action@v6
# Build all variants single-arch so they can be loaded locally and smoke-tested.
- name: Build images
uses: docker/bake-action@v5
with:
build-args: |
KUBECTL_VERSION=${{ steps.versions.outputs.kubectl }}
GCLOUD_VERSION=${{ steps.versions.outputs.gcloud }}
AWS_CLI_VERSION=${{ steps.versions.outputs.aws_cli }}
AZURE_CLI_VERSION=${{ steps.versions.outputs.azure_cli }}
SCALR_CLI_VERSION=${{ steps.versions.outputs.scalr_cli }}
PYTHON_VERSION=${{ steps.versions.outputs.python }}
PYTHON_RELEASE=${{ steps.versions.outputs.python_release }}
cache-from: type=registry,ref=scalr/runner:buildcache
cache-to: type=registry,ref=scalr/runner:buildcache
files: |
docker-bake.hcl
versions.json
load: true
tags: |
scalr/runner:sha-${{ github.sha }}
set: |
*.platform=linux/amd64
full.tags=scalr/runner:sha-${{ github.sha }}
python39.tags=scalr/runner:sha-${{ github.sha }}-python39
slim.tags=scalr/runner:sha-${{ github.sha }}-slim
full.cache-to=type=registry,ref=scalr/runner:buildcache,mode=max
python39.cache-to=type=registry,ref=scalr/runner:buildcache-python39,mode=max
slim.cache-to=type=registry,ref=scalr/runner:buildcache-slim,mode=max

- name: Test Docker Image
- name: Test full image
run: |
docker run --rm scalr/runner:sha-${{ github.sha }} -xc 'gcloud version'
docker run --rm scalr/runner:sha-${{ github.sha }} -xc 'aws --version'
Expand All @@ -68,25 +57,17 @@ jobs:
docker run --rm scalr/runner:sha-${{ github.sha }} -xc 'pip --version'
docker run --rm scalr/runner:sha-${{ github.sha }} -xc 'pip install requests'

- name: Build Docker image (Python 3.9)
uses: docker/build-push-action@v6
with:
build-args: |
KUBECTL_VERSION=${{ steps.versions.outputs.kubectl }}
GCLOUD_VERSION=${{ steps.versions.outputs.gcloud }}
AWS_CLI_VERSION=${{ steps.versions.outputs.aws_cli }}
AZURE_CLI_VERSION=${{ steps.versions.outputs.azure_cli }}
SCALR_CLI_VERSION=${{ steps.versions.outputs.scalr_cli }}
PYTHON_VERSION=3.9.25
PYTHON_RELEASE=20251031
cache-from: type=registry,ref=scalr/runner:buildcache-python39
cache-to: type=registry,ref=scalr/runner:buildcache-python39
load: true
tags: |
scalr/runner:sha-${{ github.sha }}-python39

- name: Test Docker Image (Python 3.9)
- name: Test python39 image
run: |
docker run --rm scalr/runner:sha-${{ github.sha }}-python39 -xc 'python --version'
docker run --rm scalr/runner:sha-${{ github.sha }}-python39 -xc 'pip --version'
docker run --rm scalr/runner:sha-${{ github.sha }}-python39 -xc 'pip install requests'

- name: Test slim image
run: |
docker run --rm scalr/runner:sha-${{ github.sha }}-slim -xc 'git --version'
docker run --rm scalr/runner:sha-${{ github.sha }}-slim -xc 'curl --version'
docker run --rm scalr/runner:sha-${{ github.sha }}-slim -xc 'jq --version'
# Confirm python and cloud tools are absent.
docker run --rm scalr/runner:sha-${{ github.sha }}-slim -xc '! command -v python'
docker run --rm scalr/runner:sha-${{ github.sha }}-slim -xc '! command -v aws'
131 changes: 131 additions & 0 deletions .github/workflows/build_and_release_gar.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
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"
146 changes: 101 additions & 45 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ on:
tags:
- "*.*.*"

permissions:
# Needed by the update_changelog job to git-push CHANGELOG.md back to main.
contents: write
# Required by google-github-actions/auth for workload identity federation.
id-token: write

jobs:
build:
name: Build and Push
Expand All @@ -19,65 +25,115 @@ jobs:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

# Authenticate to Google Artifact Registry (GAR) so the same build can be
# mirrored to the internal Scalr registry alongside Docker Hub.
- 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: Login to GAR (US prod)
uses: docker/login-action@v3
with:
registry: ${{ vars.US_PROD_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

- name: Read Versions
id: versions
run: |
echo "kubectl=$(grep '^kubectl=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "gcloud=$(grep '^gcloud=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "aws_cli=$(grep '^aws_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "azure_cli=$(grep '^azure_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "scalr_cli=$(grep '^scalr_cli=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "python=$(grep '^python=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT
echo "python_release=$(grep '^python_release=' versions | cut -d= -f2)" | tee -a $GITHUB_OUTPUT

- name: Format Image Tag
id: image_tag
run: |
echo "tag=${GITHUB_REF#refs/tags/}" | tee -a $GITHUB_OUTPUT

- name: Build Docker image
uses: docker/build-push-action@v6
with:
build-args: |
KUBECTL_VERSION=${{ steps.versions.outputs.kubectl }}
GCLOUD_VERSION=${{ steps.versions.outputs.gcloud }}
AWS_CLI_VERSION=${{ steps.versions.outputs.aws_cli }}
AZURE_CLI_VERSION=${{ steps.versions.outputs.azure_cli }}
SCALR_CLI_VERSION=${{ steps.versions.outputs.scalr_cli }}
PYTHON_VERSION=${{ steps.versions.outputs.python }}
PYTHON_RELEASE=${{ steps.versions.outputs.python_release }}
platforms: linux/amd64,linux/arm64
cache-from: type=registry,ref=scalr/runner:buildcache
cache-to: type=registry,ref=scalr/runner:buildcache
push: true
tags: |
scalr/runner:latest
scalr/runner:${{ steps.image_tag.outputs.tag }}
# Two regional GAR mirrors — EU dev and US production.
- name: Compose GAR image paths
id: gar
run: |
echo "image_eu=${{ vars.EU_DEV_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.EU_DEV_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT
echo "image_us=${{ vars.US_PROD_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.US_PROD_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT

- name: Build Docker image (Python 3.9)
uses: docker/build-push-action@v6
- name: Build and push images
uses: docker/bake-action@v5
env:
VERSION: ${{ steps.image_tag.outputs.tag }}
with:
build-args: |
KUBECTL_VERSION=${{ steps.versions.outputs.kubectl }}
GCLOUD_VERSION=${{ steps.versions.outputs.gcloud }}
AWS_CLI_VERSION=${{ steps.versions.outputs.aws_cli }}
AZURE_CLI_VERSION=${{ steps.versions.outputs.azure_cli }}
SCALR_CLI_VERSION=${{ steps.versions.outputs.scalr_cli }}
PYTHON_VERSION=3.9.25
PYTHON_RELEASE=20251031
platforms: linux/amd64,linux/arm64
cache-from: type=registry,ref=scalr/runner:buildcache-python39
cache-to: type=registry,ref=scalr/runner:buildcache-python39
files: |
docker-bake.hcl
versions.json
push: true
tags: |
scalr/runner:latest-python39
scalr/runner:${{ steps.image_tag.outputs.tag }}-python39
# Append both GAR region tags to each target so a single push writes
# to Docker Hub (declared in docker-bake.hcl) and both regional GAR
# mirrors. Cache-to is injected here because the docker-container
# driver supports it, while the bake file stays local-driver-friendly.
set: |
full.tags+=${{ steps.gar.outputs.image_eu }}:${{ steps.image_tag.outputs.tag }}
full.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }}
python39.tags+=${{ steps.gar.outputs.image_eu }}:${{ steps.image_tag.outputs.tag }}-python39
python39.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }}-python39
slim.tags+=${{ steps.gar.outputs.image_eu }}:${{ steps.image_tag.outputs.tag }}-slim
slim.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }}-slim
full.cache-to=type=registry,ref=scalr/runner:buildcache,mode=max
python39.cache-to=type=registry,ref=scalr/runner:buildcache-python39,mode=max
slim.cache-to=type=registry,ref=scalr/runner:buildcache-slim,mode=max

- name: Report published images
env:
TAG: ${{ steps.image_tag.outputs.tag }}
IMG_EU: ${{ steps.gar.outputs.image_eu }}
IMG_US: ${{ steps.gar.outputs.image_us }}
run: |
echo "Published runner images for release ${TAG}"
echo ""
echo "Docker Hub:"
echo " scalr/runner:${TAG}"
echo " scalr/runner:${TAG}-python39"
echo " scalr/runner:${TAG}-slim"
echo ""
echo "GAR — EU dev:"
echo " ${IMG_EU}:${TAG}"
echo " ${IMG_EU}:${TAG}-python39"
echo " ${IMG_EU}:${TAG}-slim"
echo ""
echo "GAR — US prod:"
echo " ${IMG_US}:${TAG}"
echo " ${IMG_US}:${TAG}-python39"
echo " ${IMG_US}:${TAG}-slim"
{
echo "## Published runner images — \`${TAG}\`"
echo ""
echo "**Docker Hub**"
echo ""
echo "- \`scalr/runner:${TAG}\`"
echo "- \`scalr/runner:${TAG}-python39\`"
echo "- \`scalr/runner:${TAG}-slim\`"
echo ""
echo "**GAR — EU dev**"
echo ""
echo "- \`${IMG_EU}:${TAG}\`"
echo "- \`${IMG_EU}:${TAG}-python39\`"
echo "- \`${IMG_EU}:${TAG}-slim\`"
echo ""
echo "**GAR — US prod**"
echo ""
echo "- \`${IMG_US}:${TAG}\`"
echo "- \`${IMG_US}:${TAG}-python39\`"
echo "- \`${IMG_US}:${TAG}-slim\`"
} >> "$GITHUB_STEP_SUMMARY"

update_changelog:
name: Update Changelog
Expand Down
Loading
Loading