Compare commits

...

1 Commits

Author SHA1 Message Date
Jarvis
9da71bd861 ci: switch pipelines to pre-baked ci-base image (consumer) [Phase 1b]
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline was successful
Consumer half of the Woodpecker CI cache work (#634). Re-scoped from the
original combined change: the image recipe (Dockerfile.ci, ci-image.yml)
now lives in the producer PR #637. This branch only flips the consumers.

- ci.yml / publish.yml: pull git.mosaicstack.dev/mosaicstack/stack/ci-base
  :latest for the install step and resolve from the baked pnpm store via
  --prefer-offline (drops the per-run apk add + cold network fetch).
- framework monorepo template: single cached install instead of npm ci per
  step, so scaffolded repos inherit the fix.

B2 fix (blocker): pin store-dir in root .npmrc to
/root/.local/share/pnpm/store — the exact path Dockerfile.ci warms — so the
pipeline install actually consumes the baked store instead of repopulating
a fresh one. The existing @mosaicstack registry line is preserved.

BLOCKED ON: PR #637 merge + a manual ci-image prime of ci-base:latest on
main. Until the image is primed this branch's CI is red (it pulls an image
that does not exist yet). Do not merge until a green re-run after priming.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 16:50:39 -05:00
4 changed files with 34 additions and 16 deletions

4
.npmrc
View File

@@ -1 +1,5 @@
@mosaicstack:registry=https://git.mosaicstack.dev/api/packages/mosaicstack/npm/
# Pin the pnpm store to the same path the ci-base image warms (Dockerfile.ci),
# so the pipeline `pnpm install --prefer-offline` consumes the baked store
# instead of repopulating a fresh one.
store-dir=/root/.local/share/pnpm/store

View File

@@ -1,5 +1,9 @@
# &node_image is the pre-baked CI base built by .woodpecker/ci-image.yml:
# node:22-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.
variables:
- &node_image 'node:22-alpine'
- &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:latest'
- &enable_pnpm 'corepack enable'
when:
@@ -15,8 +19,9 @@ steps:
image: *node_image
commands:
- corepack enable
- apk add --no-cache python3 make g++
- pnpm install --frozen-lockfile
# python3/make/g++ are baked into ci-base; --prefer-offline resolves from
# the baked pnpm store.
- pnpm install --frozen-lockfile --prefer-offline
# Blocking gate: public framework package must contain no operator-specific
# personal data or private $HOME defaults. Runs early (no node_modules needed).
@@ -64,8 +69,7 @@ steps:
DATABASE_URL: postgresql://mosaic:mosaic@ci-postgres:5432/mosaic
commands:
- *enable_pnpm
# Install postgresql-client for pg_isready
- apk add --no-cache postgresql-client
# postgresql-client (pg_isready) is baked into ci-base.
# Wait up to 60s for CI postgres to be ready; fail fast if it never comes up.
- |
ready=0

View File

@@ -2,7 +2,9 @@
# Runs only on main branch push/tag
variables:
- &node_image 'node:22-alpine'
# Pre-baked CI base (see .woodpecker/ci-image.yml): node:22-alpine +
# toolchain + warm pnpm store. Kills the second cold install publish pays.
- &node_image 'git.mosaicstack.dev/mosaicstack/stack/ci-base:latest'
- &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
@@ -31,7 +33,8 @@ steps:
image: *node_image
commands:
- corepack enable
- pnpm install --frozen-lockfile
# Resolve from the baked pnpm store instead of a cold network fetch.
- pnpm install --frozen-lockfile --prefer-offline
build:
image: *node_image

View File

@@ -2,12 +2,20 @@
when:
- event: [push, pull_request, manual]
# Dependencies are installed ONCE in the `install` step and every downstream
# step depends on it, reusing the populated node_modules from the shared
# workspace volume. Do NOT re-run `npm ci` per step — that pays the full cold
# install (network fetch + native rebuilds) N times and is the dominant cost
# in a pipeline.
#
# For best results, replace `&node_image` with a pre-baked CI base image that
# ships your toolchain (python3/make/g++ for native modules) and a warm npm
# cache, then keep `--prefer-offline` so installs resolve from the cache. See
# the Mosaic Stack repo's Dockerfile.ci + .woodpecker/ci-image.yml for the
# baked-image pattern.
variables:
- &node_image 'node:20-alpine'
- &gitleaks_image 'ghcr.io/gitleaks/gitleaks:v8.24.0'
- &install_deps |
corepack enable
npm ci --ignore-scripts
steps:
# Secret scanning (runs in parallel with install, no deps)
@@ -17,15 +25,18 @@ steps:
- gitleaks git --redact --verbose --log-opts="HEAD~1..HEAD"
depends_on: []
# Single cached install. Every other step depends on this and reuses the
# node_modules it produces in the shared workspace.
install:
image: *node_image
commands:
- *install_deps
- corepack enable
- npm ci --ignore-scripts --prefer-offline
depends_on: []
security-audit:
image: *node_image
commands:
- *install_deps
- npm audit --audit-level=high
depends_on:
- install
@@ -35,7 +46,6 @@ steps:
environment:
SKIP_ENV_VALIDATION: 'true'
commands:
- *install_deps
- npm run lint
depends_on:
- install
@@ -45,7 +55,6 @@ steps:
environment:
SKIP_ENV_VALIDATION: 'true'
commands:
- *install_deps
- npm run type-check
depends_on:
- install
@@ -55,7 +64,6 @@ steps:
environment:
SKIP_ENV_VALIDATION: 'true'
commands:
- *install_deps
- npm run test -- --coverage --coverageThreshold='{"global":{"branches":80,"functions":80,"lines":80,"statements":80}}'
depends_on:
- install
@@ -66,7 +74,6 @@ steps:
SKIP_ENV_VALIDATION: 'true'
NODE_ENV: 'production'
commands:
- *install_deps
- npm run build
depends_on:
- lint