refactor(ci): split monolithic pipeline into per-package pipelines
Replace single build.yml with split pipelines per the CI/CD guide: - api.yml: API with postgres, prisma, Trivy scan - web.yml: Web with Trivy scan - orchestrator.yml: Orchestrator with Trivy scan - coordinator.yml: Python with ruff/mypy/bandit/pip-audit/Trivy - infra.yml: postgres + openbao builds with Trivy Adds path filtering (only affected packages rebuild), Trivy container scanning for all images, and scoped per-package quality gates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,120 +1,142 @@
|
||||
# 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 production release |
|
||||
| `develop` branch | `dev` | Current development 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
|
||||
|
||||
This directory contains the Codex AI review pipeline configuration for automated code and security reviews on pull requests.
|
||||
The `codex-review.yml` pipeline runs independently on all PRs:
|
||||
|
||||
### Setup
|
||||
- **Code review**: Correctness, code quality, testing, performance
|
||||
- **Security review**: OWASP Top 10, hardcoded secrets, injection flaws
|
||||
|
||||
1. **Add Codex API key to Woodpecker:**
|
||||
- Go to mosaic-stack repo at `https://ci.mosaicstack.dev`
|
||||
- Settings → Secrets
|
||||
- Add secret: `codex_api_key` with your OpenAI API key
|
||||
|
||||
2. **Enable the pipeline:**
|
||||
- The `codex-review.yml` pipeline will automatically run on all PRs
|
||||
- The main `.woodpecker.yml` handles primary CI tasks
|
||||
- This codex pipeline is independent and focused solely on reviews
|
||||
|
||||
### What Gets Reviewed
|
||||
|
||||
**Code Review (`code-review` step):**
|
||||
|
||||
- Correctness — logic errors, edge cases, error handling
|
||||
- Code Quality — complexity, duplication, naming
|
||||
- Testing — coverage, test quality
|
||||
- Performance — N+1 queries, blocking ops
|
||||
- Dependencies — deprecated packages
|
||||
- Documentation — comments, API docs
|
||||
|
||||
**Security Review (`security-review` step):**
|
||||
|
||||
- OWASP Top 10 vulnerabilities
|
||||
- Hardcoded secrets/credentials
|
||||
- Injection flaws (SQL, NoSQL, OS command)
|
||||
- XSS, CSRF, SSRF
|
||||
- Auth/authz gaps
|
||||
- Data exposure in logs
|
||||
|
||||
### Pipeline Behavior
|
||||
|
||||
- **Triggers:** Every pull request
|
||||
- **Runs:** Code review + Security review in parallel
|
||||
- **Fails if:**
|
||||
- Code review finds **blockers**
|
||||
- Security review finds **critical** or **high** severity issues
|
||||
- **Outputs:** Structured JSON results in CI logs
|
||||
Fails on blockers or critical/high severity security findings.
|
||||
|
||||
### Local Testing
|
||||
|
||||
Test the review scripts locally before pushing:
|
||||
|
||||
```bash
|
||||
# Code review of uncommitted changes
|
||||
~/.claude/scripts/codex/codex-code-review.sh --uncommitted
|
||||
|
||||
# Security review of uncommitted changes
|
||||
~/.claude/scripts/codex/codex-security-review.sh --uncommitted
|
||||
|
||||
# Code review against main branch
|
||||
~/.claude/scripts/codex/codex-code-review.sh -b main
|
||||
|
||||
# Security review and save JSON
|
||||
~/.claude/scripts/codex/codex-security-review.sh -b main -o security.json
|
||||
```
|
||||
|
||||
### Schema Files
|
||||
## Troubleshooting
|
||||
|
||||
The `schemas/` directory contains JSON schemas that enforce structured output from Codex:
|
||||
### "unauthorized: authentication required"
|
||||
|
||||
- `code-review-schema.json` — Defines output for code quality reviews
|
||||
- `security-review-schema.json` — Defines output for security reviews
|
||||
- Verify `gitea_username` and `gitea_token` secrets in Woodpecker
|
||||
- Verify token has `package:write` scope
|
||||
|
||||
These schemas ensure consistent, machine-readable findings that the CI pipeline can parse and fail on.
|
||||
### Trivy scan fails with HIGH/CRITICAL
|
||||
|
||||
### Integration with Main Pipeline
|
||||
- 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
|
||||
|
||||
The main `.woodpecker.yml` in the repo root handles:
|
||||
### Package linking returns 404
|
||||
|
||||
- Type checking (TypeScript)
|
||||
- Linting (ESLint)
|
||||
- Unit tests (Vitest)
|
||||
- Integration tests (Playwright)
|
||||
- Docker image builds
|
||||
- Normal for recently pushed packages — retry logic handles this
|
||||
- If persistent: verify package name matches exactly (case-sensitive)
|
||||
|
||||
This `codex-review.yml` is independent and focuses solely on:
|
||||
### Pipeline runs Docker builds on pull requests
|
||||
|
||||
- AI-powered code quality review
|
||||
- AI-powered security vulnerability scanning
|
||||
|
||||
Both pipelines run in parallel on PRs.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**Pipeline fails with "codex: command not found"**
|
||||
|
||||
- Check that the node image in `codex-review.yml` matches a version with npm
|
||||
- Current: `node:22-slim`
|
||||
|
||||
**Pipeline fails with auth errors**
|
||||
|
||||
- Verify `codex_api_key` secret is set in Woodpecker
|
||||
- Test the key locally: `CODEX_API_KEY=<key> codex exec "test"`
|
||||
|
||||
**Pipeline passes but should fail**
|
||||
|
||||
- Check the failure conditions in `codex-review.yml`
|
||||
- Current thresholds: blockers, critical, or high findings
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
| ------------------------------------- | -------------------------------------- |
|
||||
| `codex-review.yml` | Codex AI review pipeline configuration |
|
||||
| `schemas/code-review-schema.json` | Code review output schema |
|
||||
| `schemas/security-review-schema.json` | Security review output schema |
|
||||
| `README.md` | This file |
|
||||
|
||||
## Parent CI Pipeline
|
||||
|
||||
The main `.woodpecker.yml` is located at the repository root and handles all build/test tasks.
|
||||
- Docker build steps have `when: branch: [main, develop]` guards
|
||||
- PRs only run quality gates, not Docker builds
|
||||
|
||||
Reference in New Issue
Block a user