maintenance.ymlβ’7.69 kB
name: Maintenance & Dependencies
on:
schedule:
# Run weekly on Sundays at 2 AM UTC
- cron: '0 2 * * 0'
workflow_dispatch:
permissions:
contents: read
jobs:
# Job 1: Dependency Health Check
dependency-health:
name: Dependency Health Check
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check for outdated packages
run: npm outdated || true
- name: Run security audit
run: npm audit --audit-level moderate --only=prod || true
- name: Check for unused dependencies
run: npx depcheck || true
# Job 2: Coverage Tracking
coverage-tracking:
name: Coverage Tracking
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Generate coverage report
run: npm run test:coverage:offline
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage/lcov.info
flags: maintenance
name: maintenance-coverage
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Generate coverage badge
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
// Read coverage summary if available
try {
const coveragePath = path.join(process.cwd(), 'coverage/coverage-summary.json');
if (fs.existsSync(coveragePath)) {
const coverage = JSON.parse(fs.readFileSync(coveragePath, 'utf8'));
const statements = coverage.total.statements.pct;
const branches = coverage.total.branches.pct;
const functions = coverage.total.functions.pct;
const lines = coverage.total.lines.pct;
console.log(`π Coverage Summary:`);
console.log(`Statements: ${statements}%`);
console.log(`Branches: ${branches}%`);
console.log(`Functions: ${functions}%`);
console.log(`Lines: ${lines}%`);
}
} catch (error) {
console.log('Could not read coverage summary:', error.message);
}
# Job 3: Test Health Report
test-health:
name: Test Health Report
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run all tests and collect metrics
run: |
echo "Running test suite health check..."
npm run test:offline --reporter=verbose > test-results.txt 2>&1 || true
- name: Analyze test results
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
try {
const results = fs.readFileSync('test-results.txt', 'utf8');
// Extract test statistics
const passedMatch = results.match(/(\d+) passed/);
const failedMatch = results.match(/(\d+) failed/);
const skippedMatch = results.match(/(\d+) skipped/);
const passed = passedMatch ? parseInt(passedMatch[1]) : 0;
const failed = failedMatch ? parseInt(failedMatch[1]) : 0;
const skipped = skippedMatch ? parseInt(skippedMatch[1]) : 0;
const total = passed + failed + skipped;
console.log(`π§ͺ Test Health Report:`);
console.log(`Total Tests: ${total}`);
console.log(`Passed: ${passed} (${total > 0 ? Math.round(passed/total*100) : 0}%)`);
console.log(`Failed: ${failed}`);
console.log(`Skipped: ${skipped}`);
if (failed > 0) {
console.log('β οΈ There are failing tests that need attention');
} else {
console.log('β
All tests are passing');
}
} catch (error) {
console.log('Could not analyze test results:', error.message);
}
# Job 4: Performance Baseline
performance-baseline:
name: Performance Baseline
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run performance baseline tests
run: |
echo "Running performance baseline tests..."
# Test CLI startup time
time node dist/index.js --help > /dev/null 2>&1 || true
# Test discovery performance if applicable
if [ -f "dist/cli/discover.js" ]; then
echo "Testing discovery performance..."
timeout 30s node dist/cli/discover.js --help > /dev/null 2>&1 || true
fi
- name: Memory usage check
run: |
echo "Checking memory usage patterns..."
node -e "
console.log('Node.js Memory Usage:');
console.log('RSS:', Math.round(process.memoryUsage().rss / 1024 / 1024), 'MB');
console.log('Heap Used:', Math.round(process.memoryUsage().heapUsed / 1024 / 1024), 'MB');
console.log('Heap Total:', Math.round(process.memoryUsage().heapTotal / 1024 / 1024), 'MB');
"
# Job 5: Documentation Checks
documentation-health:
name: Documentation Health
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check README links
uses: gaurav-nelson/github-action-markdown-link-check@v1
with:
use-quiet-mode: 'yes'
use-verbose-mode: 'yes'
config-file: '.github/workflows/link-check-config.json'
continue-on-error: true
- name: Documentation completeness check
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const requiredDocs = [
'README.md',
'docs/getting-started.md',
'docs/tdd-guide.md',
'CLAUDE.md'
];
console.log('π Documentation Health Check:');
for (const doc of requiredDocs) {
const exists = fs.existsSync(doc);
console.log(`${exists ? 'β
' : 'β'} ${doc}`);
}
// Check for outdated examples
const examplesDir = 'docs/examples';
if (fs.existsSync(examplesDir)) {
const examples = fs.readdirSync(examplesDir);
console.log(`π Found ${examples.length} example files`);
}