Skip to content

[improve][ci] Gate CI in apache/pulsar on the pull request being ready for testing - #26323

Merged
lhotari merged 2 commits into
apache:masterfrom
lhotari:lh-improve-ci-ready-to-test-gate
Aug 13, 2026
Merged

[improve][ci] Gate CI in apache/pulsar on the pull request being ready for testing#26323
lhotari merged 2 commits into
apache:masterfrom
lhotari:lh-improve-ci-ready-to-test-gate

Conversation

@lhotari

@lhotari lhotari commented Aug 13, 2026

Copy link
Copy Markdown
Member

Motivation

The ready-to-test enforcement was removed in #25470, so every pull request opened against
apache/pulsar consumes the shared CI quota, including the ones that aren't ready to be reviewed and
tested yet.

Two cases are wasteful in particular:

  • Draft pull requests, which are work in progress by definition.
  • Stacked pull requests.
    A stacked pull request targets the branch of the pull request below it instead of a trunk branch,
    and it isn't filtered out by the branches: filter of the workflow triggers: all layers of a stack
    currently run the full CI pipeline in apache/pulsar although only the bottom one is mergeable. The
    changes of the layers below are also included in every upper layer, so the same code is tested
    repeatedly.

Both cases are covered by Personal CI, which
runs the full pipeline in the contributor's own fork with a separate quota.

Modifications

Add a check-pr-ready-to-test composite action which fails the preconditions job of a workflow
when a pull request isn't ready for consuming the CI resources of apache/pulsar. The action is used
by the Pulsar CI, Pulsar CI Flaky and CI - Go Functions workflows, and failing it skips all of
the jobs which depend on preconditions.

The ready-to-test label passes the check immediately. Otherwise the check fails when

  • the pull request is a draft, or
  • the pull request is part of a GitHub stack and isn't the bottom one. This is resolved with the
    stackEntry/stack GraphQL fields of a pull request.

The entries of a stack keep their position when a pull request of the stack is merged, so the bottom
of the stack is the lowest entry which is still open, not the entry at position 1. For example,
after #26317 was merged, #26319 is the bottom one although it remains entry 2 of stack #26321. A pull
request which targets the trunk branch of the stack is accepted as well, since GitHub retargets a
pull request when the one below it is merged; either condition is enough, because the retargeting and
the stack entries aren't necessarily updated at the same time.

When the stack fields aren't available, a pull request that targets a branch which isn't a trunk
branch is treated as a stacked pull request.

The state of the pull request is read from the API instead of the event payload so that re-running
the workflow picks up a label or a draft state which was changed after the run was triggered. A
failing check writes instructions for proceeding to the job summary, including a reference to the
Personal CI documentation.

The check is limited to pull_request events in the apache/pulsar repository, so it never interferes
with running the CI in a fork. Documentation-only pull requests are exempt, since they don't run the
test jobs in the first place.

Compared with the check that was removed in #25470, the "pull request has been approved" bypass is
not restored: only the ready-to-test label overrides the check.

Verifying this change

  • Make sure that the change passes the CI checks.

This change is a CI-only change without test coverage in the repository. It was verified as follows:

Does this pull request potentially affect one of the following parts:

If the box was checked, please highlight the changes

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

…y for testing

### Motivation

The `ready-to-test` enforcement was removed in apache#25470, so every pull request opened
against apache/pulsar consumes the shared CI quota, including the ones that aren't
ready to be reviewed and tested yet.

Two cases are wasteful in particular:

- Draft pull requests, which are work in progress by definition.
- Stacked pull requests (https://docs.github.com/en/pull-requests/how-tos/stacked-pull-requests).
  A stacked pull request targets the branch of the pull request below it instead of a
  trunk branch, and it isn't filtered out by the `branches:` filter of the workflow
  triggers: all layers of a stack currently run the full CI pipeline in apache/pulsar
  although only the bottom one is mergeable. The changes of the layers below are also
  included in every upper layer, so the same code is tested repeatedly.

Both cases are covered by Personal CI (https://pulsar.apache.org/contribute/personal-ci/),
which runs the full pipeline in the contributor's own fork with a separate quota.

### Modifications

Add a `check-pr-ready-to-test` composite action which fails the `preconditions` job of
a workflow when a pull request isn't ready for consuming the CI resources of
apache/pulsar. The action is used by the `Pulsar CI`, `Pulsar CI Flaky` and
`CI - Go Functions` workflows, and failing it skips all of the jobs which depend on
`preconditions`.

The `ready-to-test` label passes the check immediately. Otherwise the check fails when

- the pull request is a draft, or
- the pull request is part of a GitHub stack and isn't the bottom one, which is
  resolved with the `stackEntry`/`stack` GraphQL fields of a pull request. When the
  stack fields aren't available, a pull request that targets a branch which isn't a
  trunk branch is treated as a stacked pull request.

The state of the pull request is read from the API instead of the event payload so
that re-running the workflow picks up a label or a review state which was changed
after the run was triggered. A failing check writes instructions for proceeding to
the job summary.

The check is limited to `pull_request` events in the apache/pulsar repository, so it
never interferes with running the CI in a fork.

Assisted-by: Claude Code (Opus 5)
The entries of a GitHub stack keep their position when a pull request of the
stack is merged: after apache#26317 was merged, apache#26319 still reports position 2 of
stack #26321. Requiring position 1 therefore kept the CI blocked for a pull
request which had already become the bottom one.

Resolve the bottom of the stack as the lowest entry which is still open, and
accept a pull request which targets the trunk branch of the stack as well,
since GitHub retargets a pull request when the one below it is merged. Either
condition is enough because the retargeting and the stack entries aren't
necessarily updated at the same time.

Assisted-by: Claude Code (Opus 5)
@lhotari
lhotari merged commit e712ffe into apache:master Aug 13, 2026
83 of 85 checks passed
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