Skip to content

ci: Skip GitHub Actions runs PRs don't need; never cancel master runs - #4205

Merged
ntucker merged 12 commits into
masterfrom
claude/project-thread-94yvlu
Oct 5, 2026
Merged

ntucker merged 12 commits into
masterfrom
claude/project-thread-94yvlu

Conversation

@ntucker

@ntucker ntucker commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Requested by Nathaniel · project thread

Motivation

GitHub Actions queues back up (16 queued / 2 running on 2026-10-05, with master's Release and site deploy waiting ~10 min). Over the last ~800 runs (about 15 hours):

  • 31% (245 runs) came from Renovate branches, across 48 distinct commits. Master requires up-to-date branches (strict: true), so Renovate's default rebaseWhen: auto rebases every open Renovate PR on each master push and re-runs all of its CI (CircleCI included).
  • 11 Bundle Size runs on master pushes: compressed-size-action measures on push but only reports on PRs ("No PR associated with this action run").
  • Benchmarks, Bundle Size and CodeQL ran on every draft push, and packages/** / packages/core/src/** filters fired on test- or README-only edits.

Solution

  • .github/renovate.json: rebaseWhen: conflicted. Renovate PRs need Update branch before merging (strict protection already enforced that for the merge itself).
  • Benchmark, Benchmark React, Benchmark Spread, Bundle Size, CodeQL: job-level if: ${{ !github.event.pull_request.draft }} plus ready_for_review in pull_request.types, so they run once a PR is marked ready. Correctness checks (editor-types, skills, website) still run on drafts. None of these are required checks.
  • paths drop __tests__/, typescript-tests/, src-*-types/ and *.md under packages/ (Bundle Size, editor-types, benchmarks), none of which those jobs read. Bundle Size also skips graphql, test and vue, which examples/test-bundlesize doesn't bundle. CodeQL triggers only on shipped source (packages/*/src/**, packages/*/node.mjs); the weekly scheduled scan is unchanged.
  • Bundle Size: PR-only. Master's yarn cache is still warmed by editor-types/skills, which share the setup-node cache key.
  • Master never shows a cancelled run. Cancelled push runs (website, skills, Vercel Release Deployment) marked master commits red, which hurts npm search scoring. PR runs still cancel superseded ones; push runs of check workflows get a unique concurrency group (${{ github.head_ref || github.run_id }}). Release and Beta Release use a shared group with queue: max, so runs go one at a time in push order and pending runs are kept instead of cancelled. (actionlint 1.7.12 doesn't know queue yet; the repo doesn't run it in CI.)
  • Single production deploy. site-release.yml is removed: Vercel's Git integration already deploys every master push to production (gated by website/scripts/vercel-ignore.sh), so the workflow deployed the same site twice. That workflow cloned 800 commits deep for Docusaurus' "Last updated" dates. Vercel clones about 10 and has no origin remote, so website/scripts/deepenGitHistory.cjs (called from docusaurus.config.ts during Vercel builds) fetches 800 more by repo URL and logs the outcome. Verified on the preview: /graphql shows Jul 12, 2026.
  • Dependency gate. Bundle Size and the benchmarks list yarn.lock in paths, and a reusable dependency-gate.yml (scripts/ci-deps-relevant.mjs) decides whether the main job runs. It runs when a non-manifest input changed, a measured workspace's manifest changed (or a manifest of a workspace package it ships), or the yarn.lock resolutions reachable from those workspaces' dependencies or the babel/browserslist/core-js tooling changed. On recent Renovate PRs: pkg: Update all non-major dependencies #4199 (React Native, website deps) and pkg: Update Yarn to v4.18.1 #4203 (yarn upgrade) skip; pkg: Update build packages (major) #4200 and pkg: Update non-major dependencies (excluding React Native) #4187 (build tooling) run. Benchmarks used to ignore dependency bumps entirely, so a React or babel bump now runs them.
  • .cursor/rules/ci-config.mdc documents the conventions.

Simulated against the changed files of 31 recent PRs (#4164–#4203), workflows triggered per push:

before after
ready PR 92 84
draft PR 92 58
master push (merge) 123 106

The Renovate change is the biggest saving and isn't in the table: it removes the per-master-push rebases of each open Renovate PR. Concurrency groups were already in place for every workflow (Release intentionally doesn't cancel). actionlint passes.

Open questions

Skipping report-style workflows on drafts means bundle-size and benchmark comments appear only once a PR is marked ready.

🤖 Generated with Claude Code

https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN


Generated by Claude Code


Note

Medium Risk
CI and deploy orchestration changes (dependency gate, removed Actions production deploy, release queuing); the gate and git-deepen scripts fail open, but mis-tuned paths could skip needed benchmark/bundle runs or leave wrong last-updated dates if Vercel fetch fails.

Overview
This PR cuts unnecessary GitHub Actions load and avoids red/cancelled checks on master, while tightening when expensive report workflows run.

