Monitoring and Metrics #39
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: Monitoring and Metrics | |
| on: | |
| workflow_run: | |
| workflows: ["CI", "Release", "Security Scanning"] | |
| types: [completed] | |
| schedule: | |
| # Run daily at 8 AM UTC for metrics collection | |
| - cron: '0 8 * * *' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| collect-metrics: | |
| name: Collect Workflow Metrics | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Collect workflow metrics | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # Get workflow runs for the last 30 days | |
| gh api repos/${{ github.repository }}/actions/runs \ | |
| --paginate \ | |
| --jq '.workflow_runs[] | select(.created_at > (now - 30*24*3600 | strftime("%Y-%m-%dT%H:%M:%SZ"))) | { | |
| id: .id, | |
| name: .name, | |
| status: .status, | |
| conclusion: .conclusion, | |
| created_at: .created_at, | |
| updated_at: .updated_at, | |
| run_duration_ms: ((.updated_at | fromdateiso8601) - (.created_at | fromdateiso8601)) * 1000, | |
| branch: .head_branch | |
| }' > workflow_metrics.json | |
| - name: Generate metrics summary | |
| run: | | |
| if command -v jq >/dev/null 2>&1; then | |
| echo "## Workflow Metrics Summary (Last 30 Days)" > metrics_summary.md | |
| echo "" >> metrics_summary.md | |
| # Success rate by workflow | |
| echo "### Success Rates by Workflow" >> metrics_summary.md | |
| jq -r ' | |
| group_by(.name) | | |
| map({ | |
| workflow: .[0].name, | |
| total: length, | |
| successful: map(select(.conclusion == "success")) | length, | |
| success_rate: (map(select(.conclusion == "success")) | length) / length * 100 | |
| }) | | |
| sort_by(.workflow) | | |
| .[] | | |
| "| \(.workflow) | \(.total) | \(.successful) | \(.success_rate | floor)% |" | |
| ' workflow_metrics.json | sed '1i| Workflow | Total Runs | Successful | Success Rate |' | sed '2i|----------|-----------|------------|--------------|' >> metrics_summary.md | |
| echo "" >> metrics_summary.md | |
| # Average duration by workflow | |
| echo "### Average Duration by Workflow" >> metrics_summary.md | |
| jq -r ' | |
| group_by(.name) | | |
| map({ | |
| workflow: .[0].name, | |
| avg_duration_minutes: (map(.run_duration_ms) | add / length) / 60000 | |
| }) | | |
| sort_by(.workflow) | | |
| .[] | | |
| "| \(.workflow) | \(.avg_duration_minutes | floor) minutes |" | |
| ' workflow_metrics.json | sed '1i| Workflow | Average Duration |' | sed '2i|----------|------------------|' >> metrics_summary.md | |
| echo "" >> metrics_summary.md | |
| echo "Generated on: $(date -u)" >> metrics_summary.md | |
| cat metrics_summary.md | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload metrics | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: workflow-metrics-${{ github.run_id }} | |
| path: | | |
| workflow_metrics.json | |
| metrics_summary.md | |
| retention-days: 90 | |
| health-check: | |
| name: Repository Health Check | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| issues: read | |
| pull-requests: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Check repository health | |
| run: | | |
| echo "## Repository Health Check" > health_report.md | |
| echo "Generated on: $(date -u)" >> health_report.md | |
| echo "" >> health_report.md | |
| # Check for required files | |
| echo "### Required Files" >> health_report.md | |
| for file in README.md LICENSE CHANGELOG.md .gitignore; do | |
| if [ -f "$file" ]; then | |
| echo "✅ $file exists" >> health_report.md | |
| else | |
| echo "❌ $file missing" >> health_report.md | |
| fi | |
| done | |
| echo "" >> health_report.md | |
| # Check Go module status | |
| echo "### Go Module Health" >> health_report.md | |
| if go mod verify >/dev/null 2>&1; then | |
| echo "✅ Go modules verified" >> health_report.md | |
| else | |
| echo "❌ Go module verification failed" >> health_report.md | |
| fi | |
| if go mod tidy -diff >/dev/null 2>&1; then | |
| echo "✅ Go modules are tidy" >> health_report.md | |
| else | |
| echo "⚠️ Go modules need tidying" >> health_report.md | |
| fi | |
| echo "" >> health_report.md | |
| # Check for outdated dependencies | |
| echo "### Dependency Status" >> health_report.md | |
| if go list -u -m all | grep -E '\[.*\]' > outdated_deps.txt; then | |
| echo "⚠️ Outdated dependencies found:" >> health_report.md | |
| echo '```' >> health_report.md | |
| head -10 outdated_deps.txt >> health_report.md | |
| echo '```' >> health_report.md | |
| else | |
| echo "✅ All dependencies are up to date" >> health_report.md | |
| fi | |
| cat health_report.md | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload health report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: health-report-${{ github.run_id }} | |
| path: health_report.md | |
| retention-days: 30 | |
| notify-on-failure: | |
| name: Notify on Workflow Failures | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event.workflow_run.conclusion == 'failure' }} | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Create issue on workflow failure | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const title = `Workflow Failure: ${{ github.event.workflow_run.name }}`; | |
| const body = ` | |
| ## Workflow Failure Alert | |
| **Workflow:** ${{ github.event.workflow_run.name }} | |
| **Run ID:** ${{ github.event.workflow_run.id }} | |
| **Branch:** ${{ github.event.workflow_run.head_branch }} | |
| **Commit:** ${{ github.event.workflow_run.head_sha }} | |
| **Triggered by:** ${{ github.event.workflow_run.triggering_actor.login }} | |
| **Run URL:** ${{ github.event.workflow_run.html_url }} | |
| This issue was automatically created due to a workflow failure. | |
| Please investigate and resolve the issue. | |
| --- | |
| *This issue will be automatically closed when the workflow passes again.* | |
| `; | |
| // Check if there's already an open issue for this workflow | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'workflow-failure,${{ github.event.workflow_run.name }}' | |
| }); | |
| if (issues.data.length === 0) { | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['workflow-failure', '${{ github.event.workflow_run.name }}', 'automated'] | |
| }); | |
| } |