chore: Update components and trending data #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Component Security Validation | |
| on: | |
| pull_request: | |
| paths: | |
| - 'cli-tool/components/**/*.md' | |
| - 'cli-tool/src/validation/**' | |
| - '.github/workflows/component-security-validation.yml' | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'cli-tool/components/**/*.md' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| security-audit: | |
| name: Security Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 # Full history for git metadata | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '18' | |
| cache: 'npm' | |
| cache-dependency-path: cli-tool/package-lock.json | |
| - name: Install dependencies | |
| run: | | |
| cd cli-tool | |
| npm ci --ignore-scripts | |
| - name: Run Security Audit | |
| id: audit | |
| run: | | |
| cd cli-tool | |
| npm run security-audit:ci | |
| continue-on-error: true | |
| - name: Generate JSON Report | |
| if: always() | |
| run: | | |
| cd cli-tool | |
| npm run security-audit:json | |
| - name: Upload Security Report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: security-audit-report | |
| path: cli-tool/security-report.json | |
| retention-days: 30 | |
| - name: Comment PR with Results | |
| if: github.event_name == 'pull_request' && always() | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const reportPath = 'cli-tool/security-report.json'; | |
| if (!fs.existsSync(reportPath)) { | |
| console.log('No security report found'); | |
| return; | |
| } | |
| const report = JSON.parse(fs.readFileSync(reportPath, 'utf8')); | |
| const passed = report.summary.passed; | |
| const failed = report.summary.failed; | |
| const warnings = report.summary.warnings; | |
| const total = report.summary.total; | |
| const status = failed === 0 ? '✅ PASSED' : '❌ FAILED'; | |
| const emoji = failed === 0 ? '🎉' : '⚠️'; | |
| let comment = `## ${emoji} Security Audit Report\n\n`; | |
| comment += `**Status**: ${status}\n\n`; | |
| // Summary table | |
| comment += `| Metric | Count |\n`; | |
| comment += `|--------|-------|\n`; | |
| comment += `| Total Components | ${total} |\n`; | |
| comment += `| ✅ Passed | ${passed} |\n`; | |
| comment += `| ❌ Failed | ${failed} |\n`; | |
| comment += `| ⚠️ Warnings | ${warnings} |\n\n`; | |
| if (failed > 0) { | |
| comment += `### ❌ Failed Components (Top 5)\n\n`; | |
| comment += `| Component | Errors | Warnings | Score |\n`; | |
| comment += `|-----------|--------|----------|-------|\n`; | |
| const failedComponents = report.components | |
| .filter(c => !c.overall.valid) | |
| .sort((a, b) => b.overall.errorCount - a.overall.errorCount) | |
| .slice(0, 5); | |
| for (const component of failedComponents) { | |
| const name = component.component.path.split('/').pop().replace('.md', ''); | |
| comment += `| \`${name}\` | ${component.overall.errorCount} | ${component.overall.warningCount} | ${component.overall.score}/100 |\n`; | |
| } | |
| if (report.components.filter(c => !c.overall.valid).length > 5) { | |
| const remaining = report.components.filter(c => !c.overall.valid).length - 5; | |
| comment += `\n*...and ${remaining} more failed component(s)*\n`; | |
| } | |
| } | |
| comment += `\n---\n`; | |
| comment += `📊 **[View Full Report](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})** for detailed error messages and all components`; | |
| // Post comment | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: comment | |
| }); | |