Skip to content

CI: nine hosted workflows feed the changed-files detector a stale pull_request.base.sha #4818

Description

@justin808

Summary

Nine hosted CI workflows feed script/ci-changes-detector the same stale base SHA that caused #4756. The fix for that issue is scoped to .github/workflows/ci-required.yml only, so the same misrouting is still latent everywhere else.

Mechanism

For pull_request events actions/checkout resolves refs/pull/<n>/merge, so HEAD is the PR head merged into the current base tip.

github.event.pull_request.base.sha is a different commit: it only refreshes when the PR is opened or synchronized. On a branch that has not been pushed for a while, it lags HEAD's own base parent. Diffing from it folds every base-branch commit in between into the changed-file set, so the detector routes suites for changes the PR never made.

This is not a shallow-clone or fetch-depth problem. The merge base is resolved correctly; the input is wrong. It reproduces on a full, unshallow clone.

Evidence from #4756 (PR #4739, a one-file docs-only change):

Affected workflows

Each of these invokes script/ci-changes-detector "$BASE_REF" where BASE_REF falls back to github.event.pull_request.base.sha:

  • .github/workflows/lint-js-and-ruby.yml:89
  • .github/workflows/package-js-tests.yml:90
  • .github/workflows/gem-tests.yml:101
  • .github/workflows/integration-tests.yml:96
  • .github/workflows/precompile-check.yml:81
  • .github/workflows/examples.yml:97
  • .github/workflows/playwright.yml:87
  • .github/workflows/pro-integration-tests.yml:94
  • .github/workflows/pro-test-package-and-gem.yml:92

Secondary, lower severity (same stale base, but they gate on a changed-file diff rather than suite routing):

  • .github/workflows/check-docs-sidebar.yml:39
  • .github/workflows/check-llms-full.yml:62
  • .github/workflows/actionlint.yml:32

.github/workflows/bundle-size.yml is already correct and is the precedent to copy.

Severity

Lower than #4756. These workflows only run once hosted CI is enabled, and a stale base widens the diff, so the failure mode is over-selecting suites (wasted hosted runner minutes on a stale branch) rather than skipping a suite that was needed. There is no known case of it hiding a required check.

Remedy

Take the base from the merge commit's first parent, which is the exact commit the merge was computed against, and which is always present locally because it is a parent of HEAD.

.github/workflows/bundle-size.yml:82-99 already does this and documents the same reasoning. .github/workflows/ci-required.yml adopts it in the fix for #4756.

Guard it on HEAD having exactly two parents. A single-parent HEAD on a pull_request event is reachable (GitHub produces no merge ref for a PR that conflicts with its base), and there HEAD^1 is the PR's own previous commit, not the base. Taking it would be silently wrong.

Because the shared shape is repeated across nine files, consider extracting the resolution into a small composite action or a helper in script/lib/ rather than pasting it nine times.

Notes

  • No changelog entry: CI plumbing is not user-visible per the CHANGELOG.md seam.
  • Semantic .github/workflows/** changes require a linked Follow-up: Exercise GitHub Actions changes from PR #NNNN issue before merge (see .github/read-me.md).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions