Weekly Governance Audit #11
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: Weekly Governance Audit | |
| on: | |
| schedule: | |
| # Run weekly on Sunday at midnight UTC | |
| - cron: '0 0 * * 0' | |
| workflow_dispatch: | |
| inputs: | |
| run_all_audits: | |
| description: 'Run all audit checks (including planned ones)' | |
| required: false | |
| default: 'false' | |
| type: boolean | |
| jobs: | |
| audit: | |
| runs-on: ubuntu-latest | |
| name: Weekly Governance Audit | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.x' | |
| # GATE-003: Trace Link Validation (Weekly Scan) | |
| - name: GATE-003 - Trace Link Validation (Weekly Scan) | |
| id: trace_links | |
| run: | | |
| echo "🔍 Running weekly trace link validation..." | |
| set +e | |
| OUTPUT=$(python scripts/validate_trace_links.py --check-all --verbose 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| # Count broken links | |
| BROKEN_COUNT=$(echo "$OUTPUT" | grep -c "BROKEN LINKS" || echo "0") | |
| echo "broken_links=$BROKEN_COUNT" >> $GITHUB_OUTPUT | |
| if [ $EXIT_CODE -ne 0 ]; then | |
| echo "trace_status=failed" >> $GITHUB_OUTPUT | |
| else | |
| echo "trace_status=passed" >> $GITHUB_OUTPUT | |
| fi | |
| continue-on-error: true | |
| # GATE-016: Staleness Detection (Weekly Scan) | |
| - name: GATE-016 - Staleness Detection | |
| id: staleness | |
| run: | | |
| echo "🔍 Checking for stale artifacts..." | |
| if [ -f "scripts/check_staleness.py" ]; then | |
| set +e | |
| OUTPUT=$(python scripts/check_staleness.py --all 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| if [ $EXIT_CODE -eq 0 ]; then | |
| echo "staleness_status=passed" >> $GITHUB_OUTPUT | |
| else | |
| echo "staleness_status=failed" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "⚠️ Staleness check script not yet implemented (planned)" | |
| echo "staleness_status=planned" >> $GITHUB_OUTPUT | |
| fi | |
| continue-on-error: true | |
| # GATE-017: Shadow Registry Detection (Weekly Scan) | |
| - name: GATE-017 - Shadow Registry Detection | |
| id: shadow_registry | |
| run: | | |
| echo "🔍 Detecting shadow registries..." | |
| if [ -f "scripts/detect_shadow_registries.py" ]; then | |
| set +e | |
| OUTPUT=$(python scripts/detect_shadow_registries.py --namespaces ATA99 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| if [ $EXIT_CODE -eq 0 ]; then | |
| echo "shadow_status=passed" >> $GITHUB_OUTPUT | |
| else | |
| echo "shadow_status=failed" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "⚠️ Shadow registry detection script not yet implemented (planned)" | |
| echo "shadow_status=planned" >> $GITHUB_OUTPUT | |
| fi | |
| continue-on-error: true | |
| # GATE-002: Schema Registry Validation (Weekly) | |
| - name: GATE-002 - Schema Registry Audit | |
| id: schema_audit | |
| run: | | |
| echo "🔍 Auditing schema registry..." | |
| set +e | |
| OUTPUT=$(python scripts/validate_schema_registry.py --check-all --verbose 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| if echo "$OUTPUT" | grep -q "REGISTRY_MISSING"; then | |
| echo "schema_status=registry_missing" >> $GITHUB_OUTPUT | |
| elif [ $EXIT_CODE -ne 0 ]; then | |
| echo "schema_status=failed" >> $GITHUB_OUTPUT | |
| else | |
| echo "schema_status=passed" >> $GITHUB_OUTPUT | |
| fi | |
| continue-on-error: true | |
| # GATE-001: Nomenclature Audit (Weekly) | |
| - name: GATE-001 - Nomenclature Audit | |
| id: nomenclature_audit | |
| run: | | |
| echo "🔍 Running weekly nomenclature audit..." | |
| set +e | |
| OUTPUT=$(python validate_nomenclature.py --standard v6.0 --check-all --strict --verbose 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| # Count invalid files | |
| INVALID_COUNT=$(echo "$OUTPUT" | grep -c "^✗" || echo "0") | |
| echo "invalid_count=$INVALID_COUNT" >> $GITHUB_OUTPUT | |
| if [ $EXIT_CODE -ne 0 ]; then | |
| echo "nomenclature_status=failed" >> $GITHUB_OUTPUT | |
| else | |
| echo "nomenclature_status=passed" >> $GITHUB_OUTPUT | |
| fi | |
| continue-on-error: true | |
| # Generate Audit Summary | |
| - name: Generate Audit Report | |
| id: report | |
| run: | | |
| REPORT_DATE=$(date -u +"%Y-%m-%d") | |
| cat << EOF > audit_report.md | |
| # Weekly Governance Audit Report | |
| **Date:** ${REPORT_DATE} | |
| **Run ID:** ${{ github.run_id }} | |
| ## Audit Summary | |
| | Gate | Status | Description | | |
| |------|--------|-------------| | |
| | GATE-001 | ${{ steps.nomenclature_audit.outputs.nomenclature_status == 'passed' && '✅ PASS' || '❌ FAIL' }} | Nomenclature Compliance | | |
| | GATE-002 | ${{ steps.schema_audit.outputs.schema_status == 'passed' && '✅ PASS' || (steps.schema_audit.outputs.schema_status == 'registry_missing' && '⚠️ MISSING' || '❌ FAIL') }} | Schema Registry | | |
| | GATE-003 | ${{ steps.trace_links.outputs.trace_status == 'passed' && '✅ PASS' || '❌ FAIL' }} | Trace Link Integrity | | |
| | GATE-016 | ${{ steps.staleness.outputs.staleness_status == 'passed' && '✅ PASS' || (steps.staleness.outputs.staleness_status == 'planned' && '⏭️ PLANNED' || '❌ FAIL') }} | Staleness Detection | | |
| | GATE-017 | ${{ steps.shadow_registry.outputs.shadow_status == 'passed' && '✅ PASS' || (steps.shadow_registry.outputs.shadow_status == 'planned' && '⏭️ PLANNED' || '❌ FAIL') }} | Shadow Registry Detection | | |
| ## Details | |
| ### Nomenclature Compliance (GATE-001) | |
| - Status: ${{ steps.nomenclature_audit.outputs.nomenclature_status }} | |
| - Invalid files: ${{ steps.nomenclature_audit.outputs.invalid_count }} | |
| ### Schema Registry (GATE-002) | |
| - Status: ${{ steps.schema_audit.outputs.schema_status }} | |
| ### Trace Link Integrity (GATE-003) | |
| - Status: ${{ steps.trace_links.outputs.trace_status }} | |
| ### Staleness Detection (GATE-016) | |
| - Status: ${{ steps.staleness.outputs.staleness_status }} | |
| ### Shadow Registry Detection (GATE-017) | |
| - Status: ${{ steps.shadow_registry.outputs.shadow_status }} | |
| ## Legend | |
| - ✅ PASS: Audit check passed | |
| - ❌ FAIL: Audit check failed | |
| - ⚠️ MISSING: Required resource missing | |
| - ⏭️ PLANNED: Audit not yet implemented | |
| --- | |
| *Generated by Weekly Governance Audit workflow* | |
| EOF | |
| # Store date for use in JavaScript | |
| echo "report_date=${REPORT_DATE}" >> $GITHUB_OUTPUT | |
| cat audit_report.md | |
| # Create issue if any audits failed | |
| - name: Create Issue for Audit Failures | |
| if: | | |
| always() && ( | |
| steps.trace_links.outputs.trace_status == 'failed' || | |
| steps.nomenclature_audit.outputs.nomenclature_status == 'failed' || | |
| steps.schema_audit.outputs.schema_status == 'failed' | |
| ) | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| // Read the audit report | |
| let reportContent = ''; | |
| try { | |
| reportContent = fs.readFileSync('audit_report.md', 'utf8'); | |
| } catch (e) { | |
| reportContent = 'Audit report generation failed. See workflow logs for details.'; | |
| } | |
| // Use the date from the report step output for consistency | |
| const date = '${{ steps.report.outputs.report_date }}' || new Date().toISOString().split('T')[0]; | |
| const title = `📋 Weekly Governance Audit - ${date}`; | |
| // Check for existing open issue with exact title match | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| labels: 'weekly-audit,governance', | |
| state: 'open' | |
| }); | |
| const body = `## Weekly Governance Audit Results | |
| ${reportContent} | |
| ### Required Actions | |
| Please review and address the audit findings: | |
| 1. **Nomenclature violations**: Rename files to follow the nomenclature standard | |
| 2. **Broken trace links**: Fix or remove broken links | |
| 3. **Schema issues**: Register missing schemas or fix conflicts | |
| ### Reference | |
| - **Workflow**: Weekly Governance Audit | |
| - **Run ID**: ${{ github.run_id }} | |
| - **Gate Index**: \`00_AMPEL360_SPACET_Q10_GEN_PLUS_BB_GEN_LC01_K04_DATA__ci-governance-gates_I01-R01.md\` | |
| --- | |
| *This issue was automatically created by the weekly governance audit.*`; | |
| // Find existing issue with exact title match for this week's audit | |
| const existingIssue = issues.data.find(issue => issue.title === title); | |
| if (existingIssue) { | |
| // Update existing issue | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: existingIssue.number, | |
| body: body | |
| }); | |
| console.log(`Updated existing audit issue #${existingIssue.number}`); | |
| } else { | |
| // Create new issue | |
| const issue = await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['weekly-audit', 'governance', 'K06'] | |
| }); | |
| console.log(`Created new audit issue #${issue.data.number}`); | |
| } | |
| # Upload audit report as artifact | |
| - name: Upload Audit Report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: weekly-audit-report | |
| path: audit_report.md | |
| retention-days: 90 |