2 Commits
Author SHA1 Message Date
Sebastian "Sebbie" SilbermannandClaude Code 084f5f2457 [ci] Compare size against merge base (#37355)
Sizebot compared the pull request head build against the build of
`pull_request.base.sha`, which is the tip of the base branch at event
time, not the commit the pull request diverged from. The field's
semantics are undocumented in GitHub's API schema (the OpenAPI
description types it as a bare string); the observed behavior and the
compare API's `merge_base_commit` confirm the difference.

The difference between `pull_request.base.sha` and the merge base is
confirmed with an example in https://github.com/react/react/pull/37356

The sizebot job now resolves the merge-base through the compare API and
downloads the base build for that commit instead, so the report only
ever contains the pull request's own changes. The job gains `contents:
read` for the compare call.

When no base build can be downloaded for the merge-base, for example
because its artifacts aged out of the retention window or its run
failed, the sizebot job records a `base-build-not-found` result instead
of failing immediately. `render-comment.js` on the default branch
renders that as a warning comment naming the base commit and writes the
`sizebot-problem.txt` marker, so the comment workflow fails its check
after posting the warning, the same pattern already used for build
configuration drift. The sizebot job itself intentionally stays green: a
failed run would make the renderer discard the results and mask the
warning with a generic "did not complete" message.

Co-authored-by: Claude Code (kimi-k3[1m]) <noreply@anthropic.com>
2026-09-02 12:29:06 +02:00
Sebastian "Sebbie" SilbermannandClaude Code 675a29c3e9 [ci] Rebuild sizebot on the GitHub Actions token (#37322)
The build size comparison comment was posted by Danger, which
authenticated with a personal access token hardcoded in
`scripts/tasks/danger.js`. That token has since been revoked, so sizebot
has been posting nothing at all (due to e.g.
https://github.com/react/react/actions/runs/32181295467/job/95855395224?pr=37315).
This change rebuilds it on the short-lived `GITHUB_TOKEN` that Actions
mints per run and a new workflow only responsible for rendering
untrusted JSON input as markdown in a PR comment.

A straight token swap would not have worked. Fork pull requests did
receive sizebot comments, but only because the token was in checked-out
source: the sizebot job runs on the `pull_request` trigger, where a
fork's `GITHUB_TOKEN` is read-only and cannot comment. The comment
therefore moves to a new `workflow_run` workflow,
`runtime_sizebot_comment.yml`, which runs in this repository with a
writable token no matter where the pull request came from. It posts a
placeholder when a build is requested and rewrites it in place when the
build completes, fails, is cancelled, or is held for maintainer
approval.

The measurement stays on the unprivileged side of that boundary which
are recorded as raw sizes into a `sizebot-results` artifact, and the new
workflow downloads only that JSON and renders it from a default-branch
checkout. The job holding `pull-requests: write` never unpacks a build
produced by a fork, which matters because the existing base-build
download justifies using an unverified artifact on the grounds that the
job has restricted permissions. Thresholds, the critical bundle list,
and the comment template all live on the trusted side, and the renderer
validates every field it reads out of the artifact so that a crafted
build path cannot inject markdown. The pull request number is resolved
from the API rather than from the artifact, since a number read from
fork-controlled data would let any contributor post a bot comment on an
arbitrary pull request.

Resolving that number needs a branch lookup rather than any of the
obvious approaches. `workflow_run.pull_requests` is empty for fork runs,
and neither `commits/{sha}/pulls` nor the search API indexes fork pull
request head commits, so the workflow looks the pull request up by
`owner:ref` instead.

A comment is only ever left alone in one situation: when it already
describes the pull request's current head and the event being handled
belongs to an older commit. Everything else is written, and marked stale
whenever the report does not describe the current head. That single rule
covers both an old run finishing after a force push and a new build
superseding a report already on display, and in the latter case the
previous numbers stay visible instead of being blanked back to a
placeholder.

The results file carries a `version` field. Its writer is whatever
`compare-sizes.js` a pull request branch happens to carry, while its
reader is on the default branch, so the two can mismatch and the
renderer needs to be able to say so instead of misrendering a table.

Porting the table fixed a longstanding bug in `change()`. Testing
`decimal < 0.0001` reported every size decrease as unchanged, which is
why `signDisplay: 'exceptZero'` never had a negative number to render: a
709.04 kB to 708.68 kB drop printed as `=`. It now compares the
magnitude.

Co-authored-by: Claude Code (kimi-k3[1m]) <noreply@anthropic.com>
2026-08-23 17:29:26 +02:00