Skip to content

Monitoring and Metrics #39

Monitoring and Metrics

Monitoring and Metrics #39

Workflow file for this run

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']
});
}