Renovate now uses rebaseWhen: conflicted so open dependency PRs are not rebased (and fully re-CI’d) on every master push under strict branch protection.

Benchmark, Bundle Size, and CodeQL skip draft PRs until ready_for_review, use narrower paths (e.g. exclude tests, markdown, and packages Bundle Size does not bundle), and Bundle Size is PR-only (push runs had no PR to comment on). Benchmarks and Bundle Size add a reusable dependency-gate.yml backed by scripts/ci-deps-relevant.mjs so yarn.lock/manifest-only bumps that cannot affect measured workspaces skip the main job; unclassified changes still run (fail open).

Concurrency is adjusted so PRs can cancel superseded runs but master push workflows use unique groups (github.run_id) instead of sharing a cancellable group. Release and Beta Release use queue: max so pending releases are queued rather than cancelled.

Production docs deploy drops the duplicate site-release.yml Actions workflow; production stays on Vercel Git integration (still gated by vercel-ignore.sh). deepenGitHistory.cjs runs during Vercel builds to deepen the shallow clone so Docusaurus “Last updated” dates are accurate.

CI conventions are documented in .cursor/rules/ci-config.mdc.

Reviewed by Cursor Bugbot for commit 292a67e. Bugbot is set up for automated code reviews on this repo. Configure here.


Generated by Claude Code

- Renovate rebases only on conflicts. Strict branch protection made the
  default rebase every Renovate PR (rerunning all CI) on each master push.
- Benchmarks, Bundle Size and CodeQL skip draft PRs and run once marked ready.
- Path filters drop tests, typescript-tests, legacy type overlays and
  markdown under packages/; CodeQL only triggers on shipped source.
- Bundle Size no longer runs on master pushes, where it can't report.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN
@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs-site Ready Ready Preview Oct 5, 2026 10:11pm UTC

Request Review

@ntucker ntucker self-assigned this Oct 5, 2026
@changeset-bot

changeset-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 292a67e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

- Skip Bundle Size for packages the size test doesn't bundle
- CodeQL matches node.mjs instead of every root .mjs
- Drop repeated draft comments (documented in ci-config.mdc)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN
@ntucker
ntucker marked this pull request as ready for review October 5, 2026 19:54
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at e50f1a3. Nothing for this PR to change.

What I checked:

  • The path filters are ordered correctly. Each ! exclusion comes after the packages/** include it narrows, and no later include adds those paths back. Every on: block still has at least one positive pattern.
  • The excluded paths really aren't read. The editor-types rollup bundles from packages/*/lib (tsc output), not from __tests__, typescript-tests, src-*-types or READMEs. examples/test-bundlesize only depends on img, react and rest, so leaving out graphql, test and vue is safe.
  • Making Bundle Size PR-only is safe. compressed-size-action builds the base branch itself, so it never relied on the master push run.
  • The job-level if: ${{ !github.event.pull_request.draft }} evaluates to true on push and schedule (where pull_request is null), so master benchmarks and the weekly CodeQL scan still run.
  • The Renovate config has no automerge, so rebaseWhen: conflicted doesn't stall anything. The cost (Update branch before merging, and Renovate stops managing a branch someone else touched) is written down in ci-config.mdc.

Nit: the PR body still says CodeQL triggers on packages/*/*.mjs. The second commit narrowed that to packages/*/node.mjs.

FOLLOW_UP (after merge, not this PR): rebaseWhen: conflicted works around strict up-to-date branch protection for Renovate only. Every human or Claude PR still has to rerun all of CI after each master merge. A GitHub merge queue would fix the root cause for every PR. You'd drop strict: true, add merge_group to the required workflows, and point CircleCI at gh-readonly-queue/* branches. After that, Renovate could go back to its default rebase setting. That's worth weighing once this lands and the queue numbers are back in.

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks. The nit was already fixed: the PR body was updated to packages/*/node.mjs along with the second commit. The merge-queue idea is queued as its own follow-up for after this PR merges.


Generated by Claude Code

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark React

Details
Benchmark suite Current: 292a67e Previous: 10e15cc Ratio
data-client: getlist-100 129.87 ops/s (± 4.9%) 173.93 ops/s (± 5.0%) 1.34
data-client: getlist-500 40.98 ops/s (± 4.9%) 53.76 ops/s (± 4.8%) 1.31
data-client: update-entity 307.77 ops/s (± 8.0%) 434.78 ops/s (± 10.5%) 1.41
data-client: update-user 303.03 ops/s (± 7.7%) 425.72 ops/s (± 10.2%) 1.40
data-client: getlist-500-sorted 41.75 ops/s (± 9.9%) 55.26 ops/s (± 8.5%) 1.32
data-client: update-entity-sorted 274.02 ops/s (± 6.2%) 400 ops/s (± 7.0%) 1.46
data-client: update-entity-multi-view 289.92 ops/s (± 6.4%) 408.33 ops/s (± 7.5%) 1.41
data-client: list-detail-switch-10 7.43 ops/s (± 9.1%) 12.71 ops/s (± 7.5%) 1.71
data-client: update-user-10000 73.53 ops/s (± 14.3%) 84.03 ops/s (± 15.3%) 1.14
data-client: invalidate-and-resolve 34.55 ops/s (± 5.2%) 45.98 ops/s (± 4.7%) 1.33
data-client: unshift-item 192.31 ops/s (± 8.0%) 263.16 ops/s (± 4.6%) 1.37
data-client: delete-item 263.16 ops/s (± 5.4%) 333.33 ops/s (± 6.0%) 1.27
data-client: move-item 163.93 ops/s (± 9.6%) 204.17 ops/s (± 9.8%) 1.25

This comment was automatically generated by workflow using github-action-benchmark.

claude added 2 commits October 5, 2026 20:07
Cancelled push runs (website, skills, site deploy) marked master commits
red. PR runs still cancel superseded ones; push runs get their own
concurrency group, and an older site deploy skips itself when a newer push
changed the site.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN
@ntucker ntucker changed the title ci: Skip GitHub Actions runs PRs don't need ci: Skip GitHub Actions runs PRs don't need; never cancel master runs Oct 5, 2026

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): CHANGE_THIS_PR at 6b2ba4f (the new "Never cancel GitHub Actions runs on master" commit). Splitting PR and push groups for codeql, editor-types, site-preview and skills is right. Two things in the rest of it:

  1. site-release.yml can now deploy an older site over a newer one. With its concurrency group gone, two master pushes that both touch the site build in parallel. The "newer site change" check runs once, before the build, so the older run only skips if the newer push had already landed by then. If push B lands while run A is building, both pass the check, and whichever vercel deploy --prod finishes last owns production (unless Vercel itself refuses to promote an older commit, which I couldn't confirm). Before this commit cancel-in-progress ruled that out. Today's back-to-back merges (ci: Shorten CircleCI setup, report coverage sooner, speed up the website check #4201, docs(website): Framework selector switches between equivalent pages #4202, docs(vue): Update README for Vue docs, plugin setup and testing #4204 within minutes) are exactly this pattern.

  2. The new ci-config.mdc line says release.yml and the benchmark push groups "still queue". They only partly do. By default GitHub keeps one pending run per group and cancels it when another arrives, so three quick merges still leave a cancelled (red) Release run on master, which is what this commit is meant to stop.

Smaller fix for both: GitHub concurrency now takes queue: max (workflow syntax docs), which keeps up to 100 pending runs in FIFO order instead of cancelling them. It can't be combined with cancel-in-progress: true.

  • site-release.yml: add back a group with queue: max and no cancel-in-progress. Runs then go one at a time, and the existing skip step becomes race-free, so keep it. A pending older run starts first, sees the newer site change and skips.
  • release.yml: switch to group: plus queue: max.
  • ci-config.mdc: describe what actually happens. Please check that the repo's actionlint knows the queue key.

I tried to knock this down. The skip check can't close the race because it runs before a multi-minute build, and queue: max is a few lines against the hand-rolled alternative (re-checking right before vercel deploy), so the simpler path holds.

FOLLOW_UP (after merge, not this PR): the benchmark push groups have the same pending-cancel behavior. Their cancel-in-progress is an expression that's true on PRs, and I couldn't confirm GitHub accepts queue: max next to it, so try that separately.

Nit: the PR body still says site-preview.yml is untouched to stay clear of #4201. #4201 has merged and this commit does touch it now.

…sure

A reusable gate diffs yarn.lock and the workspace manifests: bumps that
can't reach the measured workspaces or the build tooling (test, lint,
React Native, website deps) skip the job. Benchmarks now also run for
relevant bumps (react, babel, their own deps), which they ignored before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark Spread

Details
Benchmark suite Current: 292a67e Previous: b4b502d Ratio
setOneEntity in 10k entity store 196 ops/sec (±0.67%) 155 ops/sec (±0.95%) 0.79

This comment was automatically generated by workflow using github-action-benchmark.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6b2ba4f. Configure here.

Comment thread .github/workflows/site-release.yml Outdated
Dropping site-release's group let two deploys overlap, so an older one
could finish last. A shared group with queue: max runs them one at a
time in push order without cancelling pending runs; Release and Beta
Release get the same so a third quick push no longer cancels one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Details
Benchmark suite Current: 292a67e Previous: 10e15cc Ratio
normalizeLong 791 ops/sec (±4.19%) 424 ops/sec (±4.38%) 0.54
normalizeLong Values 675 ops/sec (±0.86%) 385 ops/sec (±0.30%) 0.57
normalizeLong Scalar 575 ops/sec (±3.46%) 369 ops/sec (±3.63%) 0.64
normalizeLong Scalar update 1680 ops/sec (±1.27%) 918 ops/sec (±0.21%) 0.55
denormalizeLong 395 ops/sec (±5.36%) 245 ops/sec (±5.79%) 0.62
denormalizeLong Values 349 ops/sec (±4.26%) 229 ops/sec (±4.35%) 0.66
denormalizeLong donotcache 1931 ops/sec (±3.08%) 992 ops/sec (±1.01%) 0.51
denormalizeLong Values donotcache 1369 ops/sec (±1.66%) 752 ops/sec (±0.22%) 0.55
denormalizeLong Scalar donotcache 2007 ops/sec (±1.26%) 1029 ops/sec (±0.24%) 0.51
denormalizeShort donotcache 500x 2538 ops/sec (±0.54%) 1402 ops/sec (±0.10%) 0.55
denormalizeShort 500x 989 ops/sec (±5.77%) 639 ops/sec (±6.73%) 0.65
denormalizeShort 500x withCache 9396 ops/sec (±1.75%) 6531 ops/sec (±0.21%) 0.70
queryShort 500x withCache 5728 ops/sec (±0.54%) 3178 ops/sec (±2.76%) 0.55
buildQueryKey All 96818 ops/sec (±1.58%) 59344 ops/sec (±1.21%) 0.61
query All withCache 10594 ops/sec (±6.38%) 6251 ops/sec (±2.07%) 0.59
denormalizeLong with mixin Entity 340 ops/sec (±6.71%) 217 ops/sec (±7.98%) 0.64
denormalizeLong withCache 15040 ops/sec (±0.35%) 8085 ops/sec (±0.26%) 0.54
denormalizeLong withCache (Scalar churn) 14818 ops/sec (±1.14%) 8027 ops/sec (±1.01%) 0.54
denormalizeLong Values withCache 10011 ops/sec (±1.61%) 4995 ops/sec (±1.81%) 0.50
denormalizeLong Scalar withCache 9098 ops/sec (±1.48%) 6193 ops/sec (±0.36%) 0.68
denormalizeLong Scalar update withCache 6331 ops/sec (±0.62%) 3649 ops/sec (±0.23%) 0.58
denormalizeLong All withCache 14087 ops/sec (±0.33%) 6359 ops/sec (±0.29%) 0.45
denormalizeLong Query-sorted withCache 10925 ops/sec (±7.18%) 6428 ops/sec (±2.11%) 0.59
denormalizeLongAndShort withEntityCacheOnly 3171 ops/sec (±1.27%) 1742 ops/sec (±0.27%) 0.55
denormalize bidirectional 50 6869 ops/sec (±8.08%) 4510 ops/sec (±12.09%) 0.66
denormalize bidirectional 50 donotcache 74320 ops/sec (±0.54%) 41392 ops/sec (±0.61%) 0.56
getResponse 7830 ops/sec (±4.44%) 4474 ops/sec (±3.73%) 0.57
getResponse (null) 20043810 ops/sec (±0.68%) 10187553 ops/sec (±0.57%) 0.51
getResponse (clear cache) 317 ops/sec (±8.68%) 205 ops/sec (±8.56%) 0.65
getSmallResponse 5725 ops/sec (±1.75%) 3555 ops/sec (±0.56%) 0.62
getSmallInferredResponse 5034 ops/sec (±2.16%) 2825 ops/sec (±0.10%) 0.56
getResponse Collection 8263 ops/sec (±2.54%) 4545 ops/sec (±2.96%) 0.55
get Collection 6096 ops/sec (±0.63%) 3019 ops/sec (±0.19%) 0.50
get Query-sorted 8651 ops/sec (±4.77%) 5066 ops/sec (±1.38%) 0.59
setLong 781 ops/sec (±0.57%) 427 ops/sec (±0.31%) 0.55
setLongWithMerge 422 ops/sec (±0.47%) 253 ops/sec (±0.22%) 0.60
setLongWithSimpleMerge 466 ops/sec (±1.32%) 264 ops/sec (±0.88%) 0.57
setSmallResponse 500x 1627 ops/sec (±1.18%) 934 ops/sec (±1.54%) 0.57
setMany 50x one-per-row 216 ops/sec (±0.39%) 144 ops/sec (±0.51%) 0.67
setMany 50 batch 6111 ops/sec (±1.54%) 3609 ops/sec (±0.48%) 0.59
setMany 500x one-per-row 21.96 ops/sec (±1.02%) 14.49 ops/sec (±0.59%) 0.66
setMany 500 batch 2707 ops/sec (±0.58%) 1426 ops/sec (±0.21%) 0.53

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 103 kB

ℹ️ View Unchanged
Filename Size
examples/test-bundlesize/dist/App.js 1.46 kB
examples/test-bundlesize/dist/polyfill.js 307 B
examples/test-bundlesize/dist/rdcClient.js 10.9 kB
examples/test-bundlesize/dist/rdcEndpoint.js 8.07 kB
examples/test-bundlesize/dist/rdcNextjs.js 12.3 kB
examples/test-bundlesize/dist/rdcPipeableStream.js 9.64 kB
examples/test-bundlesize/dist/react.js 59.7 kB
examples/test-bundlesize/dist/webpack-runtime.js 784 B

compressed-size-action

A queued run that skipped because a newer push changed the site left
production stale if that push had no run ([skip ci]). Deploying the
branch tip covers it and still never goes backwards.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff review at 6b2ba4f:

  1. Deploy race: agreed, fixed in this PR. site-release.yml uses group + queue: max again (d4bc406). I replaced the skip step with deploying the branch tip (c7259f9), because a skipped older run left production stale whenever the newer push had no run of its own ([skip ci]).
  2. Release still cancelling: agreed, fixed in this PR. release.yml and beta-release.yml now use queue: max, and ci-config.mdc describes what actually happens. I confirmed the key in GitHub's docs source (data/reusables/actions/actions-group-concurrency.md). actionlint 1.7.12 doesn't recognize queue yet, but this repo doesn't run actionlint in CI.
  3. Benchmark push groups: queued as a follow-up, as you suggested. The open question there is whether queue can depend on the event alongside the PR cancel-in-progress expression.
  4. PR body nit: fixed.

This push also adds the dependency gate for Bundle Size and the benchmarks that Nathaniel asked for (see the PR body).


Generated by Claude Code

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): CHANGE_THIS_PR at c7259f9, with one small item. Both points from my last review are fixed: release.yml, beta-release.yml and site-release.yml queue with queue: max, and deploying the branch tip is better than the skip step I suggested, since it also covers a [skip ci] push. The ci-config.mdc wording now matches.

The dependency gate (8b86287) is a reasonable idea with real evidence behind it (#4199/#4203 skip, #4200/#4187 run), and it fails open where it can't classify. One thing to change before merge:

Don't hand-copy each workflow's paths into the gate's with.paths. Four workflows now carry the same glob list twice, held together by a # paths above, one per line comment. If they drift, it fails silently in the wrong direction. Say a path is in on.paths but missing from with.paths, and a PR touches only that path. The workflow triggers, the gate's first check finds no matching files, the manifests and lockfile are unchanged, so it prints not relevant and the benchmark or Bundle Size is skipped on a real code change. Nothing turns red, so nobody notices. The lists are already slightly uneven: the benchmarks list dependency-gate.yml in on.paths and bundle_size.yml doesn't.

Either of these keeps the behavior with a single source of truth:

  • Read the caller's filter in the gate. Inside a reusable workflow, github.workflow_ref is the caller's workflow file, and yq is preinstalled on ubuntu-latest. So yq '.on.pull_request.paths[]' (or .on.push.paths[] on push) on that file gives the list, and the paths input goes away.
  • Or drop paths completely and count any changed file other than manifests, lockfiles, .yarn/** and .yarnrc.yml as relevant. That's simpler still. The cost is an occasional extra run on a human PR that mixes a dependency bump with unrelated edits. The Renovate cases that motivate the gate still skip.

I tried to talk myself out of this. The gate is fail-open everywhere else, and this is the one place a maintenance slip turns into a silent skip. Fixing it removes code rather than adding it.

FOLLOW_UP (no change needed here):

  • The gate is a separate runner job, so every qualifying push now queues up to four extra short jobs, including ordinary code PRs where the answer is always "relevant". That works against the queue-pressure goal a little. It's worth checking the queue after a week, and folding the gate into the main jobs if it shows up.
  • The reachability walk seeds from the measured workspaces plus BUILD_TOOLS, not from root devDependencies. If a root-only build dependency that isn't under @babel/, @anansi/babel-preset or browserslist is added later, its bumps will skip. babel-plugin-module-resolver is fine today only if it's reachable through @anansi/babel-preset. Something to keep in mind when the build toolchain changes.

Bugbot is still running on c7259f9, so its result is still needed before merge.

Hand-copied path lists could drift and silently skip a real change.
The gate now reads the caller's own on.<event>.paths (github.workflow_ref
names the caller), and babel-plugin-module-resolver, which
babel.config.js requires directly, is a build tool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff review at c7259f9:

  • Hand-copied with.paths: agreed, fixed in this PR (2201d6e). The gate now reads the caller's own on.<event>.paths with yq -r, using github.workflow_ref, which names the caller inside a reusable workflow. The paths input is gone. If the filter can't be read, the gate counts any changed file (fail open). One correction: bundle_size.yml did already list dependency-gate.yml in on.paths.
  • Root devDependencies not walked: folded into this PR. babel-plugin-module-resolver (required directly by babel.config.js) is now in BUILD_TOOLS. The script comment and ci-config.mdc say that new root build dependencies need adding there.
  • Gate job queue cost: keeping the gate as a separate job. Folding it into each main job would add an if: to every step, while the gate job is a checkout plus a ~1s script. The queue numbers will show whether it matters.

Generated by Claude Code

Vercel's Git integration already deploys every master push to
production (gated by vercel-ignore.sh), so site-release.yml deployed
the same site a second time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at 2201d6e. My CHANGE_THIS_PR from c7259f9 is resolved.

The gate now reads the caller's own on.<event>.paths through github.workflow_ref and yq, and the four hand-copied with.paths lists are gone, so there's one list per workflow. I checked the failure direction: if yq can't read the file, paths comes back empty, the script falls back to **, and any changed non-manifest file counts as relevant. That fails open, which is the right way round. The ${GITHUB_WORKFLOW_REF#*/*/} and ${workflow%@*} trims give .github/workflows/<caller>.yml for both the PR merge ref and master pushes, and every caller only triggers on pull_request or push, both of which have paths, so no event lands on a missing key. The ci-config.mdc line matches.

