- Implement ProofChainTestFixture for PostgreSQL-backed integration tests. - Create StellaOps.Integration.ProofChain project with necessary dependencies. - Add ReachabilityIntegrationTests to validate call graph extraction and reachability analysis. - Introduce ReachabilityTestFixture for managing corpus and fixture paths. - Establish StellaOps.Integration.Reachability project with required references. - Develop UnknownsWorkflowTests to cover the unknowns lifecycle: detection, ranking, escalation, and resolution. - Create StellaOps.Integration.Unknowns project with dependencies for unknowns workflow.
376 lines
12 KiB
YAML
376 lines
12 KiB
YAML
# Sprint 3500.0004.0003 - T6: Integration Tests CI Gate
|
|
# Runs integration tests on PR and gates merges on failures
|
|
|
|
name: integration-tests-gate
|
|
|
|
on:
|
|
pull_request:
|
|
branches: [main, develop]
|
|
paths:
|
|
- 'src/**'
|
|
- 'tests/integration/**'
|
|
- 'bench/golden-corpus/**'
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
inputs:
|
|
run_performance:
|
|
description: 'Run performance baseline tests'
|
|
type: boolean
|
|
default: false
|
|
run_airgap:
|
|
description: 'Run air-gap tests'
|
|
type: boolean
|
|
default: false
|
|
|
|
concurrency:
|
|
group: integration-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# ==========================================================================
|
|
# T6-AC1: Integration tests run on PR
|
|
# ==========================================================================
|
|
integration-tests:
|
|
name: Integration Tests
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
env:
|
|
POSTGRES_USER: stellaops
|
|
POSTGRES_PASSWORD: test-only
|
|
POSTGRES_DB: stellaops_test
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Restore dependencies
|
|
run: dotnet restore tests/integration/**/*.csproj
|
|
|
|
- name: Build integration tests
|
|
run: dotnet build tests/integration/**/*.csproj --configuration Release --no-restore
|
|
|
|
- name: Run Proof Chain Tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.ProofChain \
|
|
--configuration Release \
|
|
--no-build \
|
|
--logger "trx;LogFileName=proofchain.trx" \
|
|
--results-directory ./TestResults
|
|
env:
|
|
ConnectionStrings__StellaOps: "Host=localhost;Database=stellaops_test;Username=stellaops;Password=test-only"
|
|
|
|
- name: Run Reachability Tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Reachability \
|
|
--configuration Release \
|
|
--no-build \
|
|
--logger "trx;LogFileName=reachability.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Run Unknowns Workflow Tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Unknowns \
|
|
--configuration Release \
|
|
--no-build \
|
|
--logger "trx;LogFileName=unknowns.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Run Determinism Tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Determinism \
|
|
--configuration Release \
|
|
--no-build \
|
|
--logger "trx;LogFileName=determinism.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Upload test results
|
|
uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: integration-test-results
|
|
path: TestResults/**/*.trx
|
|
|
|
- name: Publish test summary
|
|
uses: dorny/test-reporter@v1
|
|
if: always()
|
|
with:
|
|
name: Integration Test Results
|
|
path: TestResults/**/*.trx
|
|
reporter: dotnet-trx
|
|
|
|
# ==========================================================================
|
|
# T6-AC2: Corpus validation on release branch
|
|
# ==========================================================================
|
|
corpus-validation:
|
|
name: Golden Corpus Validation
|
|
runs-on: ubuntu-latest
|
|
if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
|
|
timeout-minutes: 15
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Validate corpus manifest
|
|
run: |
|
|
python3 -c "
|
|
import json
|
|
import hashlib
|
|
import os
|
|
|
|
manifest_path = 'bench/golden-corpus/corpus-manifest.json'
|
|
with open(manifest_path) as f:
|
|
manifest = json.load(f)
|
|
|
|
print(f'Corpus version: {manifest.get(\"corpus_version\", \"unknown\")}')
|
|
print(f'Total cases: {manifest.get(\"total_cases\", 0)}')
|
|
|
|
errors = []
|
|
for case in manifest.get('cases', []):
|
|
case_path = os.path.join('bench/golden-corpus', case['path'])
|
|
if not os.path.isdir(case_path):
|
|
errors.append(f'Missing case directory: {case_path}')
|
|
else:
|
|
required_files = ['case.json', 'expected-score.json']
|
|
for f in required_files:
|
|
if not os.path.exists(os.path.join(case_path, f)):
|
|
errors.append(f'Missing file: {case_path}/{f}')
|
|
|
|
if errors:
|
|
print('\\nValidation errors:')
|
|
for e in errors:
|
|
print(f' - {e}')
|
|
exit(1)
|
|
else:
|
|
print('\\nCorpus validation passed!')
|
|
"
|
|
|
|
- name: Run corpus scoring tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Determinism \
|
|
--filter "Category=GoldenCorpus" \
|
|
--configuration Release \
|
|
--logger "trx;LogFileName=corpus.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
# ==========================================================================
|
|
# T6-AC3: Determinism tests on nightly
|
|
# ==========================================================================
|
|
nightly-determinism:
|
|
name: Nightly Determinism Check
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.run_performance == 'true')
|
|
timeout-minutes: 45
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Run full determinism suite
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Determinism \
|
|
--configuration Release \
|
|
--logger "trx;LogFileName=determinism-full.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Run cross-run determinism check
|
|
run: |
|
|
# Run scoring 3 times and compare hashes
|
|
for i in 1 2 3; do
|
|
dotnet test tests/integration/StellaOps.Integration.Determinism \
|
|
--filter "FullyQualifiedName~IdenticalInput_ProducesIdenticalHash" \
|
|
--results-directory ./TestResults/run-$i
|
|
done
|
|
|
|
# Compare all results
|
|
echo "Comparing determinism across runs..."
|
|
|
|
- name: Upload determinism results
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: nightly-determinism-results
|
|
path: TestResults/**
|
|
|
|
# ==========================================================================
|
|
# T6-AC4: Test coverage reported to dashboard
|
|
# ==========================================================================
|
|
coverage-report:
|
|
name: Coverage Report
|
|
runs-on: ubuntu-latest
|
|
needs: [integration-tests]
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Run tests with coverage
|
|
run: |
|
|
dotnet test tests/integration/**/*.csproj \
|
|
--configuration Release \
|
|
--collect:"XPlat Code Coverage" \
|
|
--results-directory ./TestResults/Coverage
|
|
|
|
- name: Generate coverage report
|
|
uses: danielpalme/ReportGenerator-GitHub-Action@5.2.0
|
|
with:
|
|
reports: TestResults/Coverage/**/coverage.cobertura.xml
|
|
targetdir: TestResults/CoverageReport
|
|
reporttypes: 'Html;Cobertura;MarkdownSummary'
|
|
|
|
- name: Upload coverage report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: coverage-report
|
|
path: TestResults/CoverageReport/**
|
|
|
|
- name: Add coverage to PR comment
|
|
uses: marocchino/sticky-pull-request-comment@v2
|
|
if: github.event_name == 'pull_request'
|
|
with:
|
|
recreate: true
|
|
path: TestResults/CoverageReport/Summary.md
|
|
|
|
# ==========================================================================
|
|
# T6-AC5: Flaky test quarantine process
|
|
# ==========================================================================
|
|
flaky-test-check:
|
|
name: Flaky Test Detection
|
|
runs-on: ubuntu-latest
|
|
needs: [integration-tests]
|
|
if: failure()
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Check for known flaky tests
|
|
run: |
|
|
# Check if failure is from a known flaky test
|
|
QUARANTINE_FILE=".github/flaky-tests-quarantine.json"
|
|
if [ -f "$QUARANTINE_FILE" ]; then
|
|
echo "Checking against quarantine list..."
|
|
# Implementation would compare failed tests against quarantine
|
|
fi
|
|
|
|
- name: Create flaky test issue
|
|
uses: actions/github-script@v7
|
|
if: always()
|
|
with:
|
|
script: |
|
|
// After 2 consecutive failures, create issue for quarantine review
|
|
console.log('Checking for flaky test patterns...');
|
|
// Implementation would analyze test history
|
|
|
|
# ==========================================================================
|
|
# Performance Tests (optional, on demand)
|
|
# ==========================================================================
|
|
performance-tests:
|
|
name: Performance Baseline Tests
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.run_performance == 'true'
|
|
timeout-minutes: 30
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Run performance tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.Performance \
|
|
--configuration Release \
|
|
--logger "trx;LogFileName=performance.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Upload performance report
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: performance-report
|
|
path: |
|
|
TestResults/**
|
|
tests/integration/StellaOps.Integration.Performance/output/**
|
|
|
|
- name: Check for regressions
|
|
run: |
|
|
# Check if any test exceeded 20% threshold
|
|
if [ -f "tests/integration/StellaOps.Integration.Performance/output/performance-report.json" ]; then
|
|
python3 -c "
|
|
import json
|
|
with open('tests/integration/StellaOps.Integration.Performance/output/performance-report.json') as f:
|
|
report = json.load(f)
|
|
regressions = [m for m in report.get('Metrics', []) if m.get('DeltaPercent', 0) > 20]
|
|
if regressions:
|
|
print('Performance regressions detected!')
|
|
for r in regressions:
|
|
print(f' {r[\"Name\"]}: +{r[\"DeltaPercent\"]:.1f}%')
|
|
exit(1)
|
|
print('No performance regressions detected.')
|
|
"
|
|
fi
|
|
|
|
# ==========================================================================
|
|
# Air-Gap Tests (optional, on demand)
|
|
# ==========================================================================
|
|
airgap-tests:
|
|
name: Air-Gap Integration Tests
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.run_airgap == 'true'
|
|
timeout-minutes: 30
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "10.0.100"
|
|
|
|
- name: Run air-gap tests
|
|
run: |
|
|
dotnet test tests/integration/StellaOps.Integration.AirGap \
|
|
--configuration Release \
|
|
--logger "trx;LogFileName=airgap.trx" \
|
|
--results-directory ./TestResults
|
|
|
|
- name: Upload air-gap test results
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: airgap-test-results
|
|
path: TestResults/**
|