From 3cc72b7e41d466ab0a50496f04518d2f0e100fb2 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:41:20 +0200 Subject: [PATCH 1/2] chore: update-images script; orchestrator 2.2.3, Redis 7.4.11, ClickHouse 26.4.5 hack/update-images.sh (make update-images) bumps the pinned image tags in values.yaml to the newest tag of the same shape in each registry, and syncs artifacthub.io/images. The built-in datastores keep their major version and ClickHouse its year.month release; the images Renovate groups with Appwrite follow Appwrite's docker-compose.yml and are only bumped with --all. Bumps, all checked against Appwrite 2.3.0's docker-compose.yml: - open-runtimes orchestrator jobs-service and job-sidecar 2.2.3: a fix to the Kubernetes backend the chart uses for builds (the post sidecar can read owner-only worker output). Compose stays on 2.2.2 because it runs the Docker backend. - redis 7.4.11-alpine and clickhouse-server 26.4.5-alpine: patch releases of the versions Appwrite pins. --- Makefile | 4 + charts/appwrite/Chart.yaml | 8 +- charts/appwrite/README.md | 8 +- charts/appwrite/tests/builds_test.yaml | 2 +- charts/appwrite/values.yaml | 8 +- hack/fixtures/external-dbs.yaml | 4 +- hack/update-images.sh | 115 +++++++++++++++++++++++++ 7 files changed, 134 insertions(+), 15 deletions(-) create mode 100755 hack/update-images.sh diff --git a/Makefile b/Makefile index b21f87c..9606143 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,10 @@ env-defaults: ## Regenerate files/env-defaults.yaml from Appwrite's variables.ph images: ## Sync the artifacthub.io/images annotation with values.yaml hack/chart-images.sh +.PHONY: update-images +update-images: ## Bump every pinned image tag in values.yaml to the newest in its registry (ARGS="--dry-run --all") + hack/update-images.sh $(ARGS) + .PHONY: generate generate: schema images docs ## Regenerate all generated files diff --git a/charts/appwrite/Chart.yaml b/charts/appwrite/Chart.yaml index 3a66a34..464c555 100644 --- a/charts/appwrite/Chart.yaml +++ b/charts/appwrite/Chart.yaml @@ -69,13 +69,13 @@ annotations: - name: browser image: docker.io/appwrite/browser:0.3.4 - name: builds - image: ghcr.io/open-runtimes/orchestrator/job-sidecar:2.2.2 + image: ghcr.io/open-runtimes/orchestrator/job-sidecar:2.2.3 - name: builtin image: docker.io/appwrite/postgres:0.1.0 - name: builtin - image: docker.io/library/redis:7.4.7-alpine + image: docker.io/library/redis:7.4.11-alpine - name: builtin - image: docker.io/clickhouse/clickhouse-server:26.4.3-alpine + image: docker.io/clickhouse/clickhouse-server:26.4.5-alpine - name: builtin-exporter image: quay.io/prometheuscommunity/postgres-exporter:v0.20.1 - name: builtin-exporter @@ -91,5 +91,5 @@ annotations: - name: geo image: docker.io/appwrite/geo:0.3.1 - name: orchestrator - image: ghcr.io/open-runtimes/orchestrator/jobs-service:2.2.2 + image: ghcr.io/open-runtimes/orchestrator/jobs-service:2.2.3 artifacthub.io/displayName: Appwrite diff --git a/charts/appwrite/README.md b/charts/appwrite/README.md index cc308f0..1b63934 100644 --- a/charts/appwrite/README.md +++ b/charts/appwrite/README.md @@ -379,7 +379,7 @@ Built-in or your own. | redis.builtin.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy. | | redis.builtin.image.registry | string | `"docker.io"` | Image registry. | | redis.builtin.image.repository | string | `"library/redis"` | Image repository. `valkey/valkey` works as a drop-in replacement, with a Valkey tag (e.g. `8-alpine`). | -| redis.builtin.image.tag | string | `"7.4.7-alpine"` | Image tag. | +| redis.builtin.image.tag | string | `"7.4.11-alpine"` | Image tag. | | redis.builtin.maxmemory | string | `"512mb"` | `maxmemory`. Keep it below the memory limit. | | redis.builtin.maxmemoryPolicy | string | `"allkeys-lru"` | `maxmemory-policy`. Appwrite's Docker install uses `allkeys-lru`. | | redis.builtin.metrics.enabled | bool | `false` | Run a redis_exporter sidecar and expose it on port 9121 of the Service. See docs/production.md#monitoring. | @@ -428,7 +428,7 @@ Built-in or your own. | clickhouse.builtin.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy. | | clickhouse.builtin.image.registry | string | `"docker.io"` | Image registry. | | clickhouse.builtin.image.repository | string | `"clickhouse/clickhouse-server"` | Image repository. | -| clickhouse.builtin.image.tag | string | `"26.4.3-alpine"` | Image tag. | +| clickhouse.builtin.image.tag | string | `"26.4.5-alpine"` | Image tag. | | clickhouse.builtin.metrics.enabled | bool | `false` | Serve ClickHouse's built-in Prometheus endpoint on port 9363 of the Service (`/metrics`). No sidecar. See docs/production.md#monitoring. | | clickhouse.builtin.nodeSelector | object | `{}` | Node selector. Empty inherits `defaults.nodeSelector`. | | clickhouse.builtin.persistence.accessModes | list | `["ReadWriteOnce"]` | Access modes. | @@ -848,7 +848,7 @@ The build orchestrator and the executor. | compute.builds.sidecarImage.digest | string | `""` | Image digest. | | compute.builds.sidecarImage.registry | string | `"ghcr.io"` | Image registry. | | compute.builds.sidecarImage.repository | string | `"open-runtimes/orchestrator/job-sidecar"` | Image repository of the sidecar that moves sources, outputs and caches for each build. | -| compute.builds.sidecarImage.tag | string | `"2.2.2"` | Image tag. | +| compute.builds.sidecarImage.tag | string | `"2.2.3"` | Image tag. | | compute.builds.tolerations | list | `[]` | Tolerations for build pods. | | compute.enabled | bool | `false` | Enable Functions and Sites. Needs `storage.device: s3` and `compute.executor.privileged` (see docs/executor.md). | | compute.executor.affinity | object | `{}` | Affinity. Empty inherits `defaults.affinity`. | @@ -891,7 +891,7 @@ The build orchestrator and the executor. | compute.orchestrator.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy. | | compute.orchestrator.image.registry | string | `"ghcr.io"` | Image registry. | | compute.orchestrator.image.repository | string | `"open-runtimes/orchestrator/jobs-service"` | Image repository: the orchestrator's jobs service, with the Kubernetes backend. | -| compute.orchestrator.image.tag | string | `"2.2.2"` | Image tag. | +| compute.orchestrator.image.tag | string | `"2.2.3"` | Image tag. | | compute.orchestrator.nodeSelector | object | `{}` | Node selector. Empty inherits `defaults.nodeSelector`. | | compute.orchestrator.podAnnotations | object | `{}` | Pod annotations, merged over `defaults.podAnnotations`. | | compute.orchestrator.podLabels | object | `{}` | Pod labels, merged over `defaults.podLabels`. | diff --git a/charts/appwrite/tests/builds_test.yaml b/charts/appwrite/tests/builds_test.yaml index 202af9b..2c8ce81 100644 --- a/charts/appwrite/tests/builds_test.yaml +++ b/charts/appwrite/tests/builds_test.yaml @@ -48,7 +48,7 @@ tests: asserts: - equal: path: spec.template.spec.containers[0].image - value: ghcr.io/open-runtimes/orchestrator/jobs-service:2.2.2 + value: ghcr.io/open-runtimes/orchestrator/jobs-service:2.2.3 - equal: path: spec.strategy.type value: Recreate diff --git a/charts/appwrite/values.yaml b/charts/appwrite/values.yaml index 41da99b..b85c7c7 100644 --- a/charts/appwrite/values.yaml +++ b/charts/appwrite/values.yaml @@ -458,7 +458,7 @@ redis: # with a Valkey tag (e.g. `8-alpine`). repository: library/redis # -- Image tag. - tag: 7.4.7-alpine + tag: 7.4.11-alpine # -- Image digest. digest: "" # -- Image pull policy. @@ -577,7 +577,7 @@ clickhouse: # -- Image repository. repository: clickhouse/clickhouse-server # -- Image tag. - tag: 26.4.3-alpine + tag: 26.4.5-alpine # -- Image digest. digest: "" # -- Image pull policy. @@ -855,7 +855,7 @@ compute: # -- Image repository: the orchestrator's jobs service, with the Kubernetes backend. repository: open-runtimes/orchestrator/jobs-service # -- Image tag. - tag: 2.2.2 + tag: 2.2.3 # -- Image digest. digest: "" # -- Image pull policy. @@ -911,7 +911,7 @@ compute: # -- Image repository of the sidecar that moves sources, outputs and caches for each build. repository: open-runtimes/orchestrator/job-sidecar # -- Image tag. - tag: 2.2.2 + tag: 2.2.3 # -- Image digest. digest: "" # -- Divides each build's CPU limit to get its CPU request diff --git a/hack/fixtures/external-dbs.yaml b/hack/fixtures/external-dbs.yaml index 2963313..36a00b5 100644 --- a/hack/fixtures/external-dbs.yaml +++ b/hack/fixtures/external-dbs.yaml @@ -66,7 +66,7 @@ spec: spec: containers: - name: redis - image: redis:7.4.7-alpine + image: redis:7.4.11-alpine args: [--requirepass, $(REDIS_PASSWORD)] env: - name: REDIS_PASSWORD @@ -97,7 +97,7 @@ spec: spec: containers: - name: clickhouse - image: clickhouse/clickhouse-server:26.4.3-alpine + image: clickhouse/clickhouse-server:26.4.5-alpine env: - {name: CLICKHOUSE_DB, value: usage} - {name: CLICKHOUSE_USER, value: usage} diff --git a/hack/update-images.sh b/hack/update-images.sh new file mode 100755 index 0000000..528a814 --- /dev/null +++ b/hack/update-images.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# Updates every pinned image tag in values.yaml to the newest tag in its +# registry, then syncs the artifacthub.io/images annotation. +# +# A candidate tag has the same shape as the current one: the same prefix and +# suffix (v0.20.1, 7.4.7-alpine, 29.9.0-dind, 1.1.159-self-hosted) and the +# same number of version components, so floating tags (7, 7.4, latest) and +# pre-releases (-rc.1) are never picked. The built-in datastores stay on their +# current major version, as in renovate.json, and ClickHouse on its current +# year.month release (26.4.x), since each of those is a feature release. +# +# The images Renovate groups with Appwrite in renovate.json (the console, +# executor, orchestrator and Appwrite's own services) are pinned to what +# Appwrite's docker-compose.yml uses for appVersion, not to the newest tag: +# they're skipped unless --all is given. The Appwrite image follows appVersion +# (its tag is empty) and isn't touched; see CONTRIBUTING.md. +# +# Usage: hack/update-images.sh [--dry-run] [--all] +# Requires: yq v4, jq, curl. +set -euo pipefail + +CHART="${CHART:-charts/appwrite}" +VALUES="$CHART/values.yaml" +dry_run=false +all=false +for arg in "$@"; do + case "$arg" in + --dry-run) dry_run=true ;; + --all) all=true ;; + -h | --help) + sed -n '2,/^set -euo/p' "$0" | sed '$d; s/^# \{0,1\}//' + exit 0 + ;; + *) + echo "Unknown argument: $arg (see --help)" >&2 + exit 2 + ;; + esac +done +appwrite_group=$(jq -r '.packageRules[] | select(.groupName == "appwrite") | .matchPackageNames[]' \ + "$(dirname "$0")/../renovate.json") + +# Prints every tag of registry/repository, using an anonymous pull token when +# the registry asks for one and following Link pagination. +list_tags() { + local registry=$1 repository=$2 host=$1 auth=() challenge realm service token url + [[ "$registry" == docker.io ]] && host="registry-1.docker.io" + url="https://${host}/v2/${repository}/tags/list?n=10000" + challenge=$(curl -sS -o /dev/null -D - "$url" | tr -d '\r' | grep -i '^www-authenticate: bearer' || true) + if [[ -n "$challenge" ]]; then + realm=$(sed -E 's/.*realm="([^"]+)".*/\1/' <<<"$challenge") + service=$(sed -E 's/.*service="([^"]+)".*/\1/' <<<"$challenge") + token=$(curl -fsS "${realm}?service=${service}&scope=repository:${repository}:pull" | jq -er '.token // .access_token') + auth=(-H "Authorization: Bearer ${token}") + fi + while [[ -n "$url" ]]; do + headers=$(mktemp) + curl -fsS "${auth[@]}" -D "$headers" "$url" | jq -r '.tags[]?' + url=$(tr -d '\r' < "$headers" | sed -nE 's/^[Ll]ink: <([^>]+)>.*/\1/p') + rm -f "$headers" + [[ -z "$url" || "$url" == http* ]] || url="https://${host}${url}" + done +} + +# Prints the newest tag of the same shape as $1 among the tags on stdin, +# keeping its first $2 version components (0: any version, 1: same major). +newest() { + local current=$1 fixed=$2 prefix suffix pattern="" i=0 part + [[ "$current" =~ ^([^0-9]*)([0-9]+(\.[0-9]+)*)(.*)$ ]] || return 0 + prefix=${BASH_REMATCH[1]} suffix=${BASH_REMATCH[4]} + for part in ${BASH_REMATCH[2]//./ }; do + [[ "$i" -lt "$fixed" ]] || part='[0-9]+' + pattern+="${pattern:+\\.}${part}" + i=$((i + 1)) + done + { grep -E "^$(escape "$prefix")${pattern}$(escape "$suffix")\$" || true; } \ + | awk -v p="${#prefix}" -v s="${#suffix}" '{print substr($0, p + 1, length($0) - p - s) "\t" $0}' \ + | sort -V | tail -1 | cut -f2 +} + +escape() { sed 's/[][\.*^$+?(){}|/]/\\&/g' <<<"$1"; } + +changed=0 +while IFS=$'\t' read -r path registry repository tag; do + if [[ "$all" == false ]] && grep -qx "${registry}/${repository}" <<<"$appwrite_group"; then + printf ' %-45s %s (follows Appwrite %s, --all to update)\n' "${registry}/${repository}" "$tag" \ + "$(yq '.appVersion' "$CHART/Chart.yaml")" + continue + fi + fixed=0 + [[ "$path" == *.builtin.image ]] && fixed=1 + [[ "$repository" == clickhouse/clickhouse-server ]] && fixed=2 + latest=$(list_tags "$registry" "$repository" | newest "$tag" "$fixed") + if [[ -z "$latest" || "$latest" == "$tag" ]]; then + printf ' %-45s %s\n' "${registry}/${repository}" "$tag" + continue + fi + printf '* %-45s %s -> %s\n' "${registry}/${repository}" "$tag" "$latest" + changed=$((changed + 1)) + if [[ "$dry_run" == false ]]; then + # yq -i would drop the file's blank lines: edit only the tag's line, the + # first one after the image's repository. + awk -v repo="$repository" -v old="$tag" -v new="$latest" ' + $1 == "repository:" && $2 == repo { found = 1 } + found && $1 == "tag:" && $2 == old { sub(/tag: .*/, "tag: " new); found = 0 } + { print } + ' "$VALUES" > "$VALUES.tmp" && mv "$VALUES.tmp" "$VALUES" + fi +done < <(yq -r '.. | select(tag == "!!map" and has("registry") and has("repository") and .tag != "") + | [(path | map(tostring) | join(".")), .registry, .repository, .tag] | @tsv' "$VALUES") + +if [[ "$changed" -gt 0 && "$dry_run" == false ]]; then + "$(dirname "$0")/chart-images.sh" + echo "Updated ${changed} image(s). Run 'make generate test', and add a CHANGELOG.md entry." +fi From 9cadabdb08ae490cb537f38161c9f41476437bf0 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:26:40 +0200 Subject: [PATCH 2/2] test: assert the build sidecar image The orchestrator passes job-sidecar to every build Job through JOB_SIDECAR_IMAGE; the builds suite only asserted the jobs-service image, so a wrong sidecar pin left the tests green. --- charts/appwrite/tests/builds_test.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/charts/appwrite/tests/builds_test.yaml b/charts/appwrite/tests/builds_test.yaml index 2c8ce81..fab40ae 100644 --- a/charts/appwrite/tests/builds_test.yaml +++ b/charts/appwrite/tests/builds_test.yaml @@ -49,6 +49,11 @@ tests: - equal: path: spec.template.spec.containers[0].image value: ghcr.io/open-runtimes/orchestrator/jobs-service:2.2.3 + - contains: + path: spec.template.spec.containers[0].env + content: + name: JOB_SIDECAR_IMAGE + value: ghcr.io/open-runtimes/orchestrator/job-sidecar:2.2.3 - equal: path: spec.strategy.type value: Recreate