Adding babel-plugin-module-resolver to BUILD_TOOLS and saying in the script and the rule that root devDependencies aren't walked is enough for now. It's a hand-kept list, but it's short, documented in both places, and only changes when the root babel config gains a plugin.

The changes / check jobs are still queued on this SHA, so the first real run of the new path read hasn't happened yet. It's worth a look at one gate log (it prints its decision) before merge. Bugbot is still running. The benchmark push-group queue follow-up stays a FOLLOW_UP after merge, as agreed.

@codecov

codecov Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.10%. Comparing base (7954e6b) to head (292a67e).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4205   +/-   ##
=======================================
  Coverage   98.10%   98.10%           
=======================================
  Files         166      166           
  Lines        3167     3167           
  Branches      626      626           
=======================================
  Hits         3107     3107           
  Misses         18       18           
  Partials       42       42           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ntucker

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): CHANGE_THIS_PR at b948f67 (the new "Drop the GitHub Actions production docs deploy" commit). Everything up to 2201d6e stays LGTM. The direction here is right: Vercel's Git integration already makes a Production deployment for every master push (vercel[bot] made them for bf377f4, c26c1bb, a08706b and 7954e6b today), so the Actions run was a second deploy of the same commit. One thing gets lost with it, though.

Without site-release.yml, every page's "Last updated" date comes from a 10-commit shallow clone. The Actions job checked out with fetch-depth: 800. Vercel's Git build clones about 10 commits deep, and Docusaurus (showLastUpdateTime / showLastUpdateAuthor, through getVcsPreset('default-v1')) then dates every file that wasn't touched in those 10 commits to the oldest commit in the clone. You can see it on production right now, which is the Vercel Git build of 7954e6b (that commit's Actions deploy failed):

page last real change live "Last updated"
GraphQL intro (docs/graphql/README.md) 2026-07-12 (1a3d71a) 2026-10-05 18:46:51Z
useSuspense 2026-10-04 23:05Z (74a964e) 2026-10-05 18:46:51Z
Collection 2026-10-05 16:33Z (7a42afd) 2026-10-05 18:46:51Z

18:46:51Z is b492e0b, exactly 10 commits behind 7954e6b. Today that only shows up when the Vercel Git deploy finishes after the Actions one. After this commit it's every deploy, on every docs page, and nothing goes red.

Either of these fixes it:

  • Give Vercel's build real history (preferred, keeps one deploy). Deepen the clone before docusaurus build, fail open, for example a buildCommand in website/vercel.json or the site's build script running git fetch -q --no-tags --deepen=800 origin "$VERCEL_GIT_COMMIT_REF" || true first. Don't count on the deepen() in vercel-ignore.sh: it only runs when the previous production SHA isn't in the clone, and today's build shows it didn't run.
  • Or take this commit out of ci: Skip GitHub Actions runs PRs don't need; never cancel master runs #4205 and land the deploy cleanup separately together with that history fix.

I tried to argue myself out of this. The repo clearly wants these dates (showLastUpdateTime on four doc trees, plus custom VCS hooks so the Vue mirror pages get their source file's history), so the wrong dates aren't something nobody cares about. The fix is one fail-open line, not a new workflow. Bugbot and the rest of CI are still running on this SHA.

Without the Actions deploy (fetch-depth 800), Vercel's ~10 commit clone
dated every untouched page to the clone boundary.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Agreed and fixed in this PR (a90ce99), so there's still one deploy. I checked the mechanism: the removed workflow cloned 800 deep, Vercel clones about 10, and docs/graphql/README.md really was last changed 1a3d71a (2026-07-12). I couldn't reach the live site from here.

I didn't put it in a vercel.json buildCommand, because that replaces the dashboard's build command, which isn't in the repo and also builds the packages first. I didn't put it in the ignore step either, since git changes made there aren't documented to carry into the build. Instead docusaurus.config.ts calls website/scripts/deepenGitHistory.cjs, which runs inside the build itself whatever the build command is. It only acts when VERCEL is set and the clone is shallow, runs git fetch --no-tags --deepen=800 origin $VERCEL_GIT_COMMIT_REF, and fails open with a warning. I tested it on a --depth=10 clone: the GraphQL README's last commit went from the clone boundary to 2026-07-12. CI's site-preview build doesn't set VERCEL, so nothing changes there. After merge, the next production deploy's log should print "Deepened git history by 800 commits".


Generated by Claude Code

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at a90ce99. My CHANGE_THIS_PR from b948f67 (shallow Vercel clone breaking "Last updated" dates) is resolved, and the rest of the PR stays LGTM as of 2201d6e.

I tried to knock the fix down and it held up:

  • Ordering: deepenGitHistory() runs when docusaurus.config.ts is loaded, before any content plugin reads git dates, so the build sees the deeper history.
  • Scope: it only runs when VERCEL and VERCEL_GIT_COMMIT_REF are set and the repo is actually shallow. site-preview.yml sets VERCEL_ENV but not VERCEL, so the Actions build and local builds are untouched.
  • Failure direction: any error (no origin, a fork PR whose branch isn't on origin, network trouble, the 60s timeout) prints a warning and leaves the dates as they are today. That fails open, and the warning shows up in the Vercel build log.
  • --deepen vs --depth: --deepen=800 counts from the current shallow boundary, so it still works if the branch moved on after Vercel cloned.
  • Simpler alternative? A git fetch ... || true in a vercel.json buildCommand would be the other option, but it would replace Vercel's auto-detected build command and has no shallow check or timeout. Keeping it next to generateMonacoPreloads.cjs, which already runs from the config, is the more consistent choice. The ci-config.mdc line says where it lives.

Before merge, please check the Vercel preview for this SHA. The build log should show Deepened git history by 800 commits, and the GraphQL intro page (docs/graphql/README.md) should say last updated 2026-07-12, not today. Bugbot is still running on this SHA.

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Lead Engineer: Pre-merge check on tip a90ce992 (Staff asked to verify deepen before merge).

Motivation: Dropping site-release.yml leaves "Last updated" dates on Vercel’s shallow clone. deepenGitHistory.cjs is supposed to fetch 800 more commits so dates stay real.

Findings: The preview at https://docs-site-485y3ba7n-data-client.vercel.app/graphql shows Last updated on Oct 5, 2026 by Claude, not 2026-07-12 (the real last change to docs/graphql/README.md at 1a3d71af). That matches a still-shallow history (today’s ~10-commit window), so deepen did not affect this preview’s last-update dates.

I could not read the Vercel build log from here (login wall). Please confirm whether the log has Deepened git history by 800 commits for last-update dates or Could not deepen git history, and fix so GraphQL Usage shows 2026-07-12 on the preview before merge.

Do not merge until that holds.

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Lead Engineer: Follow-up on the pre-merge deepen check (after ruling out false positives):

  1. No PR commit touches the GraphQL intro. On claude/project-thread-94yvlu, docs/graphql/README.md last changed at 1a3d71af (2026-07-12, Nathaniel Tucker). The PR file list has zero graphql paths; master...a90ce992 does not change that file.
  2. Preview is tip a90ce992. GitHub deployment 6868935455 (Preview) has sha/ref = a90ce992621a87ffdeb1f0d09f3d634bb6096c99. Page: https://docs-site-485y3ba7n-data-client.vercel.app/graphql

So Last updated on Oct 5, 2026 by Claude is not explained by the PR editing that page or by an old deploy. It matches a still-shallow ~10-commit window. Deepen did not give this preview real last-update dates.

Vercel build log still unread here (login wall). Please fix so that page shows 2026-07-12 before merge.

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): CHANGE_THIS_PR at a90ce992. This replaces my earlier LGTM (#4205 (comment)).

The history deepen isn't having an effect on the Vercel preview. The preview's GraphQL intro shows Last updated on Oct 5, 2026 by Claude. The last real change to docs/graphql/README.md is 1a3d71af (2026-07-12, Nathaniel). The two simpler explanations are ruled out:

  • This PR doesn't touch any graphql docs.
  • That preview deployment was built from exactly a90ce992.

So Docusaurus is still seeing the shallow ~10-commit clone. Either the deepen didn't run, it failed and was swallowed, or it ran after the last-update data was collected.

Ask:

  1. Find out which of those it is. Make the deepen log its outcome either way: success with the new depth, or failure with git's stderr and exit code. A silent fallback is how this slipped through.
  2. Fix it so the fetch is guaranteed to finish before docusaurus build collects git data. If the config-load hook can't guarantee that order, run the fetch in the Vercel build command or the site build script instead, e.g. git fetch -q --no-tags --deepen=800 origin "$VERCEL_GIT_COMMIT_REF" || true before the build. That should be either a buildCommand in website/vercel.json or the site build script.
  3. Verify on the new preview that /graphql shows Jul 12, 2026.

Alternatively, take the "drop site-release.yml" commit out of this PR and land it later with a working history fix. Everything else stays LGTM. Please don't merge until the preview shows the right date.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for checking the preview. Agreed, the deepen didn't work there. I can't read the Vercel log either, but the likely cause is documented (vercel/vercel#5737): Vercel's clone has no origin remote, so git fetch … origin <ref> failed and the script failed open, as it was built to.

Fixed in 47a5f37. The script now fetches by URL, built from Vercel's VERCEL_GIT_REPO_OWNER/VERCEL_GIT_REPO_SLUG (the repo is public, so no auth is needed), and the warning now includes the git error so the log says why if it fails again. I tested it on a --depth=10 clone with the remote removed, fetching from GitHub: 810 commits afterwards, and docs/graphql/README.md dates to 2026-07-12.

Please recheck /graphql on this SHA's preview. If it still shows today, the fallback is Vercel's supported VERCEL_DEEP_CLONE=true project env var (dashboard only), and with it set the script does nothing. I'm keeping the merge hold until the preview shows 2026-07-12.


Generated by Claude Code

…derr

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162EbzKf3kYr427Qe51L2jN

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Answering the CHANGE_THIS_PR at a90ce99 (it crossed with my 47a5f37 comment above). Now at 292a67e:

  1. Which failure it was: the fetch failed and the error was swallowed. Vercel's clone has no origin remote (vercel/vercel#5737), so fetch … origin <ref> errored and the old code threw the reason away. 47a5f37 fetches by URL instead. 292a67e logs the outcome every time, prefixed deepenGitHistory:. You'll see one of history deepened from 10 to 810 commits, skipped, clone not shallow (N commits), skipped, Vercel git env missing, or FAILED … (exit 128): <git stderr>. I tested each case on a --depth=10 clone with no remote.
  2. Ordering: this is already guaranteed. Docusaurus loads docusaurus.config.ts before any plugin runs, and the execFileSync blocks until git finishes, so there was never an ordering problem. I didn't move it to a buildCommand: that replaces the dashboard's build command, and the suggested origin form has the same missing-remote problem.
  3. Verification: preview for 292a67e pending. If /graphql doesn't show Jul 12, 2026, the build log line now says why, and VERCEL_DEEP_CLONE=true in the Vercel project settings is the supported fallback. The merge hold stands until then.

Generated by Claude Code

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at 292a67e3. This resolves my CHANGE_THIS_PR at a90ce992 (#4205 (comment)).

  1. Cause and logging: fetching by URL fixes the missing origin remote, and every outcome now logs with a deepenGitHistory: prefix and git's stderr on failure. That covers the silent fallback.
  2. Ordering: agreed, I withdraw the buildCommand suggestion. deepenGitHistory() runs synchronously at the top of docusaurus.config.ts, before any docs plugin reads git, and my suggested origin form would have hit the same missing remote.
  3. Verified on this SHA's preview (GitHub deployment for 292a67e3, https://docs-site-re3uqtrvb-data-client.vercel.app): /graphql and /rest both show Last updated on Jul 12, 2026 by Nathaniel Tucker, so Docusaurus is seeing real history now.

No further asks. Merge stays with Nathaniel.

@ntucker
ntucker merged commit d9200af into master Oct 5, 2026
35 checks passed
@ntucker
ntucker deleted the claude/project-thread-94yvlu branch October 5, 2026 22:23

ntucker commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at 47a5f371. This clears my CHANGE_THIS_PR from a90ce992 (#4205 (comment)).

I checked this SHA's Vercel preview (https://docs-site-p31rr8dfw-data-client.vercel.app) myself:

  • /graphql now shows Last updated on Jul 12, 2026 by Nathaniel Tucker (2026-07-12T16:37:38Z), matching 1a3d71af.
  • Other pages get their own dates (/rest Jul 12, /docs/api/useSuspense Oct 4, /docs Oct 5), so the build is seeing real history, not a single clone boundary.

The fix is the right size. Fetching by URL from VERCEL_GIT_REPO_OWNER/VERCEL_GIT_REPO_SLUG needs no auth on a public repo, keeps the shallow check and timeout, and still fails open (fork PRs whose branch isn't on the base repo just warn).

FOLLOW_UP, non-blocking: because stdio ignores stderr, the warning's e.message first line is only Command failed: git fetch ... and doesn't include git's reason. Piping stderr and printing e.stderr would make the next failure self-explaining. Fine to leave for later.

Bugbot shows neutral on this SHA and a few Actions jobs show cancelled, so per the merge checklist that needs a recheck or an explicit waive before merging. No merge from me.

This branch was successfully deployed

1 active deployment
Preview — 292a67e3 Deployed Oct 5, 2026 by vercel[bot]
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.

2 participants