From 420507da7754a30a31f2c146c831ecf60f38bd0d Mon Sep 17 00:00:00 2001 From: fargo Date: Wed, 19 Aug 2026 22:51:35 +0000 Subject: [PATCH 1/2] fix(#1323): remove legacy credential read and force-merge recipe from mosaic-gitea (#1325) --- .../framework/skills/mosaic-gitea/SKILL.md | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md b/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md index fd1a8818..9ae65e62 100644 --- a/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md +++ b/packages/mosaic/framework/skills/mosaic-gitea/SKILL.md @@ -11,13 +11,8 @@ Git operations via Mosaic wrapper scripts. Platform-aware (Gitea or GitHub). Scripts auto-detect platform from git remote. Run from inside the repo directory. -For force-merge (branch protection bypass): - -```bash -GITEA_TOKEN=$(cat ~/.config/mosaic/credentials/gitea.env | grep TOKEN | cut -d= -f2) -``` - -Or use the credentials loader: +Credentials come from the framework credentials loader (never from a shared env +file): ```bash source ~/.config/mosaic/tools/_lib/credentials.sh @@ -86,14 +81,10 @@ cd ~/src/ ~/.config/mosaic/tools/git/pr-merge.sh -n -d ``` -**Force-merge bypassing branch protection:** - -```bash -GITEA_TOKEN=$(cat ~/.config/mosaic/credentials/gitea.env | grep TOKEN | cut -d= -f2) -curl -X POST "https://git.mosaicstack.dev/api/v1/repos///pulls//merge" \ - -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \ - -d '{"Do":"squash","force_merge":true}' -``` +Branch protection is a gate, not an obstacle: if it blocks a merge, fix the cause — +a failing check, a moved head, or a missing review. Never bypass it with a raw +API call, a shared credential, or `force_merge`. Exceptional cases go to the +operator or the coordinating seat, still merged through the wrapper. ## Notes From cb9a0d16425ab44397dff1fed5e3d95f79468c7c Mon Sep 17 00:00:00 2001 From: ops-ci-01 Date: Wed, 19 Aug 2026 23:42:05 +0000 Subject: [PATCH 2/2] ci: pin ci-base to immutable lock-9cb7ffcd8828 (Closes #1328) (#1329) Co-authored-by: ops-ci-01 --- .woodpecker/ci.yml | 16 +++++++++++++++- .woodpecker/publish.yml | 7 ++++++- 2 files changed, 21 insertions(+), 2 deletions(-) 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