GitHub Analytics: Delivery Signals From Your Repositories
Most GitHub analytics projects die the same way. Someone exports pull request data, builds a leaderboard of commits per engineer, shows it to the team, and the whole effort loses credibility in a single meeting. That is a shame, because the data sitting in your repositories is genuinely useful. It just answers a different question than most people ask of it.
Your repositories do not know who your best engineer is. They know where work waits. They know which files keep breaking. They know whether the gap between "code is done" and "code is live" is measured in hours or in weeks. Those are delivery signals, and they belong to the system, not to individuals.
This is a practical guide to the four repo-level signals worth tracking, how to pull them without building a warehouse, how to combine them with Jira for a full delivery picture, and why individual productivity scoring will burn you.
What GitHub analytics can and cannot tell you
GitHub records events, not intent. Every pull request carries timestamps: when it opened, when a review was requested, when the first review landed, when it merged. Every commit carries an author, a timestamp, and a set of touched files. Every release and tag carries a date. That is a rich event log of how work moves through your team.
What it does not carry is context. It cannot tell you that a two week old pull request is stale because the author was on call, or that a 4,000 line diff is a dependency bump. It cannot see the design review that happened in a call, the incident that ate Tuesday, or the pairing session where two people wrote code under one author's name.
So the honest framing for GitHub analytics is this: use it to find friction in the system, then go ask humans why the friction is there. Every number is a prompt for a conversation, not a verdict. Teams that treat repo data as a starting question improve. Teams that treat it as a scoreboard get gamed data and quiet resentment.
The four repo-level signals worth tracking
Four signals cover most of what you need. Each one is cheap to compute, hard to game in isolation, and points at something you can actually change.
Review latency
Review latency is the time from a pull request becoming reviewable to the first substantive review. Not to approval, and not to merge. First response.
Waiting time compounds. A pull request that sits for a day does not just lose a day. The author context switches, the branch drifts from main, and when the review lands the author has to page the whole change back in. Two hours of review work spread across three days costs far more than two hours.
Measure it as a distribution, never as an average. One pull request that sat for three weeks will drag your mean into nonsense. Track the median and the 85th percentile together. The median tells you the normal experience; the 85th percentile tells you how bad the tail is. When those two numbers diverge sharply, you usually have a routing problem: some changes are easy to review and some land on a single overloaded expert.
The most common fix is not "review faster." It is reducing the number of pull requests that only one person can review, and shrinking the changes themselves. Review latency and diff size are strongly linked in practice, because a 900 line diff is a task nobody starts casually.
Pull request aging
Review latency measures what already happened. Aging measures what is happening right now.
Take every open pull request, compute its age in days, and bucket it: under one day, one to three days, three to seven days, over seven days. Look at the shape of that distribution weekly. A healthy repository has most of its open pull requests in the youngest bucket and very few survivors past a week.
The aging view catches something latency hides. If your team merges most work quickly but accumulates a long tail of half finished branches, latency stats look fine while unfinished work piles up. Those old branches are inventory: effort absorbed, nothing delivered, and harder to merge every day they age.
Do the same for draft pull requests, which many teams exclude from metrics entirely. A draft open for three weeks is still work in progress that nobody has finished.
Hotspots
A hotspot is a file that changes constantly and is complicated. Change frequency alone is not interesting: a version manifest changes with every release and is fine. Complexity alone is not interesting either: a large, stable module nobody touches is not hurting you. The intersection is where the pain lives.
Adam Tornhill popularized this analysis in his book "Your Code as a Crime Scene," and the appeal is that the first half of it is a one liner against your existing git history:
git log --since="6 months ago" --format=format: --name-only \
| grep -v '^$' | sort | uniq -c | sort -rn | head -25
That gives you change frequency per file over six months. Cross reference the top of that list with file size, cyclomatic complexity, or simply your team's gut sense of which files are scary. The files that rank high on both lists are where refactoring pays for itself, where defects concentrate, and where onboarding stalls.
Hotspots are the single most actionable output of GitHub analytics, because unlike latency or cadence, the fix is concrete: pick the worst file and break it up.
Release cadence
Release cadence is how often code reaches production and how long it takes to get there after merge. The DORA research program, published in "Accelerate" by Nicole Forsgren, Jez Humble and Gene Kim, put deployment frequency and lead time for changes at the center of delivery measurement, alongside change failure rate and time to restore service.
You can approximate deployment frequency from GitHub if your releases are tagged or your deploys run through GitHub Actions or the deployments API. What you are looking for is not a target number but a pattern: are deploys steady, or do they cluster into a Thursday afternoon batch that carries three weeks of accumulated change? Batched deploys make every incident harder to diagnose, because any of thirty merged changes could be the cause.
The gap between merge time and deploy time deserves its own tracking. If code sits merged for six days before shipping, all your review latency work is optimizing a step that was never the bottleneck.
Where each signal actually comes from
Pulling this data is less work than most teams assume, but the API details matter. Here is the practical map.
| Signal | Source | Key fields | Common distortion |
|---|---|---|---|
| Review latency | REST pulls plus pulls/{n}/reviews, or one GraphQL query | created_at, ready_for_review event, review submitted_at | Draft time counted as waiting; bot approvals treated as reviews |
| PR aging | REST pulls?state=open | created_at, draft, updated_at | Bot and dependency pull requests inflate the old buckets |
| Hotspots | Local git log, or the commits API | Commit timestamps, changed file paths | Formatting and rename commits create fake churn |
| Release cadence | Releases, tags, or deployments API; Actions runs | Tag dates, deployment created_at, workflow conclusions | Rollbacks and re-deploys counted as new releases |
| Cycle time end to end | GitHub plus Jira, joined on issue key | Jira status transitions, PR merge time | Tickets created after the work started |
Two practical notes. First, the list endpoint for pull requests does not include review data, so a naive script makes one extra call per pull request and hits rate limits fast on a busy repo. GitHub's GraphQL API lets you fetch pull requests with their reviews in a single query, which is dramatically cheaper. Check GitHub's current rate limit documentation before you size the job, since limits differ between REST, GraphQL, and GitHub App installations.
Second, filter bots deliberately and consistently. Dependabot, renovate, and release automation will dominate pull request counts and skew every latency number. Decide once whether they are in or out, write it down, and keep it stable so week over week comparisons mean something.
What GitHub gives you out of the box
Before building anything, look at the repository Insights tab. Pulse gives a rolling summary of merged and proposed pull requests, open and closed issues. Contributors, code frequency, and commit activity graphs are there. For public repos you also get traffic data. Organization level Insights and audit logs vary by plan.
The built in views are fine for a quick glance and useless for the questions above, because they are per repository, short windowed, and not joinable with anything else. That gap is the entire reason engineering analytics tools exist.
Combining GitHub analytics with Jira for a delivery picture
GitHub knows what the code did. Jira knows what the work was for. Neither alone tells you where delivery time goes.
The join is usually the issue key. If your team writes branches like PROJ-1421-fix-webhook-retry or puts the key in the pull request title, you can match pull requests to tickets with a regular expression and no integration at all. Jira's own GitHub integration does this automatically and surfaces branches, commits, and pull requests on the ticket, which is worth turning on regardless of what you build on top.
Once joined, you can decompose cycle time into stages that each have a different owner and a different fix:
| Stage | Boundary | If this stage is slow |
|---|---|---|
| Queue | Ticket created to In Progress | Too much accepted work, unclear priority |
| Coding | In Progress to PR opened | Scope too large, unclear requirements, environment friction |
| Review wait | PR opened to first review | Reviewer routing, batch size, timezone gaps |
| Rework | First review to approval | Late feedback on approach, missing design agreement |
| Merge to deploy | Approval to production | Release batching, flaky CI, manual gates |
This table is the actual deliverable of a GitHub analytics effort. A single "cycle time is 9 days" number tells a team nothing. "Seven of those nine days are queue and merge to deploy" tells them to stop optimizing code review.
Watch for one recurring data quality trap: tickets created after the work started. Retro-created tickets make queue time look near zero and coding time look enormous. If your queue stage is suspiciously fast, that is usually why.
Why individual productivity scoring fails
The measures are trivially gameable. Commits per week rewards splitting work into meaningless commits. Lines of code rewards verbosity and punishes deletion, which is often the highest value change anyone makes. Pull requests merged rewards small safe changes and punishes the person who spent three weeks untangling the payments module.
The measures are also blind to the most valuable work. Reviewing carefully, mentoring, writing the incident postmortem, killing a bad project before it ships, and unblocking three teammates all show up as low output. The engineer who quietly makes everyone else faster looks like your worst performer on every repo derived metric.
Attribution is unreliable too. Pairing and mob programming credit one author. A repository wide formatting change rewrites blame across thousands of lines unless you maintain a .git-blame-ignore-revs file. Squash merges collapse a month of commits into one.
And the moment anyone knows they are being scored, the data stops describing reality. Marilyn Strathern's well known formulation of Goodhart's law puts it plainly: when a measure becomes a target, it ceases to be a good measure. The DORA researchers make the same point directly about their own metrics, which are deliberately team and system level rather than individual.
Use repo data for systems, not people. Evaluating an individual takes manager judgment, peer feedback, and the actual impact of their work. There is no shortcut in the API, and pretending otherwise costs trust you will not get back.
The one legitimate individual view is self service: an engineer looking at their own review queue or their own aging pull requests to manage their week. That is a tool, not a score. Keep it opt in and keep it out of performance conversations.
Asking GitHub analytics questions in plain English
The gap between "I want to know our review latency" and "I have a dashboard" is usually a few days of scripting, then indefinite maintenance. For a lot of teams that is the reason none of this ever gets measured.
This is where Skopx fits, and it is worth being precise about how. Skopx is not a business intelligence tool. It does not build drag and drop dashboards or charts. If you want a persistent visual delivery dashboard with drill downs, buy a dedicated engineering analytics product or build one on a warehouse. What Skopx does is connect to GitHub, Jira, Slack and nearly 1,000 other tools, and let you ask questions across them in chat, with answers that cite where they came from.
For repo signals, that turns out to cover most of the real need, because the questions are episodic. You want the answer on Monday morning, not a chart you stare at daily.
Look at our main API repo, list every pull request open longer than three days, show how long each has waited for its first review, and flag the ones with no reviewer assigned.
That returns a ranked list with the pull request titles, ages, first review wait, and current reviewer state, sourced from GitHub. It is the input to a fifteen minute unblocking session, which is what you actually wanted.
You can push the same signal into a routine instead of a question. Skopx workflows are built by describing them in chat rather than dragging boxes: a schedule trigger, integration actions, conditions, and AI steps that run on your own provider key. So "every weekday at 9am, pull open pull requests older than two days from these three repos and post them to #eng-leads with the requested reviewers" becomes a scheduled workflow whose runs you can inspect step by step. The limits are real and worth knowing up front: workflows are acyclic, capped at 20 steps, have no human approval step and no custom code step, and the minimum schedule interval is 15 minutes.
The daily morning brief covers the passive version of this, surfacing what changed and what is slipping across connected tools without anyone asking. If your team already lives in Slack, the same pattern of reading signal from conversation is covered in Slack analytics: what team conversation reveals.
Skopx acts only with your approval, keeps data encrypted with AES-256 at rest and TLS 1.3 in transit, isolates data per organization at the row level, and never trains models on your data. It is a paid product: Solo is $5 per month, Team is $16 per seat per month with no seat cap, and every plan bills from day one rather than after a trial period. Full details are on pricing.
The same plain English approach applies outside engineering. Revenue teams use it against payment data, covered in Stripe revenue analytics, and pipeline questions work the same way in HubSpot AI analytics.
How to start without building a platform
Do this in order. Each step is useful on its own, so you can stop whenever the value stops.
- Run the hotspot one liner on your two most important repositories. It takes a minute and usually produces an immediate "oh, that file" reaction.
- Pull open pull requests once a week and bucket them by age. A spreadsheet is fine. Watch the over seven days bucket for a month.
- Add first review time from the reviews endpoint. Report median and 85th percentile, bots excluded.
- Measure merge to deploy separately. If it dominates, stop working on review and go fix your release process.
- Only then join to Jira and decompose full cycle time.
Review the numbers with the team, not about the team. Bring one signal, ask what is causing it, and change one thing. If the conversation turns to who, you have already lost the program.
Frequently asked questions
Does GitHub have built in analytics?
Yes, but limited. The repository Insights tab includes Pulse, contributors, commit activity, code frequency, and dependency views, and public repositories get traffic data. Organization level insights and audit logs depend on your plan. None of it covers review latency, pull request aging by cohort, or anything joined to your issue tracker, which is why teams build or buy on top of the API.
What is a good review latency target?
There is no universal number, and anyone quoting one is guessing about your context. Measure your own current distribution first, then set a target relative to it, for example moving the 85th percentile inside one working day. The direction matters more than the absolute value, and a target that is unreachable given your team's timezone spread will just be ignored.
Should GitHub analytics be used in performance reviews?
No. Repository metrics measure the system, not the person. They are gameable, blind to review and mentoring work, and unreliable in attribution once pairing, squash merges, and formatting commits are involved. Using them for evaluation reliably produces worse data and less trust. Judge individuals through their manager, their peers, and the impact of their work.
How do I combine GitHub and Jira without a data warehouse?
Join on the issue key found in branch names or pull request titles, which most teams already write. Jira's GitHub integration surfaces branches and pull requests on tickets natively, and for periodic analysis a scheduled job or a chat based query across both tools is usually enough. A warehouse becomes worth it when you need years of history, custom modelling, or a shared semantic layer across many teams.
Can Skopx build me a GitHub delivery dashboard?
No. Skopx answers questions in chat with cited sources, generates documents and reports, sends alerts, and runs workflows you describe in plain English. It does not build charts or drag and drop dashboards. For a persistent visual dashboard, use a dedicated BI or engineering analytics tool. For "what is blocking us right now" and recurring digests, chat and scheduled workflows are usually the better fit.
How far back should I look at repo data?
A rolling 90 days for latency and aging, and six to twelve months for hotspots, since code churn patterns need time to emerge. Compare quarter to quarter rather than week to week, and annotate reorganizations, holidays, and incidents, because unexplained dips are almost always calendar effects rather than performance changes.
The point of all of this
GitHub analytics earns its keep when it changes a decision: to split a file, to spread review load, to stop batching deploys, to say no to more parallel work. It stops earning its keep the moment it becomes a scoreboard. Your repositories are an honest record of where work waits. Read them that way, ask people what the waiting means, and fix the system that caused it.
Skopx Team
The Skopx engineering and product team