New
Apps 1,345Makers 1,343This week 1,345
Promote your app−30%
2views in
the last 30 days

OpenSource Contributions Tracker

Track the open source work of a person, a team or an organization: pull requests authored and...

Built with Claude Code

by nihaljain · Unclaimed · from INIndia · added Oct 29, 2026
no ratings0 comments

A tool that fetches contribution data from the GitHub API and produces a rich markdown report for one user or a whole team. Designed for developers and organizations who want a centralized, automated view of their open-source activity.

Features

Tracks the following metrics across all configured repositories for each user, within a configurable date range:

Metric Description
Commits Commits merged into the default branch
Pull Requests (Open / Closed) PRs authored by each user
Issues (Open / Closed) Issues opened by each user
Code Reviews Unique PRs formally reviewed (reviewed-by:)
Lines Added / Removed Line-level changes for merged commits and open PRs, with optional refactor filtering

The report includes:

  • Overall summary table with totals for every metric
  • Per-project and per-user contribution breakdowns with pie charts
  • Detailed row-level table (project / repository / user / rank / all metrics)
  • Activity detail section listing every individual PR and issue with status, dates, and labels

You control which metrics count toward the Overall Contribution score via contribution_config.

How it works

  1. Data retrieval — fetches commits, PRs, issues, code reviews, and (optionally) per-commit/per-PR line stats from the GitHub REST API, handling pagination and rate-limit headers automatically.
  2. Data processing — aggregates raw counts per user per repository, applies the contribution_config scoring weights, and optionally filters large refactor commits/PRs via refactor_threshold.
  3. Report generation — writes output/github_contributions_report.md (markdown), output/github_contribution_data.csv (raw data), and two PNG pie charts.
  4. Automated execution — a GitHub Actions workflow runs the report on a schedule and commits the output. See GitHub Actions.

Quick start (fork & go)

  1. Fork this repository.
  2. Edit input/github.json — set start_date, add your GitHub usernames, and either map projects to repositories or leave project_to_repo_dict empty to have them auto-detected. See Configuration for all options.
  3. Push the changes — the GitHub Actions workflow will run automatically on the next scheduled cycle, or you can trigger it manually.
  4. View the report — open output/github_contributions_report.md in the repository.

Local run: skip steps 3–4 and run python generate_report.py after completing the Local Setup.

Demo

A live sample report is available at output/github_contributions_report.md. It shows the full report structure: summary table, pie charts, per-project and per-user breakdowns, and the activity detail section with individual PRs and issues.

Dashboard

An interactive web dashboard for the same data lives in dashboard/. It leads with the headline numbers (merged pull requests, code reviews, commits, contribution score), shows where the work went and how it moved over time, and lets you filter and share any view as a link.

The dashboard

It is a static site built from the report in output/, so it can be hosted on any static host. The repository publishes it to GitHub Pages by default, with an optional Cloudflare deploy. See the dashboard README for local development and hosting your own copy.

Local Setup

Prerequisites

  • Python 3.10+
  • A GitHub personal access token that can read public repositories (a fine-grained token with no extra permissions, or the classic public_repo scope). Set it as the GITHUB_TOKEN environment variable. Do not give it access to private repositories unless you need them: see Private repositories.

Installation

  1. Clone the repository:

    git clone https://github.com/NihalJain/opensource-contributions-tracker.git
    cd opensource-contributions-tracker
    
  2. Install dependencies:

    pip install -r requirements.txt
    
  3. Set environment variables:

    export GITHUB_TOKEN=your_personal_access_token
    # Optional — only needed if behind a corporate proxy:
    export HTTP_PROXY=http://proxy.example.com:8080
    export HTTPS_PROXY=http://proxy.example.com:8080
    

Configuration

The input file is input/github.json. The only required fields are start_date and users.

Minimal structure (single contributor, all repositories auto-detected):

{
    "start_date": "YYYY-MM-DD",
    "users": ["user1"]
}

Auto-detected repositories (empty project_to_repo_dict)

Leave project_to_repo_dict out, or set it to {}, and the generator finds the repositories itself. Both of these are equivalent:

{
    "start_date": "2024-01-01",
    "users": ["user1", "user2"],
    "project_to_repo_dict": {}
}

For every user it searches the pull requests they authored, collects the repositories those pull requests were opened against, and turns each repository into a project named after itself. With the configuration above the effective mapping could look like this (illustrative):

{
    "owner-a/repo-one": ["owner-a/repo-one"],
    "owner-a/repo-two": ["owner-a/repo-two"],
    "owner-b/tool":     ["owner-b/tool"]
}

Use this for a quick look at everything a person has worked on. When you want repositories grouped under meaningful project names (for example several repositories under one product), list them explicitly as in the full structure below.

