Every main merge runs publish.yml, which unconditionally rebuilds the three
kaniko images (gateway/appservice/web, ~25 min) — and each Dockerfile's
`COPY . .` busts kaniko's cache on any change. But none of those apps depend
on @mosaicstack/mosaic, so the entire constitution + fleet PR stream (all
packages/mosaic/** + docs/**) rebuilds all three images for nothing, saturating
the runners.
Gate the heavy steps with step-level `when: path`:
- build-gateway/appservice/web: skip when a main push touches ONLY non-image
paths (packages/mosaic/**, docs/**, **/*.md, .woodpecker/**); always build on
tag. Exclude-list keeps the default SAFE — any non-excluded change still
builds, so no transitive dep can silently go stale (chosen over per-image
include-lists, which risked under-including an app's transitive closure).
- publish-npm: run only when packages/** changed (or on tag) — a pure-docs
merge now runs no publish.
Woodpecker semantics (docs-confirmed): `when` entries are OR'd; `path` applies
to push/PR only (hence the separate `event: tag` entry); step-level `when`
governs the step independently of the file-level `when`.
install/build remain ungated (deferred: scoping the build + tightening the
Dockerfile COPY are follow-ups). Skip-validation lands on the next real merge
(a docs-only merge should show 0 image builds); skipping is safe — prior
:latest/:sha images remain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsgTQzV5YUGk1JtCLP4B83
Publish pipeline:
- Add publish-npm step to .woodpecker/publish.yml — publishes all
@mosaic/* packages to Gitea npm registry on main push/tag
- Requires gitea_npm_token Woodpecker secret (package:write scope)
- publish-npm runs after build, parallel with Docker image builds
- pnpm publish resolves workspace:* to concrete versions automatically
Package configuration:
- All 20 packages versioned at 0.0.1-alpha.1
- publishConfig added to all packages (Gitea registry, public access)
- files field added to all packages (ship only dist/)
- @mosaic/forge includes pipeline/ assets in published package
Meta package (@mosaic/mosaic):
- Now depends on @mosaic/forge, @mosaic/macp, @mosaic/prdy,
@mosaic/quality-rails, @mosaic/types
- npm install @mosaic/mosaic pulls in the standalone framework
Build fixes:
- Fix forge and macp tsconfig rootDir: '.' -> 'src' so dist/index.js
resolves correctly (was dist/src/index.js)
- Exclude __tests__ and vitest.config from build includes
- Clean stale build artifacts from old rootDir config
Required Woodpecker secret:
woodpecker secret add mosaic/mosaic-stack \
--name gitea_npm_token --value '<token>' \
--event push,manual,tag
Each step was re-running pnpm install independently, and all quality
steps (typecheck, lint, format, test) ran in parallel. On merge commits
with more accumulated code this pushed the CI runner over its memory
limit (exit code 254 = OOM kill).
Fix:
- install once, share node_modules via Woodpecker workspace volume
- sequential execution: install → typecheck → lint → format → test → build
- corepack enable in each step (fresh container) but no redundant install