Skip to content

Use the search API to count issues - #829

Open
camUrban wants to merge 1 commit into
ossf:mainfrom
camUrban:fix-issue-counts
Open

Use the search API to count issues#829
camUrban wants to merge 1 commit into
ossf:mainfrom
camUrban:fix-issue-counts

Conversation

@camUrban

@camUrban camUrban commented Jul 17, 2026

Copy link
Copy Markdown

Summary

Fixes #816.

The three legacy issue signals (updated_issues_count, closed_issues_count, and issue_comment_frequency) currently report 0 for every repository.

GitHub's repo issues list endpoint (/repos/{owner}/{repo}/issues) now uses cursor-based pagination: its Link header contains only a rel="next" entry with an opaque cursor, and no rel="last" entry. FetchIssueCount relied on requesting per_page=1 and reading the total from the last page number, so it now always sees LastPage == 0 and returns 0. Since issue_comment_frequency divides the comment count by the updated-issues count, it is zeroed as well.

This change counts issues with a single search API request instead, reading the exact total_count from the response. The original semantics are preserved:

  • Both issues and pull requests are counted (search includes both by default, matching the list endpoint).
  • Results are filtered on updated time within the lookback window (updated:>=<timestamp>), matching the list endpoint's since parameter.
  • The closed state is expressed as is:closed, matching state=closed combined with since (closed-state items updated within the window).
  • The 5xx fallback to MaxIssuesLimit is unchanged.

FetchIssueCommentCount is untouched. The comments endpoint still uses page-number pagination.

Testing

  • make test passes.
  • make lint passes.
  • Verified end to end against camUrban/PteraSoftware (a repo with recent issue activity): before this change the three signals were 0/0/0; after, they are 117/100/1.19, matching direct queries to the search API for the same 90-day window.

The repo issues list endpoint now uses cursor-based pagination, which
no longer exposes the last page number. FetchIssueCount relied on that
number (with per_page=1) to count issues, so it silently returned 0 for
every repository, which also zeroed issue_comment_frequency.

Count issues via the search API's total_count instead, preserving the
existing semantics: both issues and PRs are counted, filtered on
updated time within the lookback, with the closed state expressed as
is:closed. The 5xx fallback to MaxIssuesLimit is unchanged.

Fixes ossf#816

Signed-off-by: Cameron Urban <camerongurban@gmail.com>
@ruohai0925

Copy link
Copy Markdown

+1 on this — I hit the same bug independently and can confirm both the diagnosis
and the impact.

The Link header on /repos/{owner}/{repo}/issues now looks like this (note
the opaque after= cursor and the complete absence of rel="last"):

Link: <https://api.github.com/repositories/150626842/issues?state=all&since=2026-05-04T00%3A00%3A00Z&per_page=1&after=Y3Vyc29yOnYyOpLPAAABn8D-mnjPAAAAASx2iuA%3D&page=2>; rel="next"

so resp.LastPage is 0 and FetchIssueCount returns 0 unconditionally.

Some measurements on top of the camUrban/PteraSoftware numbers already in the
description, in case they are useful for review — criticality_score -depsdev-disable, before vs. after fixing the count:

repo updated_issues closed_issues comment_frequency default_score
BLAST-WarpX/warpx 0 → 690 0 → 572 0 → 0.5 0.53654 → 0.62253
ruohai0925/IAMReX 0 → 2 0 → 2 0 → 0 0.38916 → 0.40145

The 690/572 figures match what the search API reports for the same 90-day
window, which is a nice independent check on the approach taken here.

Worth emphasising how much this distorts things: WarpX moves by +0.086. The
three affected signals carry 2.0 of the 10.5 total weight in
original_pike.yml, so every published score for an active project is currently
biased low, and the more issue activity a project has the more it loses.

Two small things I noticed while looking at the same code, both arguing that the
scope here is right:

  • FetchIssueCommentCount (/issues/comments) and FetchTotalContributors
    (/contributors) do still return rel="last" (I see page=347 and page=65
    respectively), so leaving them on the per_page=1 trick is correct for now.
  • internal/collector/github/legacy has no test coverage, so there is nothing
    guarding against this class of regression. I wrote httptest-backed tests for
    FetchIssueCount while investigating (cursor fallback, rel="last" fast
    path, 5xx handling, the MaxIssuesLimit cap, the since window) — happy to
    send them as a follow-up to this PR if that would help it land.

I also opened #830 with a paging-based fix before seeing how far along this one
was. The search API approach here is cleaner and I would rather see this one
merged — I'll close mine if this moves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

There's abnormal for command of 'criticality_score'

2 participants