own commit attribution

There is no GitHost-style user manifest. GitHub stores one JSON blob per (repo, user, push).

text
CACHE_VERSION = v2
gh:attr:v2:{full_name}:{username}:{version_token}

version_token is repo.pushed_at, else updated_at, else "head". A new push changes the key. Old blobs die by TTL (default 7 days, ATTRIBUTION_CACHE_TTL_SECONDS).

A truncated measurement is returned for this response and not cached. Only a finished repo walk is written.

Deadlines#

Env Default Used by
ATTRIBUTION_INLINE_DEADLINE 3.5s /languages, /stats
ATTRIBUTION_BREAKDOWN_DEADLINE 8s /contributions/breakdown
ATTRIBUTION_RATE_LIMIT_FLOOR 500 stop when GitHub remaining drops below this
ATTRIBUTION_MAX_COMMITS_PER_REPO 200 SHA listing cap
ATTRIBUTION_MAX_COMMIT_DETAILS 600 whole-user budget
ATTRIBUTION_CONCURRENCY 10 commit-detail semaphore
ATTRIBUTION_REPO_CONCURRENCY 6 repos at once

Deadline gates starting more HTTP, not in-flight work. /{username}/repos never walks. It reads the cache with cache_only=True and budget 0.

How a repo is measured#

get_user_contributions lists repos (sort=pushed, type=all), skips archived (and forks if include_forks=false), newest first, then analyze_repo_contribution:

  1. Cache hit. WalkProgress.resolved++.
  2. cache_only or deadline expired. deferred++, return None.
  3. List commit SHAs, maybe count via Link rel="last".
  4. Fetch files per SHA. Skip vendored paths (node_modules, dist, lockfiles, minified).
  5. Contributor totals for exact user vs repo additions.

RepoContribution.method:

  • commits: full own-commit diffs
  • estimated: sample mix scaled by contributor-stat additions
  • contributor_stats: exact user line totals, empty language list

Whole-repo GET /languages is never used to invent a mix. tests/test_language_fallback.py fails if attributed mode touches get_language_stats.

status on the breakdown: complete, deadline, rate_limited, cache_disabled. coverage = resolved / (resolved + deferred). partial is true when deferred > 0.

Warmer#

bash
python scripts/warm_attribution.py tashifkhan --passes 10 --deadline 60

Needs GITHUB_TOKEN and Redis. Default deadline is 60s, not the inline 3.5s. Or hit /tashifkhan/contributions/breakdown until coverage is 1.