Notes on auto-detection

  • Explicit wins. As soon as project_to_repo_dict has at least one entry, only the repositories you list are tracked. Discovery is not mixed in.
  • Found through authored pull requests only. A repository where a user only committed directly, reviewed or filed issues is not discovered. List it explicitly if it matters.
  • Up to 1 000 pull requests per user. The GitHub Search API returns at most 1 000 results, so a very prolific user can have some repositories missed. List those explicitly.
  • The date range does not limit discovery, it limits what is counted. A discovered repository with no activity in the range simply does not appear in the report.
  • Every repository is its own project, so the project pie chart and project list have one entry per repository.
  • Private repositories are left out of the discovered set under the default private_repos: "exclude"; see Private repositories.

Full structure:

{
    "start_date": "YYYY-MM-DD",
    "end_date": "YYYY-MM-DD",
    "contribution_config": {
        "commits":       { "enabled": true,  "count_towards_score": true  },
        "open_prs":      { "enabled": true,  "count_towards_score": true  },
        "closed_prs":    { "enabled": true,  "count_towards_score": false },
        "open_issues":   { "enabled": true,  "count_towards_score": true  },
        "closed_issues": { "enabled": true,  "count_towards_score": true  },
        "code_reviews":  { "enabled": true,  "count_towards_score": true  },
        "line_stats":    { "enabled": false, "refactor_threshold": 0.1   }
    },
    "private_repos": "exclude",
    "users": ["user1", "user2"],
    "project_to_repo_dict": {
        "Project1": ["owner/repo1", "owner/repo2"],
        "Project2": ["owner/repo3"]
    }
}

This block lists every key the generator reads. Only start_date and users are required; everything else can be left out. Where the block differs from the defaults:

  • end_date is optional and defaults to tomorrow.
  • private_repos defaults to "exclude"; the other values are "redact" and "include". See Private repositories.
  • project_to_repo_dict can be left out, or set to {}, to auto-detect repositories.
  • In contribution_config every metric defaults to enabled: true and count_towards_score: true. The block shows closed_prs with count_towards_score: false, which is a choice, not the default.
  • line_stats defaults to enabled: false and has no refactor_threshold; 0.1 is an example value.

Field reference:

Field Required Default Description
start_date Yes — Start of the reporting period (YYYY-MM-DD)
end_date No Tomorrow End of the reporting period (YYYY-MM-DD, inclusive)
users Yes — List of GitHub usernames to track
project_to_repo_dict No Auto-detected Maps project display names to lists of owner/repo strings. If omitted or {}, repositories are discovered from each user's PR history (capped at 1 000 results by the GitHub Search API)
private_repos No exclude exclude leaves private repositories out of every output and log; redact counts their work without naming anything; include keeps them as they are. See Private repositories
contribution_config No All enabled Per-metric configuration object. Omitting it or any key within it uses the defaults shown below
  commits No — Config for merged commits
    enabled No true Collect and display this metric
    count_towards_score No true Add to the Overall Contribution score
  open_prs No — Config for open pull requests
    enabled No true Collect and display
    count_towards_score No true Add to score
  closed_prs No — Config for closed pull requests
    enabled No true Collect and display
    count_towards_score No true Add to score
  open_issues No — Config for open issues
    enabled No true Collect and display
    count_towards_score No true Add to score
  closed_issues No — Config for closed issues
    enabled No true Collect and display
    count_towards_score No true Add to score
  code_reviews No — Config for PRs formally reviewed
    enabled No true Collect and display
    count_towards_score No true Add to score
  line_stats No — Config for lines added/removed. Expensive: one extra API call per commit and per open PR
    enabled No false Fetch and display line stats. Set to false to skip (recommended for large datasets)
    refactor_threshold No Disabled Float (0–1). Commits/PRs where net-change ratio is below this are excluded from line counts

Notes

  • Cost of a run. A run makes a few search requests per user, then a handful of requests for each repository someone was active in (its details, its contributor ranking and, only for users who committed there, the commit listing). Repositories with no activity cost one lookup, to check that they are public. The production configuration (1 user, 16 repositories) takes about 70 requests and a minute. line_stats is the expensive option: it adds one request per commit and per open pull request, which is why it is off by default.
  • Search API limits. The GitHub Search API returns at most 1 000 results per query. When a user's results are truncated the generator notices and falls back to per-repository queries, so counts stay exact but the run is slower. The log says when this happens.
  • Dates are inclusive. Both start_date and end_date are included, and end_date defaults to tomorrow so that today's activity is counted.
  • Usernames are case-insensitive. They are lower-cased before use.
  • Misconfiguration fails early. A missing start_date or users, an unknown private_repos value, or a configuration with nothing public left stops the run with a message before the report is written.

Private repositories

The report, the data files and the dashboard are normally committed to a public repository and published as a public site, so private repositories are excluded by default ("private_repos": "exclude"):

  • A repository is kept only when GitHub reports it as public. One the token cannot see, or whose visibility is missing from the answer, is excluded too.
  • Excluded repositories are not searched, counted, ranked or named anywhere: not in the report, the CSV, the activity JSON, the charts, the dashboard or the logs (CI logs of a public repository are public). The log only says how many were excluded.
  • This applies to repositories listed in project_to_repo_dict as well as to auto-detected ones.
  • Excluded work does not count towards anyone's totals or rank.

Two other modes exist for the case where your private work should be reflected in the report:

  • "redact" counts private work without naming it. Each user gets one row, Private repositories in the project Private work, with the commits, pull requests, issues and reviews of all their private repositories summed. Their numbers count towards that user's totals and score. Nothing else about them is written: no repository or owner names, titles, links, labels, descriptions, avatars, rank or contributor names, and no activity records, so private work does not appear on the dashboard timeline or in the pull request explorer. The same names are removed from log output, including failed requests and error messages.
  • "include" keeps private repositories exactly as they are, names and titles included. Use it only when the output stays private, for example a private repository with private hosting.

redact needs a token that can see your private repositories, which the workflow's built-in GITHUB_TOKEN cannot, so it matters for local runs or for a personal access token stored as a secret. A value other than exclude, redact or include stops the run before any API call.

What redact does not hide: that you have private work at all, and how much of it there is. Both appear in the totals and the Private repositories row. Leave the default exclude if that matters.

Running with a token that can see private repositories is safe with the default, but a token without that access is better still: the GitHub Actions workflow's built-in GITHUB_TOKEN already sees only public data.

Independent check. check_output_visibility.py looks up every repository named in output/ and fails if any is not public. The nightly workflow runs it before committing, so a leak is stopped before anything is published, and pull requests run it on the output they commit.

python check_output_visibility.py            # checks output/, prints counts only
python check_output_visibility.py --show-names   # locally: also prints which repositories
python check_output_visibility.py --allow-private  # report them but exit 0, for output published privately

It prints counts and file names but not repository names, because CI logs of a public repository are public. A repository the token cannot see counts as not public, so one that has been deleted is reported until it is removed from the output.

Output files written to output/:

File Description
github_contributions_report.md Full markdown report
github_contribution_data.csv Raw per-user-per-repo numeric data
github_activity_data.json Cached PR and issue objects used for the Activity Details section
project_wise_contribution.png Pie chart of contributions by project
user_wise_contribution.png Pie chart of contributions by user

Re-generate the report from cached data (no API calls) — both output files must exist:

python -c "from tracker.cli import generate_report_with_local_data; generate_report_with_local_data()"

GitHub Actions (Automated workflow)

The repository includes a GitHub Actions workflow at .github/workflows/main.yml that:

  • Runs automatically on a schedule (default: every 24 hours — adjust the cron expression to suit your needs).
  • Commits the generated report and CSV back to the repository.

To update the configuration, edit input/github.json and push — the next workflow run picks up the changes automatically.

Steps to trigger the workflow manually

  1. Go to the Actions tab of your forked repository.
  2. Select the Open Source Contribution Tracker Job workflow.
  3. Click Run workflow, choose the branch, and confirm.
  4. Once the run completes, the updated report is committed to the output/ directory.

Contributing

The generator is the tracker package; generate_report.py is its entry point.

Module What it does
tracker/cli.py Builds a report from the API (generate_report) or from earlier data files (generate_report_with_local_data)
tracker/config.py Reads input/github.json and its per-metric settings
tracker/privacy.py Keeps private repositories out of the report (private_repos)
tracker/collect.py Collects every user's contributions to every repository
tracker/github.py The GitHub queries: commits, pull requests, issues, reviews, line stats, repository details
tracker/api.py HTTP session, pagination, retries and rate limits
tracker/aggregate.py Per-project and per-user totals
tracker/report.py The markdown report, pie charts and data files
tracker/log.py The shared logger and the filter that hides private names
  1. Fork the repository and create a feature branch:
    git checkout -b feature/my-improvement
    
  2. Make your changes and verify the script runs correctly:
    export GITHUB_TOKEN=your_token
    python generate_report.py
    
  3. Run the tests (they use stubbed GitHub responses and need no token):
    pip install -r requirements-dev.txt
    pytest
    
  4. Commit, push, and open a pull request against main. The Python checks (unit tests, a live run of the generator, and the public-repositories check) run in CI only when the pull request touches the generator, its tests, input/, output/, the requirements or a workflow. A change to the dashboard or the documentation skips them.

License

This project is licensed under the Apache License 2.0. See the LICENSE file for details.

Contact

For questions or suggestions, please open an issue or reach out to the repository owner Nihal Jain.

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#open-source · #tracking · #github