518 lines
14 KiB
Markdown
518 lines
14 KiB
Markdown
<!-- Powered by BMAD-CORE™ -->
|
||
|
||
# CI/CD Pipeline Setup
|
||
|
||
**Workflow ID**: `bmad/bmm/testarch/ci`
|
||
**Version**: 4.0 (BMad v6)
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
Scaffolds a production-ready CI/CD quality pipeline with test execution, burn-in loops for flaky test detection, parallel sharding, artifact collection, and notification configuration. This workflow creates platform-specific CI configuration optimized for fast feedback and reliable test execution.
|
||
|
||
---
|
||
|
||
## Preflight Requirements
|
||
|
||
**Critical:** Verify these requirements before proceeding. If any fail, HALT and notify the user.
|
||
|
||
- ✅ Git repository is initialized (`.git/` directory exists)
|
||
- ✅ Local test suite passes (`npm run test:e2e` succeeds)
|
||
- ✅ Test framework is configured (from `framework` workflow)
|
||
- ✅ Team agrees on target CI platform (GitHub Actions, GitLab CI, Circle CI, etc.)
|
||
- ✅ Access to CI platform settings/secrets available (if updating existing pipeline)
|
||
|
||
---
|
||
|
||
## Step 1: Run Preflight Checks
|
||
|
||
### Actions
|
||
|
||
1. **Verify Git Repository**
|
||
- Check for `.git/` directory
|
||
- Confirm remote repository configured (`git remote -v`)
|
||
- If not initialized, HALT with message: "Git repository required for CI/CD setup"
|
||
|
||
2. **Validate Test Framework**
|
||
- Look for `playwright.config.*` or `cypress.config.*`
|
||
- Read framework configuration to extract:
|
||
- Test directory location
|
||
- Test command
|
||
- Reporter configuration
|
||
- Timeout settings
|
||
- If not found, HALT with message: "Run `framework` workflow first to set up test infrastructure"
|
||
|
||
3. **Run Local Tests**
|
||
- Execute `npm run test:e2e` (or equivalent from package.json)
|
||
- Ensure tests pass before CI setup
|
||
- If tests fail, HALT with message: "Fix failing tests before setting up CI/CD"
|
||
|
||
4. **Detect CI Platform**
|
||
- Check for existing CI configuration:
|
||
- `.github/workflows/*.yml` (GitHub Actions)
|
||
- `.gitlab-ci.yml` (GitLab CI)
|
||
- `.circleci/config.yml` (Circle CI)
|
||
- `Jenkinsfile` (Jenkins)
|
||
- If found, ask user: "Update existing CI configuration or create new?"
|
||
- If not found, detect platform from git remote:
|
||
- `github.com` → GitHub Actions (default)
|
||
- `gitlab.com` → GitLab CI
|
||
- Ask user if unable to auto-detect
|
||
|
||
5. **Read Environment Configuration**
|
||
- Check for `.nvmrc` to determine Node version
|
||
- Default to Node 20 LTS if not found
|
||
- Read `package.json` to identify dependencies (affects caching strategy)
|
||
|
||
**Halt Condition:** If preflight checks fail, stop immediately and report which requirement failed.
|
||
|
||
---
|
||
|
||
## Step 2: Scaffold CI Pipeline
|
||
|
||
### Actions
|
||
|
||
1. **Select CI Platform Template**
|
||
|
||
Based on detection or user preference, use the appropriate template:
|
||
|
||
**GitHub Actions** (`.github/workflows/test.yml`):
|
||
- Most common platform
|
||
- Excellent caching and matrix support
|
||
- Free for public repos, generous free tier for private
|
||
|
||
**GitLab CI** (`.gitlab-ci.yml`):
|
||
- Integrated with GitLab
|
||
- Built-in registry and runners
|
||
- Powerful pipeline features
|
||
|
||
**Circle CI** (`.circleci/config.yml`):
|
||
- Fast execution with parallelism
|
||
- Docker-first approach
|
||
- Enterprise features
|
||
|
||
**Jenkins** (`Jenkinsfile`):
|
||
- Self-hosted option
|
||
- Maximum customization
|
||
- Requires infrastructure management
|
||
|
||
2. **Generate Pipeline Configuration**
|
||
|
||
Use templates from `{installed_path}/` directory:
|
||
- `github-actions-template.yml`
|
||
- `gitlab-ci-template.yml`
|
||
|
||
**Key pipeline stages:**
|
||
|
||
```yaml
|
||
stages:
|
||
- lint # Code quality checks
|
||
- test # Test execution (parallel shards)
|
||
- burn-in # Flaky test detection
|
||
- report # Aggregate results and publish
|
||
```
|
||
|
||
3. **Configure Test Execution**
|
||
|
||
**Parallel Sharding:**
|
||
|
||
```yaml
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
shard: [1, 2, 3, 4]
|
||
|
||
steps:
|
||
- name: Run tests
|
||
run: npm run test:e2e -- --shard=${{ matrix.shard }}/${{ strategy.job-total }}
|
||
```
|
||
|
||
**Purpose:** Splits tests into N parallel jobs for faster execution (target: <10 min per shard)
|
||
|
||
4. **Add Burn-In Loop**
|
||
|
||
**Critical pattern from production systems:**
|
||
|
||
```yaml
|
||
burn-in:
|
||
name: Flaky Test Detection
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup Node
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version-file: '.nvmrc'
|
||
|
||
- name: Install dependencies
|
||
run: npm ci
|
||
|
||
- name: Run burn-in loop (10 iterations)
|
||
run: |
|
||
for i in {1..10}; do
|
||
echo "🔥 Burn-in iteration $i/10"
|
||
npm run test:e2e || exit 1
|
||
done
|
||
|
||
- name: Upload failure artifacts
|
||
if: failure()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: burn-in-failures
|
||
path: test-results/
|
||
retention-days: 30
|
||
```
|
||
|
||
**Purpose:** Runs tests multiple times to catch non-deterministic failures before they reach main branch.
|
||
|
||
**When to run:**
|
||
- On pull requests to main/develop
|
||
- Weekly on cron schedule
|
||
- After significant test infrastructure changes
|
||
|
||
5. **Configure Caching**
|
||
|
||
**Node modules cache:**
|
||
|
||
```yaml
|
||
- name: Cache dependencies
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: ~/.npm
|
||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-node-
|
||
```
|
||
|
||
**Browser binaries cache (Playwright):**
|
||
|
||
```yaml
|
||
- name: Cache Playwright browsers
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: ~/.cache/ms-playwright
|
||
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
|
||
```
|
||
|
||
**Purpose:** Reduces CI execution time by 2-5 minutes per run.
|
||
|
||
6. **Configure Artifact Collection**
|
||
|
||
**Failure artifacts only:**
|
||
|
||
```yaml
|
||
- name: Upload test results
|
||
if: failure()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: test-results-${{ matrix.shard }}
|
||
path: |
|
||
test-results/
|
||
playwright-report/
|
||
retention-days: 30
|
||
```
|
||
|
||
**Artifacts to collect:**
|
||
- Traces (Playwright) - full debugging context
|
||
- Screenshots - visual evidence of failures
|
||
- Videos - interaction playback
|
||
- HTML reports - detailed test results
|
||
- Console logs - error messages and warnings
|
||
|
||
7. **Add Retry Logic**
|
||
|
||
```yaml
|
||
- name: Run tests with retries
|
||
uses: nick-invision/retry@v2
|
||
with:
|
||
timeout_minutes: 30
|
||
max_attempts: 3
|
||
retry_on: error
|
||
command: npm run test:e2e
|
||
```
|
||
|
||
**Purpose:** Handles transient failures (network issues, race conditions)
|
||
|
||
8. **Configure Notifications** (Optional)
|
||
|
||
If `notify_on_failure` is enabled:
|
||
|
||
```yaml
|
||
- name: Notify on failure
|
||
if: failure()
|
||
uses: 8398a7/action-slack@v3
|
||
with:
|
||
status: ${{ job.status }}
|
||
text: 'Test failures detected in PR #${{ github.event.pull_request.number }}'
|
||
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
|
||
```
|
||
|
||
9. **Generate Helper Scripts**
|
||
|
||
**Selective testing script** (`scripts/test-changed.sh`):
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# Run only tests for changed files
|
||
|
||
CHANGED_FILES=$(git diff --name-only HEAD~1)
|
||
|
||
if echo "$CHANGED_FILES" | grep -q "src/.*\.ts$"; then
|
||
echo "Running affected tests..."
|
||
npm run test:e2e -- --grep="$(echo $CHANGED_FILES | sed 's/src\///g' | sed 's/\.ts//g')"
|
||
else
|
||
echo "No test-affecting changes detected"
|
||
fi
|
||
```
|
||
|
||
**Local mirror script** (`scripts/ci-local.sh`):
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# Mirror CI execution locally for debugging
|
||
|
||
echo "🔍 Running CI pipeline locally..."
|
||
|
||
# Lint
|
||
npm run lint || exit 1
|
||
|
||
# Tests
|
||
npm run test:e2e || exit 1
|
||
|
||
# Burn-in (reduced iterations)
|
||
for i in {1..3}; do
|
||
echo "🔥 Burn-in $i/3"
|
||
npm run test:e2e || exit 1
|
||
done
|
||
|
||
echo "✅ Local CI pipeline passed"
|
||
```
|
||
|
||
10. **Generate Documentation**
|
||
|
||
**CI README** (`docs/ci.md`):
|
||
- Pipeline stages and purpose
|
||
- How to run locally
|
||
- Debugging failed CI runs
|
||
- Secrets and environment variables needed
|
||
- Notification setup
|
||
- Badge URLs for README
|
||
|
||
**Secrets checklist** (`docs/ci-secrets-checklist.md`):
|
||
- Required secrets list (SLACK_WEBHOOK, etc.)
|
||
- Where to configure in CI platform
|
||
- Security best practices
|
||
|
||
---
|
||
|
||
## Step 3: Deliverables
|
||
|
||
### Primary Artifacts Created
|
||
|
||
1. **CI Configuration File**
|
||
- `.github/workflows/test.yml` (GitHub Actions)
|
||
- `.gitlab-ci.yml` (GitLab CI)
|
||
- `.circleci/config.yml` (Circle CI)
|
||
|
||
2. **Pipeline Stages**
|
||
- **Lint**: Code quality checks (ESLint, Prettier)
|
||
- **Test**: Parallel test execution (4 shards)
|
||
- **Burn-in**: Flaky test detection (10 iterations)
|
||
- **Report**: Result aggregation and publishing
|
||
|
||
3. **Helper Scripts**
|
||
- `scripts/test-changed.sh` - Selective testing
|
||
- `scripts/ci-local.sh` - Local CI mirror
|
||
- `scripts/burn-in.sh` - Standalone burn-in execution
|
||
|
||
4. **Documentation**
|
||
- `docs/ci.md` - CI pipeline guide
|
||
- `docs/ci-secrets-checklist.md` - Required secrets
|
||
- Inline comments in CI configuration
|
||
|
||
5. **Optimization Features**
|
||
- Dependency caching (npm, browser binaries)
|
||
- Parallel sharding (4 jobs default)
|
||
- Retry logic (2 retries on failure)
|
||
- Failure-only artifact upload
|
||
|
||
### Performance Targets
|
||
|
||
- **Lint stage**: <2 minutes
|
||
- **Test stage** (per shard): <10 minutes
|
||
- **Burn-in stage**: <30 minutes (10 iterations)
|
||
- **Total pipeline**: <45 minutes
|
||
|
||
**Speedup:** 20× faster than sequential execution through parallelism and caching.
|
||
|
||
---
|
||
|
||
## Important Notes
|
||
|
||
### Knowledge Base Integration
|
||
|
||
**Critical:** Consult `{project-root}/bmad/bmm/testarch/tea-index.csv` to identify and load relevant knowledge fragments:
|
||
|
||
- `ci-burn-in.md` - Burn-in loop patterns: 10-iteration detection, GitHub Actions workflow, shard orchestration, selective execution (678 lines, 4 examples)
|
||
- `selective-testing.md` - Changed test detection strategies: tag-based, spec filters, diff-based selection, promotion rules (727 lines, 4 examples)
|
||
- `visual-debugging.md` - Artifact collection best practices: trace viewer, HAR recording, custom artifacts, accessibility integration (522 lines, 5 examples)
|
||
- `test-quality.md` - CI-specific test quality criteria: deterministic tests, isolated with cleanup, explicit assertions, length/time optimization (658 lines, 5 examples)
|
||
- `playwright-config.md` - CI-optimized configuration: parallelization, artifact output, project dependencies, sharding (722 lines, 5 examples)
|
||
|
||
### CI Platform-Specific Guidance
|
||
|
||
**GitHub Actions:**
|
||
|
||
- Use `actions/cache` for caching
|
||
- Matrix strategy for parallelism
|
||
- Secrets in repository settings
|
||
- Free 2000 minutes/month for private repos
|
||
|
||
**GitLab CI:**
|
||
|
||
- Use `.gitlab-ci.yml` in root
|
||
- `cache:` directive for caching
|
||
- Parallel execution with `parallel: 4`
|
||
- Variables in project CI/CD settings
|
||
|
||
**Circle CI:**
|
||
|
||
- Use `.circleci/config.yml`
|
||
- Docker executors recommended
|
||
- Parallelism with `parallelism: 4`
|
||
- Context for shared secrets
|
||
|
||
### Burn-In Loop Strategy
|
||
|
||
**When to run:**
|
||
|
||
- ✅ On PRs to main/develop branches
|
||
- ✅ Weekly on schedule (cron)
|
||
- ✅ After test infrastructure changes
|
||
- ❌ Not on every commit (too slow)
|
||
|
||
**Iterations:**
|
||
|
||
- **10 iterations** for thorough detection
|
||
- **3 iterations** for quick feedback
|
||
- **100 iterations** for high-confidence stability
|
||
|
||
**Failure threshold:**
|
||
|
||
- Even ONE failure in burn-in → tests are flaky
|
||
- Must fix before merging
|
||
|
||
### Artifact Retention
|
||
|
||
**Failure artifacts only:**
|
||
|
||
- Saves storage costs
|
||
- Maintains debugging capability
|
||
- 30-day retention default
|
||
|
||
**Artifact types:**
|
||
|
||
- Traces (Playwright) - 5-10 MB per test
|
||
- Screenshots - 100-500 KB per screenshot
|
||
- Videos - 2-5 MB per test
|
||
- HTML reports - 1-2 MB per run
|
||
|
||
### Selective Testing
|
||
|
||
**Detect changed files:**
|
||
|
||
```bash
|
||
git diff --name-only HEAD~1
|
||
```
|
||
|
||
**Run affected tests only:**
|
||
|
||
- Faster feedback for small changes
|
||
- Full suite still runs on main branch
|
||
- Reduces CI time by 50-80% for focused PRs
|
||
|
||
**Trade-off:**
|
||
|
||
- May miss integration issues
|
||
- Run full suite at least on merge
|
||
|
||
### Local CI Mirror
|
||
|
||
**Purpose:** Debug CI failures locally
|
||
|
||
**Usage:**
|
||
|
||
```bash
|
||
./scripts/ci-local.sh
|
||
```
|
||
|
||
**Mirrors CI environment:**
|
||
|
||
- Same Node version
|
||
- Same test command
|
||
- Same stages (lint → test → burn-in)
|
||
- Reduced burn-in iterations (3 vs 10)
|
||
|
||
---
|
||
|
||
## Output Summary
|
||
|
||
After completing this workflow, provide a summary:
|
||
|
||
```markdown
|
||
## CI/CD Pipeline Complete
|
||
|
||
**Platform**: GitHub Actions (or GitLab CI, etc.)
|
||
|
||
**Artifacts Created**:
|
||
|
||
- ✅ Pipeline configuration: .github/workflows/test.yml
|
||
- ✅ Burn-in loop: 10 iterations for flaky detection
|
||
- ✅ Parallel sharding: 4 jobs for fast execution
|
||
- ✅ Caching: Dependencies + browser binaries
|
||
- ✅ Artifact collection: Failure-only traces/screenshots/videos
|
||
- ✅ Helper scripts: test-changed.sh, ci-local.sh, burn-in.sh
|
||
- ✅ Documentation: docs/ci.md, docs/ci-secrets-checklist.md
|
||
|
||
**Performance:**
|
||
|
||
- Lint: <2 min
|
||
- Test (per shard): <10 min
|
||
- Burn-in: <30 min
|
||
- Total: <45 min (20× speedup vs sequential)
|
||
|
||
**Next Steps**:
|
||
|
||
1. Commit CI configuration: `git add .github/workflows/test.yml && git commit -m "ci: add test pipeline"`
|
||
2. Push to remote: `git push`
|
||
3. Configure required secrets in CI platform settings (see docs/ci-secrets-checklist.md)
|
||
4. Open a PR to trigger first CI run
|
||
5. Monitor pipeline execution and adjust parallelism if needed
|
||
|
||
**Knowledge Base References Applied**:
|
||
|
||
- Burn-in loop pattern (ci-burn-in.md)
|
||
- Selective testing strategy (selective-testing.md)
|
||
- Artifact collection (visual-debugging.md)
|
||
- Test quality criteria (test-quality.md)
|
||
```
|
||
|
||
---
|
||
|
||
## Validation
|
||
|
||
After completing all steps, verify:
|
||
|
||
- [ ] CI configuration file created and syntactically valid
|
||
- [ ] Burn-in loop configured (10 iterations)
|
||
- [ ] Parallel sharding enabled (4 jobs)
|
||
- [ ] Caching configured (dependencies + browsers)
|
||
- [ ] Artifact collection on failure only
|
||
- [ ] Helper scripts created and executable (`chmod +x`)
|
||
- [ ] Documentation complete (ci.md, secrets checklist)
|
||
- [ ] No errors or warnings during scaffold
|
||
|
||
Refer to `checklist.md` for comprehensive validation criteria.
|