mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-13 09:42:40 +02:00
468 lines
9.8 KiB
Markdown
468 lines
9.8 KiB
Markdown
# CI/CD Integration
|
|
|
|
## Table of Contents
|
|
|
|
1. [GitHub Actions](#github-actions)
|
|
2. [Docker](#docker)
|
|
3. [Reporting](#reporting)
|
|
4. [Sharding](#sharding)
|
|
5. [Environment Management](#environment-management)
|
|
6. [Caching](#caching)
|
|
|
|
## GitHub Actions
|
|
|
|
### Basic Workflow
|
|
|
|
```yaml
|
|
# .github/workflows/playwright.yml
|
|
name: Playwright Tests
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
test:
|
|
timeout-minutes: 60
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: "npm"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Install Playwright browsers
|
|
run: npx playwright install --with-deps
|
|
|
|
- name: Run Playwright tests
|
|
run: npx playwright test
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
if: ${{ !cancelled() }}
|
|
with:
|
|
name: playwright-report
|
|
path: playwright-report/
|
|
retention-days: 30
|
|
```
|
|
|
|
### With Sharding
|
|
|
|
```yaml
|
|
name: Playwright Tests
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
test:
|
|
timeout-minutes: 60
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
shardIndex: [1, 2, 3, 4]
|
|
shardTotal: [4]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: "npm"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Install Playwright browsers
|
|
run: npx playwright install --with-deps
|
|
|
|
- name: Run Playwright tests
|
|
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
|
|
|
- name: Upload blob report
|
|
if: ${{ !cancelled() }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: blob-report-${{ matrix.shardIndex }}
|
|
path: blob-report
|
|
retention-days: 1
|
|
|
|
merge-reports:
|
|
if: ${{ !cancelled() }}
|
|
needs: [test]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: "npm"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Download blob reports
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: all-blob-reports
|
|
pattern: blob-report-*
|
|
merge-multiple: true
|
|
|
|
- name: Merge reports
|
|
run: npx playwright merge-reports --reporter html ./all-blob-reports
|
|
|
|
- name: Upload HTML report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: html-report
|
|
path: playwright-report
|
|
retention-days: 14
|
|
```
|
|
|
|
### With Container
|
|
|
|
```yaml
|
|
jobs:
|
|
test:
|
|
timeout-minutes: 60
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
# Use latest or more appropriate playwright version (match package.json)
|
|
image: mcr.microsoft.com/playwright:v1.40.0-jammy
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: "npm"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Run tests
|
|
run: npx playwright test
|
|
env:
|
|
HOME: /root
|
|
```
|
|
|
|
## Docker
|
|
|
|
### Dockerfile
|
|
|
|
```dockerfile
|
|
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
|
|
|
|
WORKDIR /app
|
|
|
|
COPY package*.json ./
|
|
RUN npm ci
|
|
|
|
COPY . .
|
|
|
|
CMD ["npx", "playwright", "test"]
|
|
```
|
|
|
|
### Docker Compose
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: "3.8"
|
|
|
|
services:
|
|
playwright:
|
|
build: .
|
|
volumes:
|
|
- ./playwright-report:/app/playwright-report
|
|
- ./test-results:/app/test-results
|
|
environment:
|
|
- CI=true
|
|
- BASE_URL=http://app:3000
|
|
depends_on:
|
|
- app
|
|
|
|
app:
|
|
build: ./app
|
|
ports:
|
|
- "3000:3000"
|
|
```
|
|
|
|
### Run with Docker
|
|
|
|
```bash
|
|
# Build and run
|
|
docker build -t playwright-tests .
|
|
docker run --rm -v $(pwd)/playwright-report:/app/playwright-report playwright-tests
|
|
|
|
# With docker-compose
|
|
docker-compose run --rm playwright
|
|
```
|
|
|
|
## Reporting
|
|
|
|
### Configuration
|
|
|
|
```typescript
|
|
// playwright.config.ts
|
|
export default defineConfig({
|
|
reporter: [
|
|
// Always generate
|
|
["html", { outputFolder: "playwright-report" }],
|
|
|
|
// Console output
|
|
["list"],
|
|
|
|
// CI-friendly
|
|
["github"], // GitHub Actions annotations
|
|
|
|
// JUnit for CI integration
|
|
["junit", { outputFile: "results.xml" }],
|
|
|
|
// JSON for custom processing
|
|
["json", { outputFile: "results.json" }],
|
|
|
|
// Blob for merging shards
|
|
["blob", { outputDir: "blob-report" }],
|
|
],
|
|
});
|
|
```
|
|
|
|
### CI-Specific Reporter
|
|
|
|
```typescript
|
|
export default defineConfig({
|
|
reporter: process.env.CI
|
|
? [["github"], ["blob"], ["html"]]
|
|
: [["list"], ["html"]],
|
|
});
|
|
```
|
|
|
|
## Sharding
|
|
|
|
### Command Line
|
|
|
|
```bash
|
|
# Split into 4 shards, run shard 1
|
|
npx playwright test --shard=1/4
|
|
|
|
# Run shard 2
|
|
npx playwright test --shard=2/4
|
|
```
|
|
|
|
### Configuration
|
|
|
|
```typescript
|
|
// playwright.config.ts
|
|
export default defineConfig({
|
|
// Evenly distribute tests across shards
|
|
fullyParallel: true,
|
|
|
|
// For blob reporter to merge later
|
|
reporter: process.env.CI ? [["blob"]] : [["html"]],
|
|
});
|
|
```
|
|
|
|
### Merge Sharded Reports
|
|
|
|
```bash
|
|
# After all shards complete, merge blob reports
|
|
npx playwright merge-reports --reporter html ./all-blob-reports
|
|
```
|
|
|
|
## Environment Management
|
|
|
|
### Environment Variables
|
|
|
|
```typescript
|
|
// playwright.config.ts
|
|
import { defineConfig } from "@playwright/test";
|
|
import dotenv from "dotenv";
|
|
|
|
// Load env file based on environment
|
|
dotenv.config({ path: `.env.${process.env.NODE_ENV || "development"}` });
|
|
|
|
export default defineConfig({
|
|
use: {
|
|
baseURL: process.env.BASE_URL || "http://localhost:3000",
|
|
},
|
|
});
|
|
```
|
|
|
|
### Multiple Environments
|
|
|
|
```yaml
|
|
# .github/workflows/playwright.yml
|
|
jobs:
|
|
test:
|
|
strategy:
|
|
matrix:
|
|
environment: [staging, production]
|
|
steps:
|
|
- name: Run tests
|
|
run: npx playwright test
|
|
env:
|
|
BASE_URL: ${{ matrix.environment == 'staging' && 'https://staging.example.com' || 'https://example.com' }}
|
|
TEST_USER: ${{ secrets[format('TEST_USER_{0}', matrix.environment)] }}
|
|
```
|
|
|
|
### Secrets Management
|
|
|
|
```yaml
|
|
# GitHub Actions secrets
|
|
- name: Run tests
|
|
run: npx playwright test
|
|
env:
|
|
TEST_EMAIL: ${{ secrets.TEST_EMAIL }}
|
|
TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
|
|
```
|
|
|
|
```typescript
|
|
// tests use environment variables
|
|
test("login", async ({ page }) => {
|
|
await page.getByLabel("Email").fill(process.env.TEST_EMAIL!);
|
|
await page.getByLabel("Password").fill(process.env.TEST_PASSWORD!);
|
|
});
|
|
```
|
|
|
|
## Caching
|
|
|
|
### Cache Playwright Browsers
|
|
|
|
```yaml
|
|
- name: Cache Playwright browsers
|
|
uses: actions/cache@v4
|
|
id: playwright-cache
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
|
|
|
|
- name: Install Playwright browsers
|
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
run: npx playwright install --with-deps
|
|
|
|
- name: Install system deps only
|
|
if: steps.playwright-cache.outputs.cache-hit == 'true'
|
|
run: npx playwright install-deps
|
|
```
|
|
|
|
### Cache Node Modules
|
|
|
|
```yaml
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: "npm"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
```
|
|
|
|
## Tag-Based Test Filtering
|
|
|
|
### Run Specific Tags in CI
|
|
|
|
```yaml
|
|
# Run smoke tests on PR
|
|
- name: Run smoke tests
|
|
run: npx playwright test --grep @smoke
|
|
|
|
# Run full regression nightly
|
|
- name: Run regression
|
|
run: npx playwright test --grep @regression
|
|
|
|
# Exclude flaky tests
|
|
- name: Run stable tests
|
|
run: npx playwright test --grep-invert @flaky
|
|
```
|
|
|
|
### PR vs Nightly Strategy
|
|
|
|
```yaml
|
|
# .github/workflows/pr.yml - Fast feedback
|
|
- name: Run critical tests
|
|
run: npx playwright test --grep "@smoke|@critical"
|
|
|
|
# .github/workflows/nightly.yml - Full coverage
|
|
- name: Run all tests
|
|
run: npx playwright test --grep-invert @flaky
|
|
```
|
|
|
|
### Tag Filtering in Config
|
|
|
|
```typescript
|
|
// playwright.config.ts
|
|
export default defineConfig({
|
|
grep: process.env.CI ? /@smoke|@critical/ : undefined,
|
|
grepInvert: process.env.CI ? /@flaky/ : undefined,
|
|
});
|
|
```
|
|
|
|
### Project-Based Tag Filtering
|
|
|
|
```typescript
|
|
// playwright.config.ts
|
|
export default defineConfig({
|
|
projects: [
|
|
{
|
|
name: "smoke",
|
|
grep: /@smoke/,
|
|
},
|
|
{
|
|
name: "regression",
|
|
grepInvert: /@smoke/,
|
|
},
|
|
],
|
|
});
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
| Practice | Benefit |
|
|
| ----------------------------- | ------------------------- |
|
|
| Use `npm ci` | Deterministic installs |
|
|
| Run headless in CI | Faster, no display needed |
|
|
| Set retries in CI only | Handle flakiness |
|
|
| Upload artifacts on failure | Debug failures |
|
|
| Use sharding for large suites | Faster execution |
|
|
| Cache browsers | Faster setup |
|
|
| Use blob reporter for shards | Merge reports correctly |
|
|
| Use tags for PR vs nightly | Fast feedback + coverage |
|
|
| Exclude @flaky in CI | Stable pipeline |
|
|
|
|
## CI Configuration Reference
|
|
|
|
```typescript
|
|
// playwright.config.ts - CI optimized
|
|
export default defineConfig({
|
|
testDir: "./tests",
|
|
fullyParallel: true,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: process.env.CI ? 2 : 0,
|
|
workers: process.env.CI ? 1 : undefined,
|
|
reporter: process.env.CI
|
|
? [["github"], ["blob"], ["html"]]
|
|
: [["list"], ["html"]],
|
|
use: {
|
|
baseURL: process.env.BASE_URL || "http://localhost:3000",
|
|
trace: "on-first-retry",
|
|
screenshot: "only-on-failure",
|
|
video: "on-first-retry",
|
|
},
|
|
});
|
|
```
|
|
|
|
## Related References
|
|
|
|
- **Test tags**: See [test-tags.md](../core/test-tags.md) for tagging and filtering patterns
|
|
- **Performance optimization**: See [performance.md](performance.md) for sharding and parallelization
|
|
- **Debugging CI failures**: See [debugging.md](../debugging/debugging.md) for troubleshooting
|
|
- **Test reporting**: See [debugging.md](../debugging/debugging.md) for trace viewer usage
|