blob: 0f0dd569ad3218e9d2fe1c0408157232f8d7861d [file] [view]
# 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
```bash
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`:
```yaml
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