mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
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
736 lines
24 KiB
YAML
736 lines
24 KiB
YAML
# 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)'"
|
|
}]
|
|
}'
|