# Woodpecker CI Configuration for Mosaic Stack ## Pipeline Architecture Split per-package pipelines with path filtering. Only affected packages rebuild on push. ``` .woodpecker/ ├── api.yml # @mosaic/api (NestJS) ├── web.yml # @mosaic/web (Next.js) ├── orchestrator.yml # @mosaic/orchestrator (NestJS) ├── coordinator.yml # mosaic-coordinator (Python/FastAPI) ├── infra.yml # postgres + openbao Docker images ├── codex-review.yml # AI code/security review (PRs only) ├── README.md └── schemas/ ├── code-review-schema.json └── security-review-schema.json ``` ## Path Filtering | Pipeline | Triggers On | | ------------------ | --------------------------------------------------- | | `api.yml` | `apps/api/**`, `packages/**`, root configs | | `web.yml` | `apps/web/**`, `packages/**`, root configs | | `orchestrator.yml` | `apps/orchestrator/**`, `packages/**`, root configs | | `coordinator.yml` | `apps/coordinator/**` | | `infra.yml` | `docker/**` | | `codex-review.yml` | All PRs (no path filter) | **Root configs** = `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `turbo.json`, `package.json` ## Security Chain Every pipeline follows the full security chain required by the CI/CD guide: ``` source scanning (lint + pnpm audit / bandit + pip-audit) -> docker build (Kaniko) -> container scanning (Trivy: HIGH,CRITICAL) -> package linking (Gitea registry) ``` Docker builds gate on ALL quality + security steps passing. ## Pipeline Dependency Graphs ### Node.js Apps (api, web, orchestrator) ``` install -> [security-audit, lint, prisma-generate*] prisma-generate* -> [typecheck, prisma-migrate*] prisma-migrate* -> test [all quality gates] -> build -> docker-build -> trivy -> link ``` _\*prisma steps: api.yml only_ ### Coordinator (Python) ``` install -> [ruff-check, mypy, security-bandit, security-pip-audit, test] [all quality gates] -> docker-build -> trivy -> link ``` ### Infrastructure ``` [docker-build-postgres, docker-build-openbao] -> [trivy-postgres, trivy-openbao] -> link ``` ## Docker Images | Image | Registry Path | Context | | ------------------ | ----------------------------------------------- | ------------------- | | stack-api | `git.mosaicstack.dev/mosaic/stack-api` | `.` (monorepo root) | | stack-web | `git.mosaicstack.dev/mosaic/stack-web` | `.` (monorepo root) | | stack-orchestrator | `git.mosaicstack.dev/mosaic/stack-orchestrator` | `.` (monorepo root) | | stack-coordinator | `git.mosaicstack.dev/mosaic/stack-coordinator` | `apps/coordinator` | | stack-postgres | `git.mosaicstack.dev/mosaic/stack-postgres` | `docker/postgres` | | stack-openbao | `git.mosaicstack.dev/mosaic/stack-openbao` | `docker/openbao` | ## Image Tagging | Condition | Tag | Purpose | | ------------- | -------------------------- | -------------------------- | | Always | `${CI_COMMIT_SHA:0:8}` | Immutable commit reference | | `main` branch | `latest` | Current latest build | | Git tag | tag value (e.g., `v1.0.0`) | Semantic version release | ## Required Secrets Configure in Woodpecker UI (Settings > Secrets): | Secret | Scope | Purpose | | ---------------- | ----------------- | ------------------------------------------- | | `gitea_username` | push, manual, tag | Gitea registry auth | | `gitea_token` | push, manual, tag | Gitea registry auth (`package:write` scope) | | `codex_api_key` | pull_request | Codex AI reviews | ## Codex AI Review Pipeline The `codex-review.yml` pipeline runs independently on all PRs: - **Code review**: Correctness, code quality, testing, performance - **Security review**: OWASP Top 10, hardcoded secrets, injection flaws Fails on blockers or critical/high severity security findings. ### Local Testing ```bash ~/.claude/scripts/codex/codex-code-review.sh --uncommitted ~/.claude/scripts/codex/codex-security-review.sh --uncommitted ``` ## Troubleshooting ### "unauthorized: authentication required" - Verify `gitea_username` and `gitea_token` secrets in Woodpecker - Verify token has `package:write` scope ### Trivy scan fails with HIGH/CRITICAL - Check if the vulnerability is in the base image (not our code) - Add to `.trivyignore` if it's a known, accepted risk - Use `--ignore-unfixed` (already set) to skip unfixable CVEs ### Package linking returns 404 - Normal for recently pushed packages — retry logic handles this - If persistent: verify package name matches exactly (case-sensitive) ### Pipeline runs Docker builds on pull requests - Docker build steps have `when: branch: [main]` guards - PRs only run quality gates, not Docker builds