8.9 KiB
Local CI Testing Guide
Run CI/CD pipelines locally before pushing to verify your changes.
Quick Start
Prerequisites
- Docker Desktop (Windows/macOS) or Docker Engine (Linux)
- .NET 10 SDK (download)
- Git
- Bash (Linux/macOS native, Windows via WSL2 or Git Bash)
- act (optional, for workflow simulation) - install
Installation
-
Copy environment template:
cp devops/ci-local/.env.local.sample devops/ci-local/.env.local -
(Optional) Install act for workflow simulation:
# macOS brew install act # Linux curl -sSL https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash # Windows (via Chocolatey) choco install act-cli -
(Optional) Build CI Docker image:
docker build -t stellaops-ci:local -f devops/docker/Dockerfile.ci .
Usage
Basic Commands
# Quick smoke test (~2 min)
./devops/scripts/local-ci.sh smoke
# Full PR-gating suite (~15 min)
./devops/scripts/local-ci.sh pr
# Test specific module
./devops/scripts/local-ci.sh module --module Scanner
# Auto-detect changed modules
./devops/scripts/local-ci.sh module
# Simulate workflow
./devops/scripts/local-ci.sh workflow --workflow test-matrix
# Release dry-run
./devops/scripts/local-ci.sh release --dry-run
# Full test suite (~45 min)
./devops/scripts/local-ci.sh full
Windows (PowerShell)
# Quick smoke test
.\devops\scripts\local-ci.ps1 smoke
# Full PR check
.\devops\scripts\local-ci.ps1 pr
# With options
.\devops\scripts\local-ci.ps1 pr -Verbose -Docker
Modes
smoke (~2 minutes)
Quick validation before pushing. Runs only Unit tests.
./devops/scripts/local-ci.sh smoke
What it does:
- Builds the solution
- Runs Unit tests
- Reports pass/fail
pr (~15 minutes)
Full PR-gating suite matching CI exactly. Run this before opening a PR.
./devops/scripts/local-ci.sh pr
What it does:
- Starts CI services (PostgreSQL, Valkey)
- Builds with warnings-as-errors
- Runs all PR-gating categories:
- Unit
- Architecture
- Contract
- Integration
- Security
- Golden
- Generates TRX reports
- Stops CI services
module
Test only the modules you've changed. Detects changes via git diff.
# Auto-detect changed modules
./devops/scripts/local-ci.sh module
# Test specific module
./devops/scripts/local-ci.sh module --module Scanner
./devops/scripts/local-ci.sh module --module Concelier
./devops/scripts/local-ci.sh module --module Authority
Available modules: Scanner, Concelier, Authority, Policy, Attestor, EvidenceLocker, ExportCenter, Findings, SbomService, Notify, Router, Cryptography, AirGap, Cli, AdvisoryAI, ReachGraph, Orchestrator, PacksRegistry, Replay, Aoc, IssuerDirectory, Telemetry, Signals
workflow
Simulate a specific Gitea Actions workflow using act.
# Simulate test-matrix workflow
./devops/scripts/local-ci.sh workflow --workflow test-matrix
# Simulate build-test-deploy
./devops/scripts/local-ci.sh workflow --workflow build-test-deploy
Requirements:
actmust be installed- CI Docker image built (
stellaops-ci:local)
release
Dry-run release pipeline to verify release artifacts.
./devops/scripts/local-ci.sh release --dry-run
What it does:
- Builds all modules
- Validates CLI packaging
- Validates Helm chart
- Shows what would be released
- Does NOT publish anything
full (~45 minutes)
Complete test suite including extended categories.
./devops/scripts/local-ci.sh full
Categories run:
- PR-Gating: Unit, Architecture, Contract, Integration, Security, Golden
- Extended: Performance, Benchmark, AirGap, Chaos, Determinism, Resilience, Observability
Options
| Option | Description |
|---|---|
--category <cat> |
Run specific test category |
--module <name> |
Test specific module |
--workflow <name> |
Workflow to simulate |
--docker |
Force Docker execution |
--native |
Force native execution |
--act |
Force act execution |
--parallel <n> |
Parallel test runners |
--verbose |
Verbose output |
--dry-run |
Show what would run |
--rebuild |
Force rebuild CI image |
--no-services |
Skip CI services |
--keep-services |
Keep services running after tests |
Test Categories
PR-Gating (Required for merge)
| Category | Purpose | Time |
|---|---|---|
| Unit | Component isolation tests | ~3 min |
| Architecture | Dependency rules | ~2 min |
| Contract | API compatibility | ~2 min |
| Integration | Database/service tests | ~8 min |
| Security | Security assertions | ~3 min |
| Golden | Corpus-based validation | ~3 min |
Extended (On-demand)
| Category | Purpose | Time |
|---|---|---|
| Performance | Latency/throughput | ~20 min |
| Benchmark | BenchmarkDotNet | ~30 min |
| Determinism | Reproducibility | ~15 min |
| AirGap | Offline operation | ~15 min |
| Chaos | Resilience testing | ~20 min |
CI Services
The local CI uses Docker Compose to run required services.
Services Started
| Service | Port | Purpose |
|---|---|---|
| postgres-ci | 5433 | PostgreSQL 16 for tests |
| valkey-ci | 6380 | Cache/messaging tests |
| nats-ci | 4223 | Message queue tests |
| mock-registry | 5001 | Container registry |
| minio-ci | 9100 | S3-compatible storage |
Manual Service Management
# Start services
docker compose -f devops/compose/docker-compose.ci.yaml up -d
# Check status
docker compose -f devops/compose/docker-compose.ci.yaml ps
# View logs
docker compose -f devops/compose/docker-compose.ci.yaml logs postgres-ci
# Stop services
docker compose -f devops/compose/docker-compose.ci.yaml down
# Stop and remove volumes
docker compose -f devops/compose/docker-compose.ci.yaml down -v
Configuration
Environment Variables
Copy the template and customize:
cp devops/ci-local/.env.local.sample devops/ci-local/.env.local
Key variables:
# Database
STELLAOPS_TEST_POSTGRES_CONNECTION="Host=localhost;Port=5433;..."
# Cache
VALKEY_CONNECTION_STRING="localhost:6380"
# Execution
LOCAL_CI_MODE=docker # docker, native, act
LOCAL_CI_PARALLEL=4 # Parallel jobs
LOCAL_CI_VERBOSE=false # Verbose output
Act Configuration
The .actrc file configures act for workflow simulation:
--platform ubuntu-22.04=stellaops-ci:local
--env-file devops/ci-local/.env.local
--bind
--reuse
Troubleshooting
Docker Issues
# Reset CI services
docker compose -f devops/compose/docker-compose.ci.yaml down -v
# Rebuild CI image
docker build --no-cache -t stellaops-ci:local -f devops/docker/Dockerfile.ci .
# Check Docker is running
docker info
Test Failures
# Run with verbose output
./devops/scripts/local-ci.sh pr --verbose
# Run specific category
./devops/scripts/local-ci.sh pr --category Unit
# Check logs
cat out/local-ci/logs/Unit-*.log
Act Issues
# List available workflows
act -l
# Dry run workflow
act -n pull_request -W .gitea/workflows/test-matrix.yml
# Debug mode
act --verbose pull_request
Windows Issues
# Check WSL is installed
wsl --status
# Install WSL if needed
wsl --install
# Check Git Bash
& "C:\Program Files\Git\bin\bash.exe" --version
Results
Test results are saved to out/local-ci/:
out/local-ci/
├── trx/ # TRX test reports
│ ├── Unit-20250128_120000.trx
│ ├── Integration-20250128_120000.trx
│ └── ...
└── logs/ # Execution logs
├── Unit-20250128_120000.log
└── ...
Viewing Results
# List TRX files
ls -la out/local-ci/trx/
# View test log
cat out/local-ci/logs/Unit-*.log | less
Examples
Pre-Push Workflow
# 1. Quick validation
./devops/scripts/local-ci.sh smoke
# 2. If smoke passes, run full PR check
./devops/scripts/local-ci.sh pr
# 3. Push your changes
git push origin feature/my-branch
Module Development
# 1. Make changes to Scanner module
# 2. Run module-specific tests
./devops/scripts/local-ci.sh module --module Scanner
# 3. If passes, run full PR check before PR
./devops/scripts/local-ci.sh pr
Debugging Test Failures
# 1. Run with verbose output
./devops/scripts/local-ci.sh pr --verbose --category Unit
# 2. Check the log
cat out/local-ci/logs/Unit-*.log
# 3. Run specific test directly
dotnet test src/Scanner/__Tests/StellaOps.Scanner.Tests/StellaOps.Scanner.Tests.csproj \
--filter "Category=Unit" \
--verbosity detailed