diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml index 35acff9e..d06f9903 100644 --- a/.woodpecker/ci.yml +++ b/.woodpecker/ci.yml @@ -2,8 +2,22 @@ # node:24-alpine + python3/make/g++/postgresql-client + pnpm + a warm pnpm # store. The install step resolves from the baked store (--prefer-offline) # instead of paying a ~731s cold fetch + native compile every run. +# +# PINNED to an immutable lock-tag (#1328, brain D27): ci-image.yml pushes +# lock- atomically with :latest, so the two are +# byte-identical at push time. A mutable :latest resolves per-pod at pull time +# on the k8s backend, which made CI verdicts non-reproducible (same tree, same +# config, different images across runs; see #1324 comment 23382/23386). The pin +# changes ONLY through reviewed commits; a wrong tag fails loudly at image pull. +# +# Bump procedure: when a recipe change (pnpm-lock.yaml / Dockerfile.ci) lands on +# main, ci-image.yml pushes lock-; a follow-up PR updates this anchor. +# Until then pipelines keep the old pin: reproducible, with the documented +# network-fallback lag (frozen-lockfile resolves missing packages from network). +# Known limitation: lock- addresses the lockfile only, so a Dockerfile-only +# change re-pushes the same tag with new content (#1328 follow-up: recipe-hash). variables: - - &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:latest' + - &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:lock-9cb7ffcd8828' - &enable_pnpm 'corepack enable' when: diff --git a/.woodpecker/publish.yml b/.woodpecker/publish.yml index 2249b1c1..418ab21f 100644 --- a/.woodpecker/publish.yml +++ b/.woodpecker/publish.yml @@ -18,7 +18,12 @@ variables: # Pre-baked CI base (see .woodpecker/ci-image.yml): node:24-alpine + # toolchain + warm pnpm store. Kills the second cold install publish pays. - - &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:latest' + # PINNED to the immutable lock-tag, not :latest (#1328, brain D27): a mutable + # tag resolves per-pod at pull time on the k8s backend and made CI verdicts + # non-reproducible (#1324). Byte-identical to :latest at pin time (pushed + # atomically by the same kaniko run, main 712c770, 2026-07-26). Bump only via + # reviewed PR, per the procedure in .woodpecker/ci.yml's header comment. + - &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:lock-9cb7ffcd8828' - &enable_pnpm 'corepack enable' # Heavy kaniko image builds (~25 min) — gate them so a merge that only touches # the npm-only CLI (@mosaicstack/mosaic) or docs does NOT rebuild the platform