Avoid calling it "health". More just-the-facts phrasing.
6 files changed
tree: 30bc2b0c027dc44fb80b1cab0ab6f089c1f66c92
  1. site/
  2. src/
  3. .gitignore
  4. .secrets.example
  5. config.example.yml
  6. DATA_SOURCES.md
  7. LICENSE
  8. PLAN.md
  9. pyproject.toml
  10. README.md
README.md

ASF Community Development Metrics

Public dashboard showing community activity metrics for Apache projects, with 12-month trend lines for meaningful context.

Status: Working dashboard deployed at https://boxofclue.com/comdev-metrics/ — fetches foundation data from projects.apache.org, mailing list stats from Pony Mail Foal API, Git/GitHub activity (with SVN support for legacy projects), and renders a per-project dashboard with trend lines, releases, and list activity.

Quick Start

cd /path/to/comdev-metrics
cp config.example.yml config.yml
cp .secrets.example .secrets
# Edit .secrets with your GitHub token
# Edit config.yml as needed

# Run with uv (no install needed)
uv run asfmetrics

# Single project
asfmetrics --project comdev

# Skip mailing lists (just fetch foundation + git data)
asfmetrics --skip-mailing-lists

# Skip git/VCS collection
asfmetrics --skip-git

# Force re-fetch everything (bypass cache)
asfmetrics --force-refresh

# View results
cd site && python3 -m http.server 8888
# Open http://localhost:8888

What It Does

  1. Fetches foundation-wide data from projects.apache.org JSON files (committees, rosters, releases, podlings)
  2. Discovers all mailing lists per project via Pony Mail Foal preferences.json
  3. Collects per-list message stats for a 12-month rolling window (with aggressive caching — past months are never re-fetched)
  4. Collects Git/VCS activity per project (commits, committers, PRs opened/merged) via GitHub API or SVN log
  5. Detects roster changes (new committers/PMC members) by diffing between runs
  6. Writes everything to a JSON data store (site/data/)
  7. Publishes a static HTML + JS dashboard with:
    • Overview: community growth, releases, mailing list activity rankings
    • Per-project pages: all active lists, monthly bar charts with trend lines, releases
    • Links to projects.apache.org for full project metadata (roster, repos, homepage)

Only lists with actual traffic in the 12-month window are shown.

Caching

Mailing list data is aggressively cached to minimize API calls:

  • Past months are immutable. Once a month ends, its message counts can never change in the archive. Cached data for completed months is never re-fetched.
  • Only the current month is refreshed on each run (since it's still in progress).
  • Cache location: site/data/_cache/mailing_lists/<project>.json
  • Force refresh: Use --force-refresh to clear all caches and re-fetch everything.

On a typical weekly cron run mid-month, the mailing list phase completes in seconds (cache hits) instead of making hundreds of API calls.

Configuration

See config.example.yml. Config is searched in order:

  1. ./config.yml
  2. ~/.asfmetrics/config.yml
  3. /etc/asfmetrics/config.yml

Secrets

GitHub token (needed for git activity collection; optional but strongly recommended):

  1. GITHUB_TOKEN environment variable
  2. .secrets file in the project directory (line: GITHUB_TOKEN=ghp_...)
  3. ~/.secrets file (user-level fallback)
  4. config.yml data_sources.git.token field

Copy .secrets.example.secrets and fill in your token. The .secrets file is in .gitignore and will never be committed.

Per-project VCS overrides

Most projects use GitHub. For projects still on Subversion, add an override in config.yml:

project_overrides:
  httpd:
    vcs: svn
    svn_path: https://svn.apache.org/repos/asf/httpd/httpd/trunk

See config.example.yml for full documentation of override options.

Project Structure

comdev-metrics/
├── .secrets.example         # Template for secrets (GitHub token)
├── config.example.yml       # Example configuration
├── pyproject.toml           # uv/hatch project definition
├── src/asfmetrics/
│   ├── cli.py              # Entry point
│   ├── config.py           # Config loading
│   ├── collectors/
│   │   ├── mailing_lists.py         # Pony Mail Foal API + caching
│   │   ├── git_activity.py          # GitHub API + SVN log collector
│   │   ├── github_repos.py          # Repo inventory + project classification
│   │   └── projects_apache_org.py   # Foundation JSON fetcher + roster differ
│   ├── analysis/           # Trend calculations
│   └── output/             # JSON + HTML generation
├── site/
│   ├── index.html          # Overview dashboard (default tab: All Projects)
│   ├── project.html        # Per-project detail page (?id=projectname)
│   └── data/               # Generated JSON + cache (git-ignored)
│       ├── _cache/
│       │   └── mailing_lists/  # Per-project mailing list cache
│       ├── <project>.json      # Mailing list data
│       └── <project>_git.json  # Git activity data
├── DATA_SOURCES.md         # Where all the data comes from
├── PLAN.md                 # Execution plan and milestones
└── tests/

CLI Reference

usage: asfmetrics [-h] [--config CONFIG] [--project PROJECT]
                  [--skip-mailing-lists] [--skip-git]
                  [--force-refresh] [--refresh-repos]

Options:
  --config CONFIG       Path to config.yml (default: auto-discover)
  --project PROJECT     Run for a single project only
  --skip-mailing-lists  Skip mailing list collection
  --skip-git            Skip git/VCS activity collection
  --force-refresh       Clear all caches and re-fetch everything
  --refresh-repos       Re-fetch the GitHub repo inventory (project → repos map)

Deployment

Dev/staging: https://boxofclue.com/comdev-metrics/ (matrim.rcbowen.com, Alma Linux) Production: ASF ComDev VM (Ubuntu) — eventually

# Weekly cron
0 6 * * 1  rcbowen  cd /opt/asfmetrics && uv run asfmetrics --config /etc/asfmetrics/config.yml

Output served by httpd vhost pointing at site/.

License

Apache License 2.0