diff --git a/.github/workflows/build_and_release_gar.yaml b/.github/workflows/build_and_release_gar.yaml index d1a7186..8ed9710 100644 --- a/.github/workflows/build_and_release_gar.yaml +++ b/.github/workflows/build_and_release_gar.yaml @@ -1,4 +1,4 @@ -name: Build and Release Runner Image (EU dev GAR) +name: Dev Runner Image # 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 @@ -22,7 +22,7 @@ permissions: jobs: build: - name: Build and Push to GAR (EU dev) + name: Build and Push if: contains(github.event.pull_request.labels.*.name, 'build-gar-images') runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 507ca27..88331f5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -42,6 +42,13 @@ jobs: username: oauth2accesstoken password: ${{ steps.gcp-auth.outputs.access_token }} + - name: Login to GAR (EU stage) + uses: docker/login-action@v3 + with: + registry: ${{ vars.EU_STAGE_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: @@ -55,17 +62,18 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Format Image Tag + - name: Format image tag id: image_tag run: | echo "tag=${GITHUB_REF#refs/tags/}" | tee -a $GITHUB_OUTPUT - # Two regional GAR mirrors — EU dev and US production. + # Three GAR mirrors — EU dev, EU stage 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 + echo "image_eu_dev=${{ vars.EU_DEV_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.EU_DEV_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT + echo "image_eu_stage=${{ vars.EU_STAGE_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.EU_STAGE_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT + echo "image_us_prod=${{ vars.US_PROD_MIRROR_LOCATION }}-docker.pkg.dev/${{ vars.US_PROD_GOOGLE_PROJECT }}/main/scalr/runner" | tee -a $GITHUB_OUTPUT - name: Build and push images uses: docker/bake-action@v5 @@ -76,25 +84,31 @@ jobs: docker-bake.hcl versions.json push: true - # 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. Both GAR mirrors additionally get a `v`-prefixed alias + # Append all GAR mirror tags to each target so a single push writes + # to Docker Hub (declared in docker-bake.hcl) and every GAR mirror. + # All GAR mirrors additionally get a `v`-prefixed alias # (e.g. `v0.4.2`) so GAR cleanup policies can filter release tags # by prefix. Cache uses GitHub Actions cache (per-repo, private) so # nothing cache-related leaks into the public Docker Hub repo. set: | - full.tags+=${{ steps.gar.outputs.image_eu }}:${{ steps.image_tag.outputs.tag }} - full.tags+=${{ steps.gar.outputs.image_eu }}:v${{ steps.image_tag.outputs.tag }} - full.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }} - full.tags+=${{ steps.gar.outputs.image_us }}:v${{ steps.image_tag.outputs.tag }} - python39.tags+=${{ steps.gar.outputs.image_eu }}:${{ steps.image_tag.outputs.tag }}-python39 - python39.tags+=${{ steps.gar.outputs.image_eu }}:v${{ steps.image_tag.outputs.tag }}-python39 - python39.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }}-python39 - python39.tags+=${{ steps.gar.outputs.image_us }}:v${{ 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_eu }}:v${{ steps.image_tag.outputs.tag }}-slim - slim.tags+=${{ steps.gar.outputs.image_us }}:${{ steps.image_tag.outputs.tag }}-slim - slim.tags+=${{ steps.gar.outputs.image_us }}:v${{ steps.image_tag.outputs.tag }}-slim + full.tags+=${{ steps.gar.outputs.image_eu_dev }}:${{ steps.image_tag.outputs.tag }} + full.tags+=${{ steps.gar.outputs.image_eu_dev }}:v${{ steps.image_tag.outputs.tag }} + full.tags+=${{ steps.gar.outputs.image_eu_stage }}:${{ steps.image_tag.outputs.tag }} + full.tags+=${{ steps.gar.outputs.image_eu_stage }}:v${{ steps.image_tag.outputs.tag }} + full.tags+=${{ steps.gar.outputs.image_us_prod }}:${{ steps.image_tag.outputs.tag }} + full.tags+=${{ steps.gar.outputs.image_us_prod }}:v${{ steps.image_tag.outputs.tag }} + python39.tags+=${{ steps.gar.outputs.image_eu_dev }}:${{ steps.image_tag.outputs.tag }}-python39 + python39.tags+=${{ steps.gar.outputs.image_eu_dev }}:v${{ steps.image_tag.outputs.tag }}-python39 + python39.tags+=${{ steps.gar.outputs.image_eu_stage }}:${{ steps.image_tag.outputs.tag }}-python39 + python39.tags+=${{ steps.gar.outputs.image_eu_stage }}:v${{ steps.image_tag.outputs.tag }}-python39 + python39.tags+=${{ steps.gar.outputs.image_us_prod }}:${{ steps.image_tag.outputs.tag }}-python39 + python39.tags+=${{ steps.gar.outputs.image_us_prod }}:v${{ steps.image_tag.outputs.tag }}-python39 + slim.tags+=${{ steps.gar.outputs.image_eu_dev }}:${{ steps.image_tag.outputs.tag }}-slim + slim.tags+=${{ steps.gar.outputs.image_eu_dev }}:v${{ steps.image_tag.outputs.tag }}-slim + slim.tags+=${{ steps.gar.outputs.image_eu_stage }}:${{ steps.image_tag.outputs.tag }}-slim + slim.tags+=${{ steps.gar.outputs.image_eu_stage }}:v${{ steps.image_tag.outputs.tag }}-slim + slim.tags+=${{ steps.gar.outputs.image_us_prod }}:${{ steps.image_tag.outputs.tag }}-slim + slim.tags+=${{ steps.gar.outputs.image_us_prod }}:v${{ steps.image_tag.outputs.tag }}-slim full.cache-from=type=gha,scope=full full.cache-to=type=gha,scope=full,mode=max python39.cache-from=type=gha,scope=python39 @@ -105,8 +119,9 @@ jobs: - 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 }} + IMG_EU_DEV: ${{ steps.gar.outputs.image_eu_dev }} + IMG_EU_STAGE: ${{ steps.gar.outputs.image_eu_stage }} + IMG_US_PROD: ${{ steps.gar.outputs.image_us_prod }} run: | echo "Published runner images for release ${TAG}" echo "" @@ -116,20 +131,28 @@ jobs: 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 " ${IMG_EU}:v${TAG}" - echo " ${IMG_EU}:v${TAG}-python39" - echo " ${IMG_EU}:v${TAG}-slim" + echo " ${IMG_EU_DEV}:${TAG}" + echo " ${IMG_EU_DEV}:${TAG}-python39" + echo " ${IMG_EU_DEV}:${TAG}-slim" + echo " ${IMG_EU_DEV}:v${TAG}" + echo " ${IMG_EU_DEV}:v${TAG}-python39" + echo " ${IMG_EU_DEV}:v${TAG}-slim" + echo "" + echo "GAR — EU stage:" + echo " ${IMG_EU_STAGE}:${TAG}" + echo " ${IMG_EU_STAGE}:${TAG}-python39" + echo " ${IMG_EU_STAGE}:${TAG}-slim" + echo " ${IMG_EU_STAGE}:v${TAG}" + echo " ${IMG_EU_STAGE}:v${TAG}-python39" + echo " ${IMG_EU_STAGE}:v${TAG}-slim" echo "" echo "GAR — US prod:" - echo " ${IMG_US}:${TAG}" - echo " ${IMG_US}:${TAG}-python39" - echo " ${IMG_US}:${TAG}-slim" - echo " ${IMG_US}:v${TAG}" - echo " ${IMG_US}:v${TAG}-python39" - echo " ${IMG_US}:v${TAG}-slim" + echo " ${IMG_US_PROD}:${TAG}" + echo " ${IMG_US_PROD}:${TAG}-python39" + echo " ${IMG_US_PROD}:${TAG}-slim" + echo " ${IMG_US_PROD}:v${TAG}" + echo " ${IMG_US_PROD}:v${TAG}-python39" + echo " ${IMG_US_PROD}:v${TAG}-slim" { echo "## Published runner images — \`${TAG}\`" echo "" @@ -141,21 +164,30 @@ jobs: echo "" echo "**GAR — EU dev**" echo "" - echo "- \`${IMG_EU}:${TAG}\`" - echo "- \`${IMG_EU}:${TAG}-python39\`" - echo "- \`${IMG_EU}:${TAG}-slim\`" - echo "- \`${IMG_EU}:v${TAG}\`" - echo "- \`${IMG_EU}:v${TAG}-python39\`" - echo "- \`${IMG_EU}:v${TAG}-slim\`" + echo "- \`${IMG_EU_DEV}:${TAG}\`" + echo "- \`${IMG_EU_DEV}:${TAG}-python39\`" + echo "- \`${IMG_EU_DEV}:${TAG}-slim\`" + echo "- \`${IMG_EU_DEV}:v${TAG}\`" + echo "- \`${IMG_EU_DEV}:v${TAG}-python39\`" + echo "- \`${IMG_EU_DEV}:v${TAG}-slim\`" + echo "" + echo "**GAR — EU stage**" + echo "" + echo "- \`${IMG_EU_STAGE}:${TAG}\`" + echo "- \`${IMG_EU_STAGE}:${TAG}-python39\`" + echo "- \`${IMG_EU_STAGE}:${TAG}-slim\`" + echo "- \`${IMG_EU_STAGE}:v${TAG}\`" + echo "- \`${IMG_EU_STAGE}:v${TAG}-python39\`" + echo "- \`${IMG_EU_STAGE}:v${TAG}-slim\`" echo "" echo "**GAR — US prod**" echo "" - echo "- \`${IMG_US}:${TAG}\`" - echo "- \`${IMG_US}:${TAG}-python39\`" - echo "- \`${IMG_US}:${TAG}-slim\`" - echo "- \`${IMG_US}:v${TAG}\`" - echo "- \`${IMG_US}:v${TAG}-python39\`" - echo "- \`${IMG_US}:v${TAG}-slim\`" + echo "- \`${IMG_US_PROD}:${TAG}\`" + echo "- \`${IMG_US_PROD}:${TAG}-python39\`" + echo "- \`${IMG_US_PROD}:${TAG}-slim\`" + echo "- \`${IMG_US_PROD}:v${TAG}\`" + echo "- \`${IMG_US_PROD}:v${TAG}-python39\`" + echo "- \`${IMG_US_PROD}:v${TAG}-slim\`" } >> "$GITHUB_STEP_SUMMARY" update_changelog: @@ -172,7 +204,7 @@ jobs: with: ruby-version: "3.3" - - name: Install Changelog Generator + - name: Install changelog generator run: gem install github_changelog_generator - name: Update CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 098e234..9c2b550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [0.6.0](https://github.com/Scalr/runner/tree/0.6.0) (Unreleased) + +### Changed +- Updated Python: 3.14.6 → 3.14.8 +- Reverted base image: `ubuntu:26.04` → `debian:trixie-slim` (snapshot `sha256:a29215f6a35e51e22adffa17f89e9d2ef06214e64a2bad10d765c46aea49f11f`). +- Updated CLI tools to latest versions: + - `kubectl`: v1.36.2 → v1.37.1 + - `gcloud`: 575.0.0 → 588.0.0 + - `aws`: 2.35.13 → 2.37.10 + - `azure`: 2.87.0 → 2.91.0 + - `session-manager-plugin`: 1.2.814.0 → 1.2.835.0 + - `git-lfs`: v3.7.1 → v3.8.0 (patched `golang.org/x/crypto` v0.57.0, `golang.org/x/net` v0.59.0, `golang.org/x/sys` v0.48.0) + +[Full Changelog](https://github.com/Scalr/runner/compare/0.5.0...0.6.0) + ## [0.5.0](https://github.com/Scalr/runner/tree/0.5.0) (2026-07-01) ### Changed diff --git a/Dockerfile b/Dockerfile index 914e077..1b5e176 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,12 +9,12 @@ # - full: slim + Python + cloud CLIs + hardening (published as scalr/runner: # and scalr/runner:-python39) # -# UBUNTU_BASE_IMAGE, UBUNTU_BASE_DIGEST and other ARGs are supplied at build +# DEBIAN_BASE_IMAGE, DEBIAN_BASE_DIGEST and other ARGs are supplied at build # time via bake (see docker-bake.hcl + versions.json). The skip directive # above silences BuildKit's check for ARGs in FROM without a default. -ARG UBUNTU_BASE_IMAGE -ARG UBUNTU_BASE_DIGEST +ARG DEBIAN_BASE_IMAGE +ARG DEBIAN_BASE_DIGEST # Custom git-lfs build, we rely on Wolfi's approach from # https://github.com/wolfi-dev/os/blob/main/git-lfs.yaml @@ -22,22 +22,22 @@ FROM golang:tip-bookworm AS git-lfs-build SHELL ["/bin/bash", "-o", "pipefail", "-euxc"] -ARG GIT_LFS_VERSION=v3.7.1 +ARG GIT_LFS_VERSION=v3.8.0 RUN </dev/null || true - # Remove unnecesary files for final build - rm -rf \ - /usr/bin/pebble EOT FROM scratch AS slim diff --git a/README.md b/README.md index 12206d9..b8dd089 100644 --- a/README.md +++ b/README.md @@ -65,13 +65,13 @@ versions below are the current pins (kept in sync with `versions.json` by `bump-versions.py`): * **Programming language** - * Python ([v3.14.6](https://www.python.org/downloads/release/python-3146/)) — [standalone CPython build](https://github.com/astral-sh/python-build-standalone) from [astral.sh](https://astral.sh/) + * Python ([v3.14.8](https://www.python.org/downloads/release/python-3148/)) — [standalone CPython build](https://github.com/astral-sh/python-build-standalone) from [astral.sh](https://astral.sh/) * **Cloud CLIs** - * AWS CLI ([2.35.13](https://github.com/aws/aws-cli/releases/tag/2.35.13)) — Amazon Web Services CLI + * AWS CLI ([2.37.10](https://github.com/aws/aws-cli/releases/tag/2.37.10)) — Amazon Web Services CLI * AWS Session Manager Plugin — SSM session support for the AWS CLI - * Azure CLI ([2.87.0](https://github.com/Azure/azure-cli/releases/tag/azure-cli-2.87.0)) — Microsoft Azure CLI - * Google Cloud SDK ([575.0.0](https://cloud.google.com/sdk/docs/release-notes#57500)) — `gcloud` with `alpha`, `beta`, and `gke-gcloud-auth-plugin` components - * Kubectl ([0.36.2](https://github.com/kubernetes/kubectl/releases/tag/v0.36.2)) — Kubernetes CLI + * Azure CLI ([2.91.0](https://github.com/Azure/azure-cli/releases/tag/azure-cli-2.91.0)) — Microsoft Azure CLI + * Google Cloud SDK ([588.0.0](https://cloud.google.com/sdk/docs/release-notes#58800)) — `gcloud` with `alpha`, `beta`, and `gke-gcloud-auth-plugin` components + * Kubectl ([0.37.1](https://github.com/kubernetes/kubectl/releases/tag/v0.37.1)) — Kubernetes CLI * Scalr CLI ([0.18.0](https://github.com/Scalr/scalr-cli/releases/tag/v0.18.0)) — command-line client for the Scalr API ### Added in the `-python39` image diff --git a/bump-versions.py b/bump-versions.py index 23265d7..3ab7eb7 100755 --- a/bump-versions.py +++ b/bump-versions.py @@ -225,8 +225,8 @@ def _latest_python_version(series: str) -> tuple[str, str]: return "", "" -def get_ubuntu_base_digest(image_ref: str) -> str: - """Resolve a Docker Hub image reference (e.g. "ubuntu:26.04") to +def get_debian_base_digest(image_ref: str) -> str: + """Resolve a Docker Hub image reference (e.g. "debian:trixie-slim") to its current manifest digest. Uses Docker Hub's anonymous v2 registry API. """ name, _, tag = image_ref.partition(":") @@ -385,18 +385,18 @@ def main() -> int: base = read_versions(SECTION_BASE) changes: list[tuple[str, str, str]] = [] - # UBUNTU_BASE_IMAGE is read-only here — the base image (e.g. ubuntu:26.04) + # DEBIAN_BASE_IMAGE is read-only here — the base image (e.g. debian:trixie-slim) # is a deliberate human choice and must not be auto-bumped. We only refresh the # digest pinning for whatever image is currently configured. - ubuntu_image = base.get("UBUNTU_BASE_IMAGE", "") - if not ubuntu_image: - log.error(f"UBUNTU_BASE_IMAGE missing from {VERSIONS_FILE} ({SECTION_BASE})") + debian_image = base.get("DEBIAN_BASE_IMAGE", "") + if not debian_image: + log.error(f"DEBIAN_BASE_IMAGE missing from {VERSIONS_FILE} ({SECTION_BASE})") return 1 bump( - "ubuntu_base_digest", - "UBUNTU_BASE_DIGEST", - get_ubuntu_base_digest(ubuntu_image), - base.get("UBUNTU_BASE_DIGEST", ""), + "debian_base_digest", + "DEBIAN_BASE_DIGEST", + get_debian_base_digest(debian_image), + base.get("DEBIAN_BASE_DIGEST", ""), changes, section=SECTION_BASE, ) diff --git a/versions.json b/versions.json index 06f23ab..2187be2 100644 --- a/versions.json +++ b/versions.json @@ -2,32 +2,32 @@ "variable": { "versions_base": { "default": { - "UBUNTU_BASE_IMAGE": "ubuntu:26.04", - "UBUNTU_BASE_DIGEST": "sha256:53958ec7b67c2c9355df922dd08dbf0360611f8c3cdb656875e81873db9ffdba" + "DEBIAN_BASE_IMAGE": "debian:trixie-slim", + "DEBIAN_BASE_DIGEST": "sha256:a29215f6a35e51e22adffa17f89e9d2ef06214e64a2bad10d765c46aea49f11f" } }, "versions_full": { "default": { - "KUBECTL_VERSION": "v1.36.2", - "KUBECTL_SHA256_AMD64": "1e9045ec32bea85da43de85f0065358529ea7c7a152eca78154fba5b58c27d82", - "KUBECTL_SHA256_ARM64": "c957eb8c4bea27a3bb35b269edd9082e27f027f7b76b20b5bf4afebc726c6d3e", - "GCLOUD_VERSION": "575.0.0", - "GCLOUD_SHA256_AMD64": "92a7331b6b20c9869c5e234f15e44850a58af435ccab43578d4ede1ef368a6e6", - "GCLOUD_SHA256_ARM64": "54b607d35b7335297e5e4166b3f9137baa5b1a7c7d2f8ce396411e91bd1fd4df", - "AWS_CLI_VERSION": "2.35.13", - "AWS_CLI_SHA256_AMD64": "9d8358b854dfac0decde81a0a21471abb5fd52d7366533bf25affcbbc2d5ad90", - "AWS_CLI_SHA256_ARM64": "c562b596fa9711f340c82307ca9eff576a4b96e75f1a003d1e6b2fec77820883", - "AZURE_CLI_VERSION": "2.87.0", + "KUBECTL_VERSION": "v1.37.1", + "KUBECTL_SHA256_AMD64": "65691ff77eb6fa44c908b77a1082c9f092c3b9733b5cefabec0d1104890e21a8", + "KUBECTL_SHA256_ARM64": "ff749f4b78d9c4f1ec87307df9b50119ed819e2094aa9810cb9acffc3286c8c7", + "GCLOUD_VERSION": "588.0.0", + "GCLOUD_SHA256_AMD64": "7b3111f67f8942f567ed5310319fb0cdfb618f03c80ae1ee1a22d6ddfc0d7cbd", + "GCLOUD_SHA256_ARM64": "9f2f3746b08884bd4440450be295ec3a1d9c0adc2f5c52c55888988e5c7ea70c", + "AWS_CLI_VERSION": "2.37.10", + "AWS_CLI_SHA256_AMD64": "1aaed142cb63294e41ef70431fe9c602dbb869f8a21b6b8fc9d5ffd53b5c9235", + "AWS_CLI_SHA256_ARM64": "891bb294ba0b8e7e1bd729b782864a3b10ca9754ee7ee1c650a0a306149484c7", + "AZURE_CLI_VERSION": "2.91.0", "SCALR_CLI_VERSION": "0.18.0", "SCALR_CLI_SHA256_AMD64": "5321bcebd48d30f7c3a936a5c5f10d9d3cfb77ef2974575d4df8e7ee9f890589", "SCALR_CLI_SHA256_ARM64": "8dcada09b5bf10001f4e83190fc9c2a66df692beb07a74b4afe503d2fa75629e", - "PYTHON_VERSION": "3.14.6", - "PYTHON_RELEASE": "20260623", - "PYTHON_SHA256_AMD64": "59a0e2d202f1d36cd8233cf1c426b469048025cf4eb26b972aea334c302cd999", - "PYTHON_SHA256_ARM64": "2746a23641001d1e7b7c1cb412b15f60824a8d66f00999a06e84da48b9939179", - "AWS_SSM_PLUGIN_VERSION": "1.2.814.0", - "AWS_SSM_PLUGIN_SHA256_AMD64": "67ddd12b963c28e44126f9732075caae333cc5f55e902623bd6a107ead2bcc56", - "AWS_SSM_PLUGIN_SHA256_ARM64": "dd714895b7e9b9945139301311778c175e556f75fda25250d36cff19c5eb0cdf" + "PYTHON_VERSION": "3.14.8", + "PYTHON_RELEASE": "20261003", + "PYTHON_SHA256_AMD64": "43b8c1b02e3daefbbbf4b5714b656ea00a5cae24f55c4589fb87468bcac682ed", + "PYTHON_SHA256_ARM64": "72cee1a99dfde64850dd5ffde8d96f84b0d352fd694cc1e92dad78abae6b8f29", + "AWS_SSM_PLUGIN_VERSION": "1.2.835.0", + "AWS_SSM_PLUGIN_SHA256_AMD64": "7c6dcad12518571cc7959a713e6a8ae1bdf6ed66fd9bee37dc189e39ca58ae03", + "AWS_SSM_PLUGIN_SHA256_ARM64": "0add94c4c8b6ca63f26e44fd655d662b0f6455a268b5b9ebebee0f462214e928" } }, "versions_python39": {