GitHubCard Team

这篇文章也有 English 版本。

GitHub 的隐私安全 Star History API:GitHubCard 做了什么更新

2026 年 7 月 GitHub 正式收紧 stargazer 名单权限(6 月 30 日发公告、7 月起生效)之后,不少 README 里的 Star History 图一夜之间变空白了。其实画图工具根本不关心是谁点的 star,只是旧接口没给别的选择:你只能一页页拉 GET /repos/{owner}/{repo}/stargazers,留下 starred_at 时间戳,再把用户信息丢掉。

9 月 4 日,GitHub 把工具真正需要的接口补上了:GET /repos/{owner}/{repo}/stargazers/history。它直接按自然周返回聚合计数,响应里不再带任何用户身份。

GET /repos/{owner}/{repo}/stargazers/history 返回什么

请求时带上 Accept: application/vnd.github+json 和 X-GitHub-Api-Version: 2026-03-10。返回数组按自然周从近到远排列:

[
  {
    "week": 1772928000,
    "total": 3,
    "days": [1, 0, 2, 0, 0, 0, 0]
  }
]

week 是这一周起点的 Unix 时间戳,total 是本周新增的 star 总数,days 是从周日算起的 7 个日计数。注意这里只统计现有的 star——如果有人曾经点过 star 后来又取消了,不会计入这些周桶中。

单次请求最多返回 30 周(per_page=30)。page 往大翻,时间就往仓库创建那一周倒推,上限 100 页。哪怕某一周是 0 新增,这一周也会留在数组里,多页直接拼起来就是连续曲线,不用自己补空档。

公开仓库可以匿名调这个接口。带 token 只是为了拿更高的速率限额,既不能恢复旧的用户名单,也不能读私有仓库。

完整的接口定义可以看 GitHub REST API 文档、9 月 4 日 Changelog,以及 GitHub 团队写的工程复盘。

旧接口为什么会把数据库拖垮

旧的 stargazer 列表一页最多 100 人。像 react/react 这种 25 万多 star 的仓库,拉完完整曲线要发 2,511 次请求;更糟的是分页实现里有个 bug,每次翻页都会把全仓库的当前 star 重新数一遍。

如果只是在 SQL 里先按周 GROUP BY、再用 LIMIT 和 OFFSET 分页,问题还在——数据库每次还是得先把全表扫完、分组完,最后才切出一页。GitHub 现在的做法是先把 page 和 per_page 换算成带索引的 created_at 时间范围,只捞这几周里的记录出来按天汇总。同样是 react/react,拉完历史从两千多次请求降到了 24 次。

契约里要注意的三件事

GitHub 在工程文章里把新接口的边界交待得很清楚:

  • 它统计的是当前仍在的 star,不是事件流水。 有人取消 star,那条记录就会消失,曲线反映的是「今天还点着 star 的人分别是哪天点的」。
  • 周边界不保证对齐 UTC。 它适合看发布前后的增长趋势,不适合当精确到 UTC 自然日的审计账本。
  • 单周暴涨时仍然可能慢。 先按时间过滤只能锁住单次请求跨多少周,锁不住某一周之内突然涌进来的 star 数量。

我们改了什么

我们把仓库卡片的 Star History 控件切到了这个聚合接口,同时撤掉了之前要求登录授权的门槛:

  1. 公开数据路由先校验目标仓库是否为公开仓库。
  2. 分页读取 /stargazers/history,把仓库创建周作为 0 点基线,再把日计数累加为增长曲线。
  3. 保存或发布设计时,把算好的序列写进控件快照。
  4. 已发布的卡片直接渲染快照,不会在每次被访问时再去请求 GitHub。

具体来说,曲线上的每一个数字是按这三步从周桶算出来的:

  • 以创建周作为 0 点起点:接口翻到最后一页就是仓库创建那一周,我们取这一周的起始日期作为曲线的第一个点 (date, 0)。
  • 展开有新增的自然日:把每个周桶里的 days[0..6](周日到周六)换算成具体日期,只保留 count > 0 的日期,避免没有 star 的空档期塞入大量重复平点。
  • 按时间顺序累加:将所有有新增的日期从早到晚排序,逐日累加(value += count)。曲线上任意一点 (date, value) 代表截至当天仍保留的累计 star 数,最后一个点的值等于所有周桶 total 的总和。

现在任何公开仓库都可以直接以访客身份添加或刷新 Star History,不再需要先登录 GitHub,也不用为了画张图去授权范围过宽的 public_repo。如果你手头有旧卡片还是空白的,打开仓库卡片编辑器刷新一次 Star History 并重新发布就行;发布后的嵌入方式可以看如何在网站或 README 中嵌入 GitHub 仓库卡片。

FAQ

添加 Star History 还需要登录 GitHub 或授权 public_repo 吗?

不需要。公开仓库的聚合历史接口支持匿名访问,访客可以直接在编辑器里添加或刷新 Star History。只有保存设计或发布卡片时才需要登录。

新接口会暴露是谁给仓库点了 star 吗?

不会。GET /repos/{owner}/{repo}/stargazers/history 只返回每周总数和 7 个日计数,不包含用户名、头像或任何个人身份字段。

为什么我之前发布的 Star History 嵌入图还是空白?

7 月到 8 月权限收紧期间生成的卡片,可能还没有写入有效快照。在仓库卡片编辑器里打开对应仓库,点一次刷新并重新发布,嵌入图就会恢复。


GitHubCard Team

Turn this into a card

Turn the ideas from this article into an editable GitHub profile card, repo card, or README section.