Skip to content

Add weekly GitHub repository health report #1095

Description

@ptr727

Add weekly GitHub repository health report

Objective

Add a scheduled GitHub Actions workflow that generates and emails a weekly health report covering all personal GitHub repositories accessible through the existing GitHub App.

The report should include:

  • GitHub Actions failures
  • Open pull requests
  • Pull request health/state
  • Repository summary statistics
  • Only active repositories
  • Both public and private repositories
  • Exclude archived repositories

The report should be sent by email through Gmail SMTP using existing SMTP credentials stored as repository or organization secrets.

Authentication

Do not use a PAT.

Use the existing GitHub App that already has access to all required repositories.

The workflow should obtain an installation access token from the GitHub App at runtime and use that token for GitHub REST and/or GraphQL API requests.

Recommended approach:

  • Store GitHub App ID as a secret or variable
  • Store the GitHub App private key as a secret
  • Use actions/create-github-app-token or equivalent to generate a short-lived installation token
  • Request only read permissions required for reporting

Expected GitHub App permissions should include at least:

  • Actions: Read
  • Metadata: Read
  • Pull requests: Read
  • Checks: Read
  • Commit statuses: Read

Additional read permissions may be added if future report sections require them.

The implementation must not depend on fine-grained or classic PATs.

Repository scope

Enumerate repositories accessible through the GitHub App and include repositories that meet all of the following conditions:

  • Repository is owned by the configured personal GitHub account
  • Repository is not archived
  • Repository is accessible through the GitHub App
  • Public and private repositories are both included

Exclude:

  • Archived repositories
  • Forks if explicitly configured to exclude them
  • Repositories merely accessible through collaboration but owned by another user or organization
  • Any repository included in an optional exclusion configuration

The GitHub username/account owner should be configurable rather than hard-coded in the report logic.

Schedule

Create a GitHub Actions workflow that:

  • Runs once per week
  • Supports manual execution through workflow_dispatch
  • Uses UTC cron as required by GitHub Actions
  • Documents the corresponding Pacific Time execution time
  • Does not require exact DST adjustment unless specifically implemented

Example:

on:
  schedule:
    - cron: "0 16 * * 1"
  workflow_dispatch:

The exact schedule may be adjusted during implementation.

Suggested implementation

Implement the report generator as a Python application/script rather than embedding substantial logic directly in workflow YAML.

Suggested structure:

.github/
  workflows/
    weekly-github-report.yml

scripts/
  github_report/
    __init__.py
    main.py
    github_api.py
    models.py
    report.py
    templates/
      report.html.j2

A simpler single-file implementation is acceptable initially if the code remains maintainable.

Recommended runtime:

  • Python 3.13+
  • GitHub REST API for repository and workflow-run enumeration
  • GitHub GraphQL API where it materially reduces API calls for PR state
  • Jinja2 or equivalent for HTML report generation

Keep GitHub data collection, state classification, and presentation logic reasonably separated.

GitHub API usage

Repository enumeration

Enumerate all repositories available to the GitHub App installation.

Filter them to:

owner == configured GitHub username
archived == false

Capture at minimum:

  • name
  • full name
  • URL
  • visibility
  • default branch
  • archived
  • fork status

GitHub Actions report

For each repository, inspect workflow runs during the reporting period.

Default reporting window:

7 days

The window should be configurable.

Capture at minimum:

  • workflow name
  • workflow run URL
  • branch
  • event
  • conclusion
  • created time
  • completed time
  • run attempt
  • commit SHA where useful

Report abnormal conclusions including:

failure
timed_out
startup_failure
action_required

Treat the following separately:

cancelled

Cancelled workflows should not automatically be classified as failures because intentional cancellations are common.

Failure classification

Where practical, distinguish between transient/resolved failures and currently broken workflows.

Suggested classifications:

FAILED, LATEST RUN STILL FAILING
FAILED DURING PERIOD, LATEST RUN SUCCEEDED
CANCELLED

Example:

❌ Build
   Failed 3 times this week
   Latest run still failing

⚠️ CodeQL
   Failed once this week
   Latest run succeeded

Avoid listing every successful workflow run.

The report should be exception-oriented.

Pull request report

Enumerate all open pull requests for each included repository.

Capture at minimum:

  • PR number
  • title
  • URL
  • author
  • created time
  • last updated time
  • draft state
  • source branch
  • target branch
  • review decision
  • mergeability/merge conflict state where available
  • latest check/status state
  • labels

Where useful, use GraphQL to obtain PR state efficiently rather than issuing many REST calls per PR.

Pull request classification

Classify each open PR into an actionable state.

Suggested states:

🟢 Ready
Approved and required checks passing

🟡 Waiting for review
Review required or review decision pending

🔴 Checks failing
One or more required/latest checks failing

🟠 Changes requested
Review decision is changes requested

🔵 Draft
Pull request is still a draft

⚠️ Stale
No meaningful activity for the configured stale period

⚠️ Merge conflict
Pull request cannot currently be merged cleanly

A pull request may have multiple conditions, but the report should present a clear primary state plus relevant secondary indicators.

Default stale threshold:

14 days

Make the threshold configurable.

Suggested weekly email report

Generate both:

  • HTML email body
  • Plain-text or Markdown equivalent where convenient

The HTML should be designed for Gmail and avoid relying on advanced CSS that email clients commonly strip.

Suggested report structure:

GitHub Weekly Health Report
August 24–30, 2026

SUMMARY

Repositories checked:              37
Public repositories:               24
Private repositories:              13

Repositories with Action failures:  4
Failed workflow runs:               7
Unresolved workflow failures:       2

Open pull requests:                11
PRs ready to merge:                 3
PRs with failing checks:            3
PRs awaiting review:                2
Stale PRs:                          2

Action failures

Example:

ACTION FAILURES

ProjectTemplate

❌ Build
   Branch: develop
   Failed: Aug 28
   Failures this week: 3
   Latest run: FAILED
   View run

⚠️ CodeQL
   Branch: main
   Failed: Aug 27
   Failures this week: 1
   Latest run: PASSED
   View run

Prioritize unresolved failures before failures that later recovered.

Open pull requests

Example:

OPEN PULL REQUESTS

ProjectTemplate

🔴 #812 Update dependencies
   Author: dependabot
   Open: 4 days
   Checks: failing
   Review: approved
   View PR

🟡 #809 Refactor validation logic
   Author: ptr727
   Open: 6 days
   Checks: passing
   Review: waiting
   View PR

⚠️ #807 Cleanup repository tooling
   Author: ptr727
   Open: 18 days
   Checks: passing
   Review: changes requested
   Stale: 15 days since last activity
   View PR

Healthy repositories

Do not generate verbose sections for repositories with no actionable items.

Instead include a compact summary such as:

HEALTHY REPOSITORIES

21 repositories have:
- no unresolved Actions failures
- no open pull requests requiring attention

Optionally list repository names in a collapsed/compact table if useful.

Report ordering

Order the report by severity.

Suggested top-level ordering:

1. Unresolved Actions failures
2. Pull requests with failing checks
3. Pull requests with merge conflicts
4. Pull requests with changes requested
5. Stale pull requests
6. Pull requests waiting for review
7. Pull requests ready to merge
8. Resolved Actions failures
9. Healthy repository summary

Within each section:

  • Group by repository
  • Sort oldest or most severe issues first where appropriate

Email delivery

Send the generated HTML report using Gmail SMTP.

SMTP credentials already exist and should be referenced through GitHub Actions secrets.

Expected secrets/configuration may include:

SMTP_HOST
SMTP_PORT
SMTP_USERNAME
SMTP_PASSWORD
REPORT_EMAIL_TO
REPORT_EMAIL_FROM

Typical Gmail SMTP configuration:

smtp.gmail.com
587
STARTTLS

Use either:

  • a small Python SMTP sender using the standard library, or
  • a well-maintained email GitHub Action pinned to a commit SHA

Prefer avoiding an unnecessary third-party Action if Python is already being used to generate the report.

A Python implementation using smtplib and email.message.EmailMessage would keep the reporting pipeline largely self-contained.

Workflow outline

Suggested workflow:

Scheduled/manual trigger
        |
        v
Checkout repository
        |
        v
Set up Python
        |
        v
Generate GitHub App installation token
        |
        v
Collect repository/workflow/PR data
        |
        v
Generate HTML report
        |
        v
Send report through Gmail SMTP

Configuration

Avoid hard-coding policy decisions.

Suggested environment/configuration:

GITHUB_OWNER
REPORT_DAYS=7
STALE_PR_DAYS=14
INCLUDE_FORKS=false
REPORT_CANCELLED_RUNS=true

Optional future configuration:

EXCLUDED_REPOSITORIES
INCLUDED_REPOSITORIES
REPORT_READY_PRS=true
REPORT_HEALTHY_REPOSITORIES=true

Error handling

The report job should fail if:

  • GitHub App authentication fails
  • Repository enumeration fails
  • Report generation fails
  • Email delivery fails

Individual repository/API failures should preferably not abort the entire report.

Instead:

  • record the repository/API error
  • continue processing other repositories
  • include an ERRORS section in the report
  • fail the workflow at the end if important data could not be collected

Example:

DATA COLLECTION ERRORS

RepoA
Unable to query workflow runs: HTTP 403

RepoB
Unable to query pull request checks: GraphQL error

This prevents one bad repository from eliminating the entire weekly report.

Security requirements

  • GitHub App token must be short-lived
  • Do not log the GitHub App private key
  • Do not log the generated installation token
  • Do not log SMTP credentials
  • Use read-only GitHub permissions
  • Pin third-party Actions to full commit SHAs where practical
  • Do not expose private repository names or URLs outside the configured email recipient
  • Generated report artifacts should not be uploaded publicly
  • Avoid retaining the HTML report as a GitHub Actions artifact unless explicitly useful

Testing

Support workflow_dispatch for development and testing.

The report generator should preferably support local execution with environment-based credentials.

Suggested CLI:

python -m scripts.github_report \
  --days 7 \
  --stale-days 14 \
  --output report.html

Where practical, separate data models/classification logic enough to allow unit tests without making GitHub API calls.

Tests should cover at minimum:

  • archived repositories are excluded
  • repositories owned by another account are excluded
  • successful runs are not reported as failures
  • resolved vs unresolved workflow failures
  • cancelled run handling
  • draft PR classification
  • failing PR checks
  • changes-requested PRs
  • stale PR detection
  • ready-to-merge PR classification

Future enhancements

Design the implementation so additional repository-health checks can be added later without restructuring the entire report.

Potential future sections:

  • Dependabot/security alerts
  • Open issues requiring attention
  • Dependency update PRs
  • Branch protection status
  • Repository rulesets
  • CodeQL status
  • Secret scanning alerts
  • Dependabot configuration
  • Stale branches
  • Releases/tags
  • Repositories with no recent activity
  • Workflow files using outdated Action versions
  • Repeated/flaky workflow failures
  • Repository visibility/security policy inconsistencies

These are out of scope for the initial implementation.

Acceptance criteria

  • Scheduled workflow runs weekly
  • Workflow can be manually dispatched
  • GitHub authentication uses the existing GitHub App
  • No PAT is required
  • All personal public repositories are evaluated
  • All personal private repositories accessible to the App are evaluated
  • Archived repositories are excluded
  • Repositories owned by other users/organizations are excluded
  • GitHub Actions failures from the reporting period are reported
  • Resolved and unresolved workflow failures are distinguishable
  • Cancelled runs are treated separately from failures
  • All open PRs are evaluated
  • PR check/review/draft/stale/merge-conflict state is represented
  • Report is ordered by actionable severity
  • Healthy repositories do not create excessive report noise
  • HTML report renders correctly in Gmail
  • Report is sent through existing Gmail SMTP credentials
  • GitHub and SMTP credentials are never logged
  • Third-party Actions are pinned to commit SHAs where practical
  • Partial repository/API failures are included in the report rather than silently ignored
  • Workflow fails if material report collection or email delivery fails

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions