From 83097c8305532c6c48355219cadca6325d9989e3 Mon Sep 17 00:00:00 2001 From: Baptiste LAFOURCADE Date: Thu, 13 Aug 2026 23:40:53 +0200 Subject: [PATCH 1/4] ci: render the star history chart in the repo's own CI GitHub restricted the stargazers API to a repository's own admins and collaborators on June 30 2026, so the third-party chart the README embeds now returns a placeholder telling readers the data is unavailable. The repository can still read its own stargazers, so the chart is rendered here from that data and published on the star-history orphan branch. No credential leaves the repository, and the renderer is deterministic, so a run that finds no new star produces no commit. The push trigger is temporary: schedule and workflow_dispatch only fire from the default branch, so it is the only way to exercise the workflow before the merge. It is removed later in this same pull request. Co-Authored-By: Claude Opus 5 --- .github/workflows/star-history.yml | 68 +++++++++++++++ scripts/generate-star-history.mjs | 135 +++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 .github/workflows/star-history.yml create mode 100644 scripts/generate-star-history.mjs diff --git a/.github/workflows/star-history.yml b/.github/workflows/star-history.yml new file mode 100644 index 00000000..ff5b9033 --- /dev/null +++ b/.github/workflows/star-history.yml @@ -0,0 +1,68 @@ +name: Star history + +# Regenerates the star history chart the README embeds. GitHub restricted the +# stargazers API to a repository's own admins and collaborators on June 30 2026, +# so no third-party service can draw this chart any more โ€” only the repository +# itself can, with its own token. +# +# The SVG is published on the `star-history` orphan branch rather than committed +# to main: main requires a pull request, and a data-only branch keeps generated +# bytes out of the source history while staying servable over raw.githubusercontent. + +on: + schedule: + - cron: "0 5 * * 1" # Mondays 05:00 UTC + workflow_dispatch: + push: + branches: [blafourcade/fix-stars] # TEMPORARY: schedule and dispatch only fire from the default branch, so this proves the workflow before the merge. Removed in this same PR. + +concurrency: + group: star-history + cancel-in-progress: false + +permissions: + contents: write + +jobs: + star-history: + name: Render the chart and publish it + runs-on: ubuntu-latest + env: + BRANCH: star-history + FILE: star-history.svg + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Setup Node + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: "22" + + - name: Render the chart + env: + GH_TOKEN: ${{ github.token }} + run: node scripts/generate-star-history.mjs > "$FILE" + + - name: Publish it to the ${{ env.BRANCH }} branch + run: | + set -euo pipefail + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + parent="" + if git fetch --depth=1 origin "$BRANCH" 2>/dev/null; then + parent=$(git rev-parse FETCH_HEAD) + fi + + blob=$(git hash-object -w "$FILE") + tree=$(printf '100644 blob %s\t%s\n' "$blob" "$FILE" | git mktree) + + # The renderer is deterministic, so an identical tree means no new star. + if [ -n "$parent" ] && [ "$(git rev-parse "$parent^{tree}")" = "$tree" ]; then + echo "Star history unchanged." + exit 0 + fi + + commit=$(git commit-tree "$tree" ${parent:+-p "$parent"} -m "chore(ci): refresh star history chart") + git push origin "$commit:refs/heads/$BRANCH" diff --git a/scripts/generate-star-history.mjs b/scripts/generate-star-history.mjs new file mode 100644 index 00000000..0764b051 --- /dev/null +++ b/scripts/generate-star-history.mjs @@ -0,0 +1,135 @@ +#!/usr/bin/env node +// Renders the repository's star history as an SVG on stdout, from the GitHub +// stargazers API. Since June 30 2026 that API only answers a repository's own +// admins and collaborators, which killed the third-party chart services the +// README used to embed. Running it here, with the repository's own credentials, +// is the only way left to keep a live chart. +// +// GH_TOKEN=$(gh auth token) node scripts/generate-star-history.mjs > star-history.svg +// +// The output is deterministic: identical star data yields identical bytes, so a +// scheduled run that finds no new star produces no commit. Nothing renders the +// current date, and no