From 8d27e0f78ce27e3a3517fee3ec6a4ec224638aee Mon Sep 17 00:00:00 2001 From: code-be-01 Date: Mon, 24 Aug 2026 19:40:24 -0500 Subject: [PATCH] ci(publish): serialize workspace-consuming image builds after publish-next-npm (#1411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pipeline 2648 failed build-gateway with ERR_PNPM_OUTDATED_LOCKFILE although publish-next-npm completed green and restored the workspace byte-exact ('git diff clean' in its own log). Root cause: build-gateway and publish-next-npm both depend on [build, verify] and run concurrently; kaniko's COPY of apps/gateway/package.json raced inside publish's in-place mutation window (transform .. publish .. restore). PR 1405's snapshot/restore governs the END state of its own step only — no mutual exclusion against a concurrent reader. The snapshot/restore set was already a superset of the transform's write set (both derive from apps/packages/plugins with the same exclusions — the tasking's apps-coverage hypothesis is refuted by the committed find). The defect is ordering, so the fix is a DAG edge: build-gateway, build-appservice, and build-web each gain publish-next-npm in depends_on, serializing every kaniko workspace consumer after the restore. publish-npm (main-only, transform is next-only) is unchanged. The invariant is stated inline at each edge: any new workspace-consuming step must depend on publish-next-npm. Red-first evidence (clean clone of next; scripts from the committed YAML; gateway manifest as the demonstration case): pre-fix DAG shows build-gateway deps == publish deps (concurrent); post-fix adds the edge. Reading apps/gateway/package.json mid-window shows 0.0.3-next.2648 pins (the 2648 dump shape) and pnpm install --frozen-lockfile fails ERR_PNPM_OUTDATED_LOCKFILE; the same read after restore shows workspace:^ and the identical clean tree installs rc=0. Closes #1411 (blocks PR 1401's merge — USC chain). --- .woodpecker/publish.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.woodpecker/publish.yml b/.woodpecker/publish.yml index a5ada7b1..bf6cdd3b 100644 --- a/.woodpecker/publish.yml +++ b/.woodpecker/publish.yml @@ -449,6 +449,14 @@ steps: depends_on: - build - verify + # #1411: publish-next-npm mutates workspace manifests in place during + # its transform window and restores them at step end. Any step that + # reads the pipeline workspace (kaniko COPY of manifests, later + # installs) must run AFTER publish-next-npm, never concurrently — + # pipeline 2648 raced a COPY inside the window and failed + # ERR_PNPM_OUTDATED_LOCKFILE despite a clean restore. This edge is the + # serialization invariant; add it to every new workspace consumer. + - publish-next-npm build-appservice: image: gcr.io/kaniko-project/executor:debug @@ -476,6 +484,14 @@ steps: depends_on: - build - verify + # #1411: publish-next-npm mutates workspace manifests in place during + # its transform window and restores them at step end. Any step that + # reads the pipeline workspace (kaniko COPY of manifests, later + # installs) must run AFTER publish-next-npm, never concurrently — + # pipeline 2648 raced a COPY inside the window and failed + # ERR_PNPM_OUTDATED_LOCKFILE despite a clean restore. This edge is the + # serialization invariant; add it to every new workspace consumer. + - publish-next-npm build-web: image: gcr.io/kaniko-project/executor:debug @@ -503,3 +519,11 @@ steps: depends_on: - build - verify + # #1411: publish-next-npm mutates workspace manifests in place during + # its transform window and restores them at step end. Any step that + # reads the pipeline workspace (kaniko COPY of manifests, later + # installs) must run AFTER publish-next-npm, never concurrently — + # pipeline 2648 raced a COPY inside the window and failed + # ERR_PNPM_OUTDATED_LOCKFILE despite a clean restore. This edge is the + # serialization invariant; add it to every new workspace consumer. + - publish-next-npm