Skip to content

CI Default Versions#

All ci_*.sh helper scripts read their Docker image versions from a single centralized module: lib/ci_defaults.sh. This page explains how the defaults work, how to override them, and how to update them.

How it works#

lib/ci_defaults.sh          <-- single source of truth for all versions
  |
  +-- scripts/ci_node.sh    IMAGE_TAG="$CI_DEFAULT_NODE_VERSION"
  +-- scripts/ci_python.sh  IMAGE_TAG="$CI_DEFAULT_PYTHON_VERSION"
  +-- scripts/ci_flutter.sh IMAGE_TAG="$CI_DEFAULT_FLUTTER_VERSION"
  +-- scripts/ci_gradle.sh  IMAGE_TAG="$CI_DEFAULT_GRADLE_VERSION"
  +-- scripts/ci_go.sh      IMAGE_TAG="$CI_DEFAULT_GO_VERSION"
  +-- scripts/ci_security.sh
        PY_VERSION="$CI_DEFAULT_PYTHON_VERSION"
        NODE_VERSION="$CI_DEFAULT_NODE_VERSION"
        GITLEAKS_VERSION="$CI_DEFAULT_GITLEAKS_VERSION"
        foxguard: CI_DEFAULT_FOXGUARD_VERSION + SHA-256 per platform (lib/foxguard.sh)

Overriding at runtime#

CLI flags always take precedence over the centralized defaults:

# Use defaults from ci_defaults.sh
./scripts/ci_node.sh --workdir frontend

# Override the tag for this run only
./scripts/ci_node.sh --workdir frontend --version 22-bookworm

# Override the entire image reference
./scripts/ci_node.sh --workdir frontend --image myregistry/node:22

Overriding via environment#

Each default uses ${CI_DEFAULT_*:-fallback} syntax, so you can also override via environment variables without editing the file:

export CI_DEFAULT_NODE_VERSION="22-bookworm"
./scripts/ci_node.sh --workdir frontend

Current defaults#

Service Variable Default Image
Node.js CI_DEFAULT_NODE_VERSION 24-bookworm node:24-bookworm
Python CI_DEFAULT_PYTHON_VERSION 3.12-slim python:3.12-slim
Flutter CI_DEFAULT_FLUTTER_VERSION 3.38.8 ghcr.io/cirruslabs/flutter:3.38.8
Gradle CI_DEFAULT_GRADLE_VERSION 8.7-jdk17 gradle:8.7-jdk17
Go CI_DEFAULT_GO_VERSION 1.22 golang:1.22
Gitleaks CI_DEFAULT_GITLEAKS_VERSION v8.30.1 zricethezav/gitleaks:v8.30.1
Wrangler CI_DEFAULT_WRANGLER_VERSION 4.42.0 npm package, not an image

How to update versions#

Step 1 -- Check latest stable releases#

Run these commands to find the latest versions:

# Node.js LTS (pick latest LTS + Debian codename)
# https://hub.docker.com/_/node/tags
docker run --rm node:lts cat /etc/os-release | grep VERSION_CODENAME
# or check: https://nodejs.org/en/about/previous-releases

# Python (pick 3.x-slim)
# https://hub.docker.com/_/python/tags
curl -s 'https://registry.hub.docker.com/v2/repositories/library/python/tags/?page_size=20&name=slim' \
  | jq -r '.results[].name' | grep -E '^3\.[0-9]+-slim$' | sort -V | tail -3

# Flutter (specific version, not "stable")
# https://github.com/cirruslabs/docker-images-flutter/pkgs/container/flutter
gh api repos/flutter/flutter/git/refs/tags --paginate \
  --jq '.[].ref' | grep -E '^refs/tags/[0-9]+\.[0-9]+\.[0-9]+$' \
  | sort -t. -k1,1n -k2,2n -k3,3n | tail -1

# Gradle (pick version-jdkNN)
# https://hub.docker.com/_/gradle/tags
curl -s 'https://registry.hub.docker.com/v2/repositories/library/gradle/tags/?page_size=50' \
  | jq -r '.results[].name' | grep -E '^[0-9]+\.[0-9]+-jdk[0-9]+$' | sort -V | tail -5

# Go (pick 1.x)
# https://hub.docker.com/_/golang/tags
gh api repos/golang/go/git/refs/tags --paginate \
  --jq '.[].ref' | grep -E '^refs/tags/go1\.[0-9]+(\.[0-9]+)?$' \
  | sort -V | tail -3

# Gitleaks
gh api repos/gitleaks/gitleaks/releases/latest --jq '.tag_name'

Step 2 -- Edit lib/ci_defaults.sh#

Update the version strings and the LAST UPDATED date comment:

$EDITOR lib/ci_defaults.sh

Step 3 -- Commit#

git add lib/ci_defaults.sh
git commit -m "chore: bump ci default versions"

Step 4 -- Propagate to consuming repositories#

Repositories that vendor script-helpers as a submodule need to update:

cd /path/to/consuming-repo
./update   # or: git submodule update --remote scripts/script-helpers
git add scripts/script-helpers
git commit -m "chore: update script-helpers submodule"

For ci-helpers (which vendors under vendor/script-helpers/):

cd /path/to/ci-helpers
./scripts/sync_script_helpers.sh
git add vendor/script-helpers
git commit -m "chore: sync script-helpers vendor"

Supply-chain pinning#

For stronger guarantees, pin images to an immutable digest:

# Flutter
./scripts/ci_flutter.sh --digest sha256:abcdef...

# Gitleaks
./scripts/ci_security.sh --gitleaks-digest sha256:abcdef...

# Any image via full override
./scripts/ci_node.sh --image node@sha256:abcdef...

To find the current digest for an image:

docker manifest inspect node:24-bookworm | jq -r '.manifests[0].digest'
# or
docker pull node:24-bookworm && docker inspect node:24-bookworm | jq -r '.[0].RepoDigests[0]'