Skip to content
🤖 Consolidated, AI-optimized BMAD docs: llms-full.txt. Fetch this plain text file for complete context.

How to Set Up CI Pipeline with TEA

Use TEA’s ci workflow to scaffold production-ready CI/CD configuration for automated test execution with selective testing, parallel sharding, and flakiness detection.

  • Need to automate test execution in CI/CD
  • Want selective testing (only run affected tests)
  • Need parallel execution for faster feedback
  • Want burn-in loops for flakiness detection
  • Setting up new CI/CD pipeline
  • Optimizing existing CI/CD workflow
  • BMad Method installed
  • TEA agent available
  • Test framework configured (run framework first)
  • Tests written (have something to run in CI)
  • CI/CD platform access (GitHub Actions, GitLab CI, etc.)

Start a fresh chat and load TEA:

tea
ci

TEA will ask which platform you’re using.

Supported Platforms:

  • GitHub Actions (most common)
  • GitLab CI
  • Circle CI
  • Jenkins
  • Other (TEA provides generic template)

Example:

GitHub Actions

TEA will ask about your test execution strategy.

Question: “What’s your repository structure?”

Options:

  • Single app - One application in root
  • Monorepo - Multiple apps/packages
  • Monorepo with affected detection - Only test changed packages

Example:

Monorepo with multiple apps
Need selective testing for changed packages only

Question: “Want to shard tests for parallel execution?”

Options:

  • No sharding - Run tests sequentially
  • Shard by workers - Split across N workers
  • Shard by file - Each file runs in parallel

Example:

Yes, shard across 4 workers for faster execution

Why Shard?

  • 4 workers: 20-minute suite → 5 minutes
  • Better resource usage: Utilize CI runners efficiently
  • Faster feedback: Developers wait less

Question: “Want burn-in loops for flakiness detection?”

Options:

  • No burn-in - Run tests once
  • PR burn-in - Run tests multiple times on PRs
  • Nightly burn-in - Dedicated flakiness detection job

Example:

Yes, run tests 5 times on PRs to catch flaky tests early

Why Burn-In?

  • Catches flaky tests before they merge
  • Prevents intermittent CI failures
  • Builds confidence in test suite

TEA generates platform-specific workflow files.

name: Test Suite
on:
pull_request:
push:
branches: [main, develop]
schedule:
- cron: '0 2 * * *' # Nightly at 2 AM
jobs:
# Main test job with sharding
test:
name: Test (Shard ${{ matrix.shard }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run tests
run: npx playwright test --shard=${{ matrix.shard }}/4
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.shard }}
path: test-results/
retention-days: 7
- name: Upload test report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report-${{ matrix.shard }}
path: playwright-report/
retention-days: 7
# Burn-in job for flakiness detection (PRs only)
burn-in:
name: Burn-In (Flakiness Detection)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run burn-in loop
run: |
for i in {1..5}; do
echo "=== Burn-in iteration $i/5 ==="
npx playwright test --grep-invert "@skip" || exit 1
done
- name: Upload burn-in results
if: failure()
uses: actions/upload-artifact@v4
with:
name: burn-in-failures
path: test-results/
# Selective testing (changed files only)
selective:
name: Selective Tests
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for git diff
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run selective tests
run: npm run test:changed
variables:
NODE_VERSION: "18"
stages:
- test
- burn-in
# Test job with parallel execution
test:
stage: test
image: node:$NODE_VERSION
parallel: 4
script:
- npm ci
- npx playwright install --with-deps
- npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
artifacts:
when: always
paths:
- test-results/
- playwright-report/
expire_in: 7 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# Burn-in job for flakiness detection
burn-in:
stage: burn-in
image: node:$NODE_VERSION
script:
- npm ci
- npx playwright install --with-deps
- |
for i in {1..5}; do
echo "=== Burn-in iteration $i/5 ==="
npx playwright test || exit 1
done
artifacts:
when: on_failure
paths:
- test-results/
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

Option 1: Classic Burn-In (Playwright Built-In)

{
"scripts": {
"test": "playwright test",
"test:burn-in": "playwright test --repeat-each=5 --retries=0"
}
}

How it works:

  • Runs every test 5 times
  • Fails if any iteration fails
  • Detects flakiness before merge

Use when: Small test suite, want to run everything multiple times


Option 2: Smart Burn-In (Playwright Utils)

If tea_use_playwright_utils: true:

scripts/burn-in-changed.ts:

import { runBurnIn } from '@seontechnologies/playwright-utils/burn-in';
await runBurnIn({
configPath: 'playwright.burn-in.config.ts',
baseBranch: 'main'
});

playwright.burn-in.config.ts:

import type { BurnInConfig } from '@seontechnologies/playwright-utils/burn-in';
const config: BurnInConfig = {
skipBurnInPatterns: ['**/config/**', '**/*.md', '**/*types*'],
burnInTestPercentage: 0.3,
burnIn: { repeatEach: 5, retries: 0 }
};
export default config;

package.json:

{
"scripts": {
"test:burn-in": "tsx scripts/burn-in-changed.ts"
}
}

How it works:

  • Git diff analysis (only affected tests)
  • Smart filtering (skip configs, docs, types)
  • Volume control (run 30% of affected tests)
  • Each test runs 5 times

Use when: Large test suite, want intelligent selection


Comparison:

FeatureClassic Burn-InSmart Burn-In (PW-Utils)
Changed 1 fileRuns all 500 tests × 5 = 2500 runsRuns 3 affected tests × 5 = 15 runs
Config changeRuns all testsSkips (no tests affected)
Type changeRuns all testsSkips (no runtime impact)
SetupZero configRequires config file

Recommendation: Start with classic (simple), upgrade to smart (faster) when suite grows.

TEA provides a secrets checklist.

Required Secrets (add to CI/CD platform):

## GitHub Actions Secrets
Repository Settings → Secrets and variables → Actions
### Required
- None (tests run without external auth)
### Optional
- `TEST_USER_EMAIL` - Test user credentials
- `TEST_USER_PASSWORD` - Test user password
- `API_BASE_URL` - API endpoint for tests
- `DATABASE_URL` - Test database (if needed)

How to Add Secrets:

GitHub Actions:

  1. Go to repo Settings → Secrets → Actions
  2. Click “New repository secret”
  3. Add name and value
  4. Use in workflow: ${{ secrets.TEST_USER_EMAIL }}

GitLab CI:

  1. Go to Project Settings → CI/CD → Variables
  2. Add variable name and value
  3. Use in workflow: $TEST_USER_EMAIL

Commit the workflow file:

Terminal window
git add .github/workflows/test.yml
git commit -m "ci: add automated test pipeline"
git push

Watch the CI run:

  • GitHub Actions: Go to Actions tab
  • GitLab CI: Go to CI/CD → Pipelines
  • Circle CI: Go to Pipelines

Expected Result:

✓ test (shard 1/4) - 3m 24s
✓ test (shard 2/4) - 3m 18s
✓ test (shard 3/4) - 3m 31s
✓ test (shard 4/4) - 3m 15s
✓ burn-in - 15m 42s

Create test PR:

Terminal window
git checkout -b test-ci-setup
echo "# Test" > test.md
git add test.md
git commit -m "test: verify CI setup"
git push -u origin test-ci-setup

Open PR and verify:

  • Tests run automatically
  • Burn-in runs (if configured for PRs)
  • Selective tests run (if applicable)
  • All checks pass ✓
  • On every PR - Catch issues before merge
  • On every push to main - Protect production
  • Nightly - Comprehensive regression testing
  • 4x faster feedback - Shard across multiple workers
  • Efficient resource usage - Maximize CI runner utilization
  • Run only affected tests - Git diff-based selection
  • Faster PR feedback - Don’t run entire suite every time
  • Burn-in loops - Run tests multiple times
  • Early detection - Catch flaky tests in PRs
  • Confidence building - Know tests are reliable
  • Test results - Saved for 7 days
  • Screenshots - On test failures
  • Videos - Full test recordings
  • Traces - Playwright trace files for debugging

Week 1: Basic pipeline

- Run tests on PR
- Single worker (no sharding)

Week 2: Add parallelization

- Shard across 4 workers
- Faster feedback

Week 3: Add selective testing

- Git diff-based selection
- Skip unaffected tests

Week 4: Add burn-in

- Detect flaky tests
- Run on PR and nightly

Goal: PR feedback in < 5 minutes

Strategies:

  • Shard tests across workers (4 workers = 4x faster)
  • Use selective testing (run 20% of tests, not 100%)
  • Cache dependencies (actions/cache, cache: 'npm')
  • Run smoke tests first, full suite after

Example fast workflow:

jobs:
smoke:
# Run critical path tests (2 min)
run: npm run test:smoke
full:
needs: smoke
# Run full suite only if smoke passes (10 min)
run: npm test

Tag tests for selective execution:

// Critical path tests (always run)
test('@critical should login', async ({ page }) => { });
// Smoke tests (run first)
test('@smoke should load homepage', async ({ page }) => { });
// Slow tests (run nightly only)
test('@slow should process large file', async ({ page }) => { });
// Skip in CI
test('@local-only should use local service', async ({ page }) => { });

In CI:

Terminal window
# PR: Run critical and smoke only
npx playwright test --grep "@critical|@smoke"
# Nightly: Run everything except local-only
npx playwright test --grep-invert "@local-only"

Track metrics:

## CI Metrics
| Metric | Target | Current | Status |
|--------|--------|---------|--------|
| PR feedback time | < 5 min | 3m 24s | ✅ |
| Full suite time | < 15 min | 12m 18s | ✅ |
| Flakiness rate | < 1% | 0.3% | ✅ |
| CI cost/month | < $100 | $75 | ✅ |

When burn-in detects flakiness:

  1. Quarantine flaky test:
test.skip('flaky test - investigating', async ({ page }) => {
// TODO: Fix flakiness
});
  1. Investigate with trace viewer:
Terminal window
npx playwright show-trace test-results/trace.zip
  1. Fix root cause:
  • Add network-first patterns
  • Remove hard waits
  • Fix race conditions
  1. Verify fix:
Terminal window
npm run test:burn-in -- tests/flaky.spec.ts --repeat 20

Don’t commit secrets to code:

# ❌ Bad
- run: API_KEY=sk-1234... npm test
# ✅ Good
- run: npm test
env:
API_KEY: ${{ secrets.API_KEY }}

Use environment-specific secrets:

  • STAGING_API_URL
  • PROD_API_URL
  • TEST_API_URL

Speed up CI with caching:

# Cache node_modules
- uses: actions/setup-node@v4
with:
cache: 'npm'
# Cache Playwright browsers
- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('package-lock.json') }}

Symptoms:

  • Green locally, red in CI
  • “Works on my machine”

Common Causes:

  • Different Node version
  • Different browser version
  • Missing environment variables
  • Timezone differences
  • Race conditions (CI slower)

Solutions:

# Pin Node version
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# Pin browser versions
- run: npx playwright install --with-deps chromium@1.40.0
# Set timezone
env:
TZ: 'America/New_York'

Problem: CI takes 30+ minutes, developers wait too long.

Solutions:

  1. Shard tests: 4 workers = 4x faster
  2. Selective testing: Only run affected tests on PR
  3. Smoke tests first: Run critical path (2 min), full suite after
  4. Cache dependencies: npm ci with cache
  5. Optimize tests: Remove slow tests, hard waits

Problem: Burn-in job fails every time.

Cause: Test suite is flaky.

Solution:

  1. Identify flaky tests (check which iteration fails)
  2. Fix flaky tests using test-review
  3. Re-run burn-in on specific files:
Terminal window
npm run test:burn-in tests/flaky.spec.ts

Problem: Using too many CI minutes, hitting plan limit.

Solutions:

  1. Run full suite only on main branch
  2. Use selective testing on PRs
  3. Run expensive tests nightly only
  4. Self-host runners (for GitHub Actions)

Generated with BMad Method - TEA (Test Architect)