mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
✅ test: implement comprehensive automated testing system with daily CI/CD
Implement rock-solid automated testing infrastructure for mana-core-auth with daily execution, notifications, and comprehensive monitoring. Test Suite Improvements: - Fix all 36 failing BetterAuthService tests (missing service mocks) - Add 21 JwtAuthGuard tests achieving 100% statement coverage - Create silentError helper to suppress intentional error logs - Fix Todo backend TaskService test structure - Add jose mock for JWT testing - Configure jest collectCoverageFrom for mana-core-auth GitHub Actions Workflow: - Daily automated test execution (2 AM UTC + manual trigger) - Matrix parallelization across 6 backend services - PostgreSQL and Redis service containers - Coverage enforcement (80% threshold) - Multi-channel notifications (Discord, Slack, GitHub Issues) - Support for success notifications (opt-in) Test Infrastructure: - Coverage aggregation across multiple services - Flaky test detection with 30-run history tracking - Performance metrics tracking with regression detection - Test data seeding and cleanup scripts - Comprehensive test reporting with formatted metrics Documentation: - TESTING_GUIDE.md (4000+ words) - Complete testing documentation - AUTOMATED_TESTING_SYSTEM.md - System architecture and workflows - DISCORD_NOTIFICATIONS_SETUP.md - Discord webhook setup guide - TESTING_DEPLOYMENT_CHECKLIST.md - Pre-deployment verification - TESTING_QUICK_REFERENCE.md - Quick command reference Final Result: - 180/180 tests passing (100% pass rate) - Zero console errors in test output - Automated daily testing with rich notifications - Production-ready test infrastructure
This commit is contained in:
parent
9dbd6e6c09
commit
304897261d
24 changed files with 5017 additions and 16 deletions
736
.github/workflows/daily-tests.yml
vendored
Normal file
736
.github/workflows/daily-tests.yml
vendored
Normal file
|
|
@ -0,0 +1,736 @@
|
|||
# Daily Test Execution - Comprehensive automated testing with monitoring and reporting
|
||||
#
|
||||
# Schedule: Runs daily at 2 AM UTC
|
||||
# Manual Trigger: workflow_dispatch for on-demand test runs
|
||||
# Features:
|
||||
# - Full test suite execution with coverage
|
||||
# - Parallel execution where possible
|
||||
# - Database setup/teardown per test suite
|
||||
# - Coverage thresholds enforcement (80% minimum)
|
||||
# - Test result summaries and failure notifications
|
||||
# - Flaky test detection
|
||||
# - Performance metrics tracking
|
||||
|
||||
name: Daily Tests
|
||||
|
||||
on:
|
||||
# Run daily at 2 AM UTC
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
# Allow manual trigger
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
coverage_threshold:
|
||||
description: 'Minimum coverage percentage (default: 80)'
|
||||
required: false
|
||||
default: '80'
|
||||
verbose:
|
||||
description: 'Verbose test output'
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
notify_success:
|
||||
description: 'Send Discord notification on success'
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: daily-tests-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20'
|
||||
PNPM_VERSION: '9.15.0'
|
||||
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
|
||||
|
||||
jobs:
|
||||
# Job 1: Setup and prepare test environment
|
||||
setup:
|
||||
name: Setup Test Environment
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix_backend: ${{ steps.detect-tests.outputs.matrix_backend }}
|
||||
matrix_mobile: ${{ steps.detect-tests.outputs.matrix_mobile }}
|
||||
matrix_web: ${{ steps.detect-tests.outputs.matrix_web }}
|
||||
has_backend_tests: ${{ steps.detect-tests.outputs.has_backend_tests }}
|
||||
has_mobile_tests: ${{ steps.detect-tests.outputs.has_mobile_tests }}
|
||||
has_web_tests: ${{ steps.detect-tests.outputs.has_web_tests }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Detect test suites
|
||||
id: detect-tests
|
||||
run: |
|
||||
# Detect backend tests (Jest)
|
||||
BACKEND_TESTS=$(find services apps/*/apps/backend -name "*.spec.ts" -type f 2>/dev/null | wc -l || echo 0)
|
||||
if [ "$BACKEND_TESTS" -gt 0 ]; then
|
||||
echo "has_backend_tests=true" >> $GITHUB_OUTPUT
|
||||
# Create matrix for parallel execution
|
||||
BACKEND_MATRIX=$(cat <<EOF
|
||||
{
|
||||
"include": [
|
||||
{"name": "mana-core-auth", "path": "services/mana-core-auth", "db": "manacore"},
|
||||
{"name": "chat-backend", "path": "apps/chat/apps/backend", "db": "chat"},
|
||||
{"name": "todo-backend", "path": "apps/todo/apps/backend", "db": "todo"},
|
||||
{"name": "calendar-backend", "path": "apps/calendar/apps/backend", "db": "calendar"},
|
||||
{"name": "contacts-backend", "path": "apps/contacts/apps/backend", "db": "contacts"},
|
||||
{"name": "picture-backend", "path": "apps/picture/apps/backend", "db": "picture"}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
echo "matrix_backend=$(echo $BACKEND_MATRIX | jq -c .)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_backend_tests=false" >> $GITHUB_OUTPUT
|
||||
echo "matrix_backend={\"include\":[]}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Detect mobile tests (Jest/React Native)
|
||||
MOBILE_TESTS=$(find apps/*/apps/mobile -name "*.test.ts" -o -name "*.test.tsx" 2>/dev/null | wc -l || echo 0)
|
||||
if [ "$MOBILE_TESTS" -gt 0 ]; then
|
||||
echo "has_mobile_tests=true" >> $GITHUB_OUTPUT
|
||||
MOBILE_MATRIX=$(cat <<EOF
|
||||
{
|
||||
"include": [
|
||||
{"name": "chat-mobile", "path": "apps/chat/apps/mobile"},
|
||||
{"name": "context-mobile", "path": "apps/context/apps/mobile"}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
echo "matrix_mobile=$(echo $MOBILE_MATRIX | jq -c .)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_mobile_tests=false" >> $GITHUB_OUTPUT
|
||||
echo "matrix_mobile={\"include\":[]}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Detect web tests (Vitest/Svelte)
|
||||
WEB_TESTS=$(find apps/*/apps/web -name "*.test.ts" -o -name "*.test.svelte" 2>/dev/null | wc -l || echo 0)
|
||||
if [ "$WEB_TESTS" -gt 0 ]; then
|
||||
echo "has_web_tests=true" >> $GITHUB_OUTPUT
|
||||
WEB_MATRIX=$(cat <<EOF
|
||||
{
|
||||
"include": [
|
||||
{"name": "manacore-web", "path": "apps/manacore/apps/web"},
|
||||
{"name": "chat-web", "path": "apps/chat/apps/web"}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
echo "matrix_web=$(echo $WEB_MATRIX | jq -c .)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_web_tests=false" >> $GITHUB_OUTPUT
|
||||
echo "matrix_web={\"include\":[]}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Job 2: Backend tests with database setup
|
||||
test-backend:
|
||||
name: Test ${{ matrix.name }}
|
||||
needs: setup
|
||||
if: needs.setup.outputs.has_backend_tests == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.matrix_backend) }}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: manacore
|
||||
POSTGRES_PASSWORD: testpassword
|
||||
POSTGRES_DB: ${{ matrix.db }}
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build dependencies
|
||||
run: pnpm run build:packages
|
||||
|
||||
- name: Setup test database
|
||||
working-directory: ${{ matrix.path }}
|
||||
env:
|
||||
DATABASE_URL: postgresql://manacore:testpassword@localhost:5432/${{ matrix.db }}
|
||||
run: |
|
||||
# Run migrations if they exist
|
||||
if [ -f "package.json" ] && grep -q "db:push" package.json; then
|
||||
pnpm run db:push || echo "No migrations to run"
|
||||
fi
|
||||
|
||||
- name: Run tests with coverage
|
||||
working-directory: ${{ matrix.path }}
|
||||
env:
|
||||
DATABASE_URL: postgresql://manacore:testpassword@localhost:5432/${{ matrix.db }}
|
||||
REDIS_URL: redis://localhost:6379
|
||||
NODE_ENV: test
|
||||
JWT_ISSUER: manacore
|
||||
JWT_AUDIENCE: manacore
|
||||
run: |
|
||||
if [ "${{ github.event.inputs.verbose }}" = "true" ]; then
|
||||
pnpm run test:cov --verbose
|
||||
else
|
||||
pnpm run test:cov
|
||||
fi
|
||||
|
||||
- name: Upload coverage to artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-${{ matrix.name }}
|
||||
path: ${{ matrix.path }}/coverage
|
||||
retention-days: 30
|
||||
|
||||
- name: Check coverage threshold
|
||||
working-directory: ${{ matrix.path }}
|
||||
run: |
|
||||
if [ -f "coverage/coverage-summary.json" ]; then
|
||||
COVERAGE=$(node -e "const c = require('./coverage/coverage-summary.json'); console.log(c.total.lines.pct)")
|
||||
echo "Coverage for ${{ matrix.name }}: ${COVERAGE}%"
|
||||
|
||||
if (( $(echo "$COVERAGE < $COVERAGE_THRESHOLD" | bc -l) )); then
|
||||
echo "::error::Coverage ${COVERAGE}% is below threshold ${COVERAGE_THRESHOLD}%"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Job 3: Mobile tests (no database needed)
|
||||
test-mobile:
|
||||
name: Test ${{ matrix.name }}
|
||||
needs: setup
|
||||
if: needs.setup.outputs.has_mobile_tests == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.matrix_mobile) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests with coverage
|
||||
working-directory: ${{ matrix.path }}
|
||||
run: pnpm run test -- --coverage --watchAll=false
|
||||
|
||||
- name: Upload coverage to artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-${{ matrix.name }}
|
||||
path: ${{ matrix.path }}/coverage
|
||||
retention-days: 30
|
||||
|
||||
# Job 4: Web tests (Vitest)
|
||||
test-web:
|
||||
name: Test ${{ matrix.name }}
|
||||
needs: setup
|
||||
if: needs.setup.outputs.has_web_tests == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.matrix_web) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests with coverage
|
||||
working-directory: ${{ matrix.path }}
|
||||
run: pnpm run test -- --coverage
|
||||
|
||||
- name: Upload coverage to artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-${{ matrix.name }}
|
||||
path: ${{ matrix.path }}/coverage
|
||||
retention-days: 30
|
||||
|
||||
# Job 5: Integration tests (E2E flows)
|
||||
test-integration:
|
||||
name: Integration Tests
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: manacore
|
||||
POSTGRES_PASSWORD: testpassword
|
||||
POSTGRES_DB: manacore
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build dependencies
|
||||
run: pnpm run build:packages
|
||||
|
||||
- name: Setup databases for integration tests
|
||||
env:
|
||||
DATABASE_URL: postgresql://manacore:testpassword@localhost:5432/manacore
|
||||
run: |
|
||||
# Setup auth database
|
||||
cd services/mana-core-auth
|
||||
pnpm run db:push || echo "Auth DB setup skipped"
|
||||
cd ../..
|
||||
|
||||
- name: Run integration tests
|
||||
env:
|
||||
DATABASE_URL: postgresql://manacore:testpassword@localhost:5432/manacore
|
||||
REDIS_URL: redis://localhost:6379
|
||||
NODE_ENV: test
|
||||
JWT_ISSUER: manacore
|
||||
JWT_AUDIENCE: manacore
|
||||
run: |
|
||||
# Run auth integration tests
|
||||
cd services/mana-core-auth
|
||||
if [ -d "test/integration" ]; then
|
||||
pnpm run test:e2e || pnpm run test -- test/integration
|
||||
fi
|
||||
|
||||
- name: Upload integration test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: integration-test-results
|
||||
path: services/mana-core-auth/test-results
|
||||
retention-days: 30
|
||||
|
||||
# Job 6: Aggregate and report results
|
||||
report:
|
||||
name: Generate Test Report
|
||||
needs: [test-backend, test-mobile, test-web, test-integration]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all coverage artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: coverage-reports
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Install report dependencies
|
||||
run: npm install -g istanbul-merge
|
||||
|
||||
- name: Aggregate coverage reports
|
||||
run: |
|
||||
# Create aggregated report directory
|
||||
mkdir -p aggregated-coverage
|
||||
|
||||
# Find and merge all coverage-summary.json files
|
||||
find coverage-reports -name "coverage-summary.json" -exec echo "Found: {}" \;
|
||||
|
||||
# Calculate total coverage
|
||||
node scripts/test-reporting/aggregate-coverage.js coverage-reports aggregated-coverage
|
||||
|
||||
- name: Generate test summary
|
||||
run: |
|
||||
node scripts/test-reporting/generate-summary.js coverage-reports > $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Check overall coverage threshold
|
||||
run: |
|
||||
if [ -f "aggregated-coverage/total-coverage.json" ]; then
|
||||
TOTAL_COVERAGE=$(node -e "const c = require('./aggregated-coverage/total-coverage.json'); console.log(c.lines.pct)")
|
||||
echo "Total Coverage: ${TOTAL_COVERAGE}%"
|
||||
|
||||
if (( $(echo "$TOTAL_COVERAGE < $COVERAGE_THRESHOLD" | bc -l) )); then
|
||||
echo "::error::Overall coverage ${TOTAL_COVERAGE}% is below threshold ${COVERAGE_THRESHOLD}%"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Upload aggregated coverage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: aggregated-coverage-report
|
||||
path: aggregated-coverage
|
||||
retention-days: 90
|
||||
|
||||
- name: Comment on commit (if failed)
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const summary = fs.readFileSync('aggregated-coverage/summary.md', 'utf8');
|
||||
|
||||
github.rest.repos.createCommitComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
commit_sha: context.sha,
|
||||
body: `## Daily Tests Failed ❌\n\n${summary}\n\n[View Details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`
|
||||
});
|
||||
|
||||
# Job 7: Detect flaky tests
|
||||
detect-flaky:
|
||||
name: Detect Flaky Tests
|
||||
needs: [test-backend, test-mobile, test-web]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Download test results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: test-results
|
||||
|
||||
- name: Analyze test stability
|
||||
run: |
|
||||
# Run flaky test detection script
|
||||
node scripts/test-reporting/detect-flaky-tests.js test-results
|
||||
|
||||
- name: Upload flaky test report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: flaky-test-report
|
||||
path: test-results/flaky-tests.json
|
||||
retention-days: 90
|
||||
|
||||
- name: Create issue for flaky tests
|
||||
if: hashFiles('test-results/flaky-tests.json') != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const flakyTests = JSON.parse(fs.readFileSync('test-results/flaky-tests.json', 'utf8'));
|
||||
|
||||
if (flakyTests.length > 0) {
|
||||
const body = `## Flaky Tests Detected 🔄\n\n` +
|
||||
`Found ${flakyTests.length} potentially flaky tests:\n\n` +
|
||||
flakyTests.map(t => `- \`${t.name}\` (failed ${t.failureRate}% of the time)`).join('\n');
|
||||
|
||||
github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: `[Daily Tests] Flaky Tests Detected - ${new Date().toISOString().split('T')[0]}`,
|
||||
body: body,
|
||||
labels: ['testing', 'flaky-test', 'automated']
|
||||
});
|
||||
}
|
||||
|
||||
# Job 8: Performance metrics
|
||||
metrics:
|
||||
name: Track Test Performance
|
||||
needs: [test-backend, test-mobile, test-web]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download test results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: test-results
|
||||
|
||||
- name: Calculate performance metrics
|
||||
run: |
|
||||
# Track test execution time, memory usage, etc.
|
||||
node scripts/test-reporting/track-metrics.js test-results
|
||||
|
||||
- name: Upload metrics
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-metrics
|
||||
path: test-results/metrics.json
|
||||
retention-days: 365
|
||||
|
||||
- name: Post metrics to summary
|
||||
run: |
|
||||
if [ -f "test-results/metrics.json" ]; then
|
||||
echo "## Test Performance Metrics" >> $GITHUB_STEP_SUMMARY
|
||||
node scripts/test-reporting/format-metrics.js test-results/metrics.json >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Job 9: Notify on failure
|
||||
notify:
|
||||
name: Notify on Failure
|
||||
needs: [report, detect-flaky, metrics]
|
||||
if: failure()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download coverage summary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: aggregated-coverage-report
|
||||
path: coverage-summary
|
||||
continue-on-error: true
|
||||
|
||||
- name: Prepare notification data
|
||||
id: prepare
|
||||
run: |
|
||||
# Get workflow run URL
|
||||
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
echo "run_url=$RUN_URL" >> $GITHUB_OUTPUT
|
||||
|
||||
# Get coverage if available
|
||||
if [ -f "coverage-summary/total-coverage.json" ]; then
|
||||
COVERAGE=$(node -e "const c = require('./coverage-summary/total-coverage.json'); console.log(c.lines.pct)")
|
||||
echo "coverage=${COVERAGE}%" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "coverage=N/A" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Get date
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
echo "date=$DATE" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Send Discord notification
|
||||
if: env.DISCORD_WEBHOOK_URL != ''
|
||||
env:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST "$DISCORD_WEBHOOK_URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"username": "ManaCore CI/CD",
|
||||
"avatar_url": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
|
||||
"embeds": [{
|
||||
"title": "❌ Daily Tests Failed",
|
||||
"description": "The daily test suite encountered failures and needs attention.",
|
||||
"color": 15158332,
|
||||
"fields": [
|
||||
{
|
||||
"name": "📅 Date",
|
||||
"value": "${{ steps.prepare.outputs.date }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "📊 Coverage",
|
||||
"value": "${{ steps.prepare.outputs.coverage }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "🔗 Workflow Run",
|
||||
"value": "[View Details](${{ steps.prepare.outputs.run_url }})",
|
||||
"inline": false
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": "ManaCore Monorepo"
|
||||
},
|
||||
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
|
||||
}]
|
||||
}'
|
||||
|
||||
- name: Send Slack notification
|
||||
if: env.SLACK_WEBHOOK_URL != ''
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST $SLACK_WEBHOOK_URL \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"text\":\"Daily Tests Failed ❌\",\"blocks\":[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"*Daily Test Suite Failed*\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>\"}}]}"
|
||||
|
||||
- name: Create GitHub issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: `[Daily Tests] Test Suite Failed - ${new Date().toISOString().split('T')[0]}`,
|
||||
body: `The daily test suite failed. Please investigate.\n\n[View Workflow Run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`,
|
||||
labels: ['testing', 'failure', 'automated']
|
||||
});
|
||||
|
||||
# Job 10: Notify on success (optional)
|
||||
notify-success:
|
||||
name: Notify on Success
|
||||
needs: [report, detect-flaky, metrics]
|
||||
if: success() && github.event.inputs.notify_success == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download coverage summary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: aggregated-coverage-report
|
||||
path: coverage-summary
|
||||
continue-on-error: true
|
||||
|
||||
- name: Prepare notification data
|
||||
id: prepare
|
||||
run: |
|
||||
# Get workflow run URL
|
||||
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
echo "run_url=$RUN_URL" >> $GITHUB_OUTPUT
|
||||
|
||||
# Get coverage if available
|
||||
if [ -f "coverage-summary/total-coverage.json" ]; then
|
||||
COVERAGE=$(node -e "const c = require('./coverage-summary/total-coverage.json'); console.log(c.lines.pct)")
|
||||
echo "coverage=${COVERAGE}%" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "coverage=N/A" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Get test count if available
|
||||
if [ -f "coverage-summary/total-coverage.json" ]; then
|
||||
TESTS=$(node -e "const c = require('./coverage-summary/total-coverage.json'); console.log(c.tests || 'N/A')")
|
||||
echo "tests=$TESTS" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "tests=N/A" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Get date
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
echo "date=$DATE" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Send Discord success notification
|
||||
if: env.DISCORD_WEBHOOK_URL != ''
|
||||
env:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST "$DISCORD_WEBHOOK_URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"username": "ManaCore CI/CD",
|
||||
"avatar_url": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
|
||||
"embeds": [{
|
||||
"title": "✅ Daily Tests Passed",
|
||||
"description": "All tests completed successfully!",
|
||||
"color": 3066993,
|
||||
"fields": [
|
||||
{
|
||||
"name": "📅 Date",
|
||||
"value": "${{ steps.prepare.outputs.date }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "📊 Coverage",
|
||||
"value": "${{ steps.prepare.outputs.coverage }}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "✅ Tests",
|
||||
"value": "${{ steps.prepare.outputs.tests }} passed",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "🔗 Workflow Run",
|
||||
"value": "[View Details](${{ steps.prepare.outputs.run_url }})",
|
||||
"inline": false
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": "ManaCore Monorepo"
|
||||
},
|
||||
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
|
||||
}]
|
||||
}'
|
||||
Loading…
Add table
Add a link
Reference in a new issue