Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
724a40a
[fix][broker] Fix ownership-generation races in OwnershipCache remove…
Jul 16, 2026
c1211bc
Merge branch 'master' into fix/broker-ownership-cache-generation-race
Jul 27, 2026
bb4768d
[feat][pip] PIP-478: Asynchronous v5 client auth plugin interfaces an…
lhotari Aug 3, 2026
f61d66c
[improve][broker] PIP-486 (PR5): broker-side entry-bucket handoff for…
merlimat Aug 4, 2026
c61fc19
[feat][misc] PIP-478: dedicated pulsar-tls-factory-api and pulsar-htt…
lhotari Aug 4, 2026
534fd89
[improve][io] Replace Spring Framework with cron-utils in CronTrigger…
lhotari Aug 4, 2026
34c7c94
[fix][broker] Fix bucket delayed delivery counter and dedup consisten…
nodece Aug 4, 2026
2fbf416
[fix][admin] Avoid creating subscriptions when peeking messages if au…
void-ptr974 Aug 7, 2026
bab5c77
[feat][misc] PIP-478: default file-based TLS factory implementation (…
lhotari Aug 7, 2026
af54f64
[fix][misc] Remove unnecessary " {}" suffix from log lines when there…
lhotari Aug 7, 2026
17de556
[fix][txn] Fix X-Pulsar-txn-uncommitted header semantics and add X-Pu…
poorbarcode Aug 9, 2026
e2d706b
[fix][client] Make V5 async producer flush() await the caller's send …
lhotari Aug 10, 2026
cb90c12
[fix][sec] Upgrade Netty to 4.2.17 to address several CVEs and bugs (…
lhotari Aug 10, 2026
403aae6
[improve][misc] Upgrade Jetty to 12.1.12 (#26302)
lhotari Aug 10, 2026
a87e36d
[fix][ml] Skip contiguous deleted ranges during reads (#26299)
coderzc Aug 10, 2026
afa93b5
[cleanup][ml] Remove unused metadata quorum configuration fields (#26…
somiljain2006 Aug 10, 2026
9a5bed3
[fix][broker] Wait for in-flight snapshot creation when trimming orph…
lhotari Aug 11, 2026
a5e7937
[fix][test] Fix flaky TestReplicationWorker.testRepairedNotAdheringPl…
lhotari Aug 11, 2026
3412427
[improve][broker] Expose interface for the replicator in ManagedLedge…
zymap Aug 11, 2026
2babfbc
[Fix][broker]Get a fenced error when loading a topic that does not al…
poorbarcode Aug 12, 2026
86ff200
[improve][misc] Upgrade Conscrypt to 2.6.1 to add aarch64 native supp…
lhotari Aug 12, 2026
fd7eebb
[feat][client] PIP-478: asynchronous v5 client authentication and TLS…
lhotari Aug 12, 2026
416d9d7
[improve][misc] Upgrade Conscrypt to 2.6.2 to restore the native libr…
lhotari Aug 13, 2026
96dd35a
[fix][test] Fix flaky AuditorPeriodicCheckTest.testFailedWriteRecover…
lhotari Aug 13, 2026
ddd043b
[improve][broker][proxy] Add httpMaxResponseHeaderSize config (#26255)
geniusjoe Aug 13, 2026
75cc51e
[improve][client] PIP-478: drive the v5 authentication model natively…
lhotari Aug 13, 2026
e712ffe
[improve][ci] Gate CI in apache/pulsar on the pull request being read…
lhotari Aug 13, 2026
3061275
[fix][ml] Make inflight reads limiter work even if managed ledger cac…
poorbarcode Aug 14, 2026
be203ca
[fix][sec] Pin httpclient5 to 5.6.4 and httpcore5 to 5.4.3 (#26331)
lhotari Aug 14, 2026
307035b
[fix][sec] Bump log4j2 from 2.26.0 to 2.26.1 (#26329)
dependabot[bot] Aug 14, 2026
ab60681
[improve][build] Upgrade Gradle to 9.7.0 (#26332)
lhotari Aug 14, 2026
b0a2604
[improve][build] Upgrade Shadow plugin to 9.6.1 and merge service des…
lhotari Aug 14, 2026
1d8d471
[improve][client] PIP-478: Athenz and SASL v5 authentication plugins …
lhotari Aug 15, 2026
387e7c5
[improve][misc] PIP-478: remove the superseded PIP-337 TLS stack (#26…
lhotari Aug 15, 2026
3b176c3
[improve][build] Upgrade OpenTelemetry to 1.65.0, instrumentation to …
lhotari Aug 16, 2026
8810361
[fix][sec] Upgrade Jackson to 2.21.6 (#26338)
lhotari Aug 16, 2026
bcdbdaa
[fix][broker] Prevent Key_Shared out-of-order replay starvation at th…
Denovo1998 Aug 17, 2026
6629b4b
[improve][build] Upgrade Jersey to 3.1.12 (#26347)
lhotari Aug 18, 2026
bc660a8
[improve][build] Upgrade Apache Commons libraries (#26348)
lhotari Aug 18, 2026
ac2b2d2
[improve][build] Upgrade Gradle plugins and move to the io.github.ben…
lhotari Aug 18, 2026
6cfb191
[improve][test] Upgrade test libraries (#26351)
lhotari Aug 18, 2026
e332083
[improve][monitor] Upgrade Dropwizard Metrics to 4.2.39 and HdrHistog…
lhotari Aug 18, 2026
1d549c8
[improve][build] Upgrade Jakarta and servlet APIs within the Jakarta …
lhotari Aug 18, 2026
9a9f462
[improve][build] Upgrade gRPC to 1.83.1 and Protobuf to 4.35.1 (#26356)
lhotari Aug 18, 2026
ee1c18d
[improve][build] Upgrade data structure and compression libraries (#2…
lhotari Aug 18, 2026
e2ed9ca
[improve][build] Upgrade misc tooling, annotation and utility librari…
lhotari Aug 18, 2026
81722ee
[improve][build] Upgrade Gson to 2.14.0 and json-smart to 2.6.0 (#26355)
lhotari Aug 18, 2026
9f923a4
[improve][build] Upgrade OkHttp to 5.5.0 and Okio to 3.18.1 (#26352)
lhotari Aug 18, 2026
ae07c33
[fix][offload] Normalize offloader cache directory path (#26372)
coderzc Aug 18, 2026
b660d70
[fix][client] Apply no-memory-limit producer queue defaults at produc…
lhotari Aug 18, 2026
6fbb9d6
[improve][build] Upgrade networking and infrastructure client librari…
lhotari Aug 19, 2026
1db5b80
[improve][build] Upgrade BouncyCastle to 1.85 and BouncyCastle FIPS t…
lhotari Aug 19, 2026
81936d5
[improve][build] Set --enable-native-access=ALL-UNNAMED for test JVMs…
lhotari Aug 19, 2026
68aa11c
[fix][cli] Set --enable-native-access=ALL-UNNAMED for the CLI tools o…
lhotari Aug 19, 2026
bbc02f0
[fix][test] Fix OneWayReplicatorSchemaValidationEnforcedTest racing t…
lhotari Aug 19, 2026
99ae8ae
[improve][build] Upgrade async-http-client to 3.0.13 and netty-reacti…
lhotari Aug 19, 2026
3be684a
[fix][client] Divide the across-partitions budget only when it was se…
lhotari Aug 19, 2026
a25ae29
[fix][broker] Do not log an error when the tenant does not exist (#26…
codelipenghui Aug 20, 2026
20ef856
[fix][broker] Reject topic names with leading or trailing whitespace …
crossoverJie Aug 20, 2026
00a6bad
[improve][broker] Change partition metadata not-found log to warn (#2…
Technoboy- Aug 20, 2026
53b6f62
[improve][broker] Add reason label for topic_load_failed_total (#26264)
poorbarcode Aug 23, 2026
12b86b1
[fix][fn] Honour negativeAckRedeliveryDelayMs in the Go function runt…
david-streamlio Aug 24, 2026
ee4ee98
[improve][pip] PIP-492: Add pulsar_subscription_storage_backlog_age_s…
Technoboy- Aug 24, 2026
9890872
[improve][ci] Run the Python function instance tests in CI (#26399)
david-streamlio Aug 24, 2026
0897616
[fix][fn] Honour retainOrdering and retainKeyOrdering in the Go funct…
david-streamlio Aug 25, 2026
fcf1555
[improve][client] Avoid recomputing entry-bucket hashes (#26383)
3pacccccc Aug 25, 2026
01964dc
[improve][broker] Add pulsar_subscription_storage_backlog_age_seconds…
Technoboy- Aug 26, 2026
7d2a0bd
[fix][fn] Honour producerSpec batching configuration in the Python fu…
david-streamlio Aug 26, 2026
8a6f25b
[fix][fn] Honour producerSpec batching configuration in the Go functi…
david-streamlio Aug 26, 2026
4040eec
[fix][fn] Honour negativeAckRedeliveryDelayMs in the Python function …
david-streamlio Aug 26, 2026
ecf6dae
[fix][fn] Allow retainKeyOrdering on Go functions (#26421)
david-streamlio Aug 26, 2026
91226e4
[fix][sec] Upgrade avro to 1.12.2 (#24992)
lhotari Aug 26, 2026
a0f3995
[fix][offload] Cache and reuse entry offsets discovered while skippin…
omarkj Aug 27, 2026
3bf3ec2
[feat][broker] PIP-470: Close inactive topics without deleting their …
codelipenghui Aug 27, 2026
fd1cc62
[improve][misc] PIP-478: close out the migration follow-ups, add the …
lhotari Aug 27, 2026
71c4109
[fix][admin] PIP-478: off-load the admin's v4 credential and lend it …
lhotari Aug 27, 2026
7e9edb8
[fix][proxy] PIP-478: resolve the proxy's broker-client credential of…
lhotari Aug 27, 2026
0c37fd3
[fix][client] Fix incorrect topic in OTel spans for multi-topic consu…
void-ptr974 Aug 28, 2026
4ce0cd5
[fix][broker] Bound the topic deletion retries triggered by a replica…
lhotari Aug 28, 2026
7ca86fa
[fix][txn] Do not fail topic deletion when the aborted txn snapshot c…
lhotari Aug 28, 2026
5180dba
[fix][test] Fix flaky IsolatedBookieEnsemblePlacementPolicyTest by aw…
lhotari Aug 28, 2026
36ff86c
[improve][pip] PIP-445: Add Builder Methods to Create Message-based T…
namest504 Aug 28, 2026
367caff
[improve][client] Seed MessageCryptoBc from the BC-FIPS DRBG when tha…
david-streamlio Aug 28, 2026
10c6cf1
[improve][build] Upgrade Gradle to 9.7.1 (#26440)
lhotari Aug 31, 2026
41255fb
[fix][broker] Add missing bundle Prometheus metrics for extensible lo…
Dream95 Sep 1, 2026
19c69ee
[improve][build] Upgrade lightproto to 0.8.1 (#26445)
merlimat Sep 2, 2026
f3c7707
[improve][misc] PIP-472: Drop Jetty ee8 usage and adapt legacy javax.…
lhotari Sep 2, 2026
8ae58a1
[fix][sec] Bump google.golang.org/grpc from 1.82.1 to 1.83.1 in /puls…
dependabot[bot] Sep 2, 2026
5951b6d
[improve][test] Cover reverse equality for topic message IDs (#26449)
hiSandog Sep 2, 2026
c70039c
[fix][client] PIP-486: explicit unsubscribe for scalable consumers' c…
merlimat Sep 3, 2026
d4e8677
[fix][client] Fix incorrect topic in OTel spans for partitioned produ…
void-ptr974 Sep 3, 2026
94af75a
[improve][broker] PIP-486: rebucket rollover and the segments-vs-buck…
merlimat Sep 3, 2026
23fa956
[improve][build] Profile Pulsar tests with async-profiler from Gradle…
lhotari Sep 4, 2026
46182ff
[improve][broker] Avoid iterator allocation in BrokerInterceptors hot…
merlimat Sep 4, 2026
7010231
[improve][broker] Copy small entries into a flat buffer when prependi…
merlimat Sep 4, 2026
f41e620
[fix][cli] pulsar-perf: register subcommand classes with picocli inst…
lhotari Sep 4, 2026
ffd9b6a
[fix][cli] Apply PULSAR_MEM and PULSAR_GC in bin/pulsar-perf (#26465)
lhotari Sep 4, 2026
bc1785d
[improve][cli] pulsar-perf: cut latency histogram memory ~100x, fix r…
lhotari Sep 5, 2026
8207618
[improve][test] Make PulsarProfilingTest test Scalable Topics and adj…
lhotari Sep 5, 2026
67205b9
[improve][build] Allow building with Java 26 (#26461)
merlimat Sep 5, 2026
9ba61bd
[fix][ml] Track all pending read callbacks for timeouts (#26081)
Technoboy- Sep 7, 2026
dfe30a6
[fix][misc] Resolve void by name in Reflections.loadClass (#26478)
hiSandog Sep 7, 2026
31dea17
[improve][cli] Add v4-client subcommands to pulsar-perf and pulsar-cl…
lhotari Sep 8, 2026
ce60798
[improve][ml] Parse message metadata at entry cache insert time inste…
merlimat Sep 8, 2026
00d475f
[improve][ml] Back LongBitmap with the on-heap RoaringBitmap to fix a…
lhotari Sep 8, 2026
bef7b8f
[fix][broker] Fix NPE in ManagedLedgerInterceptorImpl when AppendInde…
lhotari Sep 8, 2026
b08c6f9
Merge branch 'master' into fix/broker-ownership-cache-generation-race
lhotari Sep 8, 2026
2166893
[fix][broker] Make the lock-expiry unload generation-aware and drain …
Sep 9, 2026
f39ab2b
[improve][test] Inject the ownership cache spy through a VisibleForTe…
Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
55 changes: 55 additions & 0 deletions .github/actions/check-pr-ready-to-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

name: check PR readiness for running CI
description: >
Fails the workflow when a pull request isn't ready for consuming the shared CI resources of the
apache/pulsar repository. Draft pull requests and stacked pull requests which aren't at the bottom
of the stack are expected to be tested in the contributor's own fork. The check is overridden by
adding the ready-to-test label to the pull request.
inputs:
github-token:
description: "Token used for reading the pull request state"
required: false
default: ${{ github.token }}
ready-to-test-label:
description: "Label which overrides the readiness check"
required: false
default: 'ready-to-test'
trunk-branches:
description: >
Comma separated glob patterns of the branches that are considered trunk branches. Used for
detecting stacked pull requests when the GitHub stack API isn't available.
required: false
default: 'master,branch-*,pulsar-*'
runs:
using: composite
steps:
- uses: actions/github-script@v8
env:
# github.action_path is passed in an environment variable since a relative require would be
# resolved against the github-script action's own directory instead of this action's directory
ACTION_PATH: ${{ github.action_path }}
READY_TO_TEST_LABEL: ${{ inputs.ready-to-test-label }}
TRUNK_BRANCHES: ${{ inputs.trunk-branches }}
with:
github-token: ${{ inputs.github-token }}
script: |
const checkPrReadyToTest = require(`${process.env.ACTION_PATH}/check-pr-ready-to-test.js`);
await checkPrReadyToTest({ github, context, core });
223 changes: 223 additions & 0 deletions .github/actions/check-pr-ready-to-test/check-pr-ready-to-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

const DEFAULT_READY_TO_TEST_LABEL = 'ready-to-test';
const DEFAULT_TRUNK_BRANCHES = 'master,branch-*,pulsar-*';

// GitHub stacked pull requests: https://docs.github.com/en/pull-requests/how-tos/stacked-pull-requests
// The entries 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 necessarily the entry at position 1.
const STACK_QUERY = `
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
stackEntry {
position
}
stack {
number
size
baseRefName
entries(first: 100) {
nodes {
position
pullRequest {
number
url
state
}
}
}
}
}
}
}`;

function parsePatterns(value) {
return (value || '').split(/[\s,]+/).filter(pattern => pattern.length > 0);
}

function matchesAnyPattern(branch, patterns) {
return patterns.some(pattern => {
const regex = new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`);
return regex.test(branch);
});
}

function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

/**
* Resolves the place of the pull request within a GitHub stack.
* The stack fields aren't available in all GitHub deployments, in that case `available` is false and
* the caller falls back to inspecting the base branch of the pull request.
*/
async function resolveStack({ github, core, owner, repo, number, baseRef }) {
let response;
try {
response = await github.graphql(STACK_QUERY, { owner, repo, number });
} catch (error) {
core.warning(`Couldn't resolve GitHub stack information for #${number}: ${error.message}`);
return { available: false };
}
const stack = response?.repository?.pullRequest?.stack;
if (!stack) {
return { available: true, inStack: false };
}
const entries = (stack.entries?.nodes || []).filter(entry => entry?.pullRequest);
const openEntries = entries.filter(entry => entry.pullRequest.state === 'OPEN');
const bottomEntry = openEntries.reduce(
(bottom, entry) => (bottom == null || entry.position < bottom.position ? entry : bottom), null);
const position = response.repository.pullRequest.stackEntry?.position;
// The pull request is at the bottom of the stack when every pull request below it has been merged
// or closed. When such a pull request is merged, GitHub retargets the one above it to the branch
// that was merged into, so targeting the trunk branch of the stack means the same thing. Either
// condition is enough: the retargeting and the stack entries aren't necessarily updated at once.
const isLowestOpen = position != null
? !entries.some(entry => entry.position < position && entry.pullRequest.state === 'OPEN')
: bottomEntry?.pullRequest?.number === number;
return {
available: true,
inStack: true,
isBottom: isLowestOpen || baseRef === stack.baseRefName,
position,
number: stack.number,
size: stack.size,
trunkBranch: stack.baseRefName,
bottomPullRequest: bottomEntry?.pullRequest
};
}

function renderSummary({ pullRequestUrl, blockers, label }) {
const steps = [
...blockers.map(blocker => blocker.remedy),
`Test the change in your own fork in the meantime. The full CI pipeline runs in a fork without `
+ `maintainer approval and GitHub Actions provides separate quota for it. See the `
+ `[Personal CI documentation](https://pulsar.apache.org/contribute/personal-ci/) for enabling `
+ `it: push the branch to your fork and let the CI run against the pull request opened in your `
+ `own fork. As the pull request author, you are responsible for following up on test failures. `
+ `Please report any flaky tests as new issues at https://github.com/apache/pulsar/issues after `
+ `checking that the flaky test isn't already reported.`,
`An Apache Pulsar committer can add the \`${label}\` label to ${pullRequestUrl} to run the CI in `
+ `apache/pulsar regardless of the checks above.`,
`This workflow doesn't restart on its own when the pull request is marked as ready for review, `
+ `when the \`${label}\` label is added or when the pull request below this one in a stack is `
+ `merged. Once the checks above are addressed, start a new run by pushing to the branch, by `
+ `adding a "/pulsarbot rerun" comment to the pull request, or by re-running the failed jobs in `
+ `the GitHub Actions UI.`
];
return `
## Pulsar CI didn't run for this pull request

The apache/pulsar CI based on GitHub Actions has constrained resources and quota which are shared by
all contributors, so CI in apache/pulsar is reserved for pull requests that are ready to be tested:
draft pull requests, and the pull requests of a stack above the bottom one, are expected to be tested
with [Personal CI](https://pulsar.apache.org/contribute/personal-ci/) in the contributor's own fork.

### Why this run was stopped

${blockers.map(blocker => `- ${blocker.reason}`).join('\n')}

### How to proceed

${steps.map((step, index) => `${index + 1}. ${step}`).join('\n')}

If you have any trouble you can get support in multiple ways:
* by sending email to the [dev mailing list](mailto:dev@pulsar.apache.org) ([subscribe](mailto:dev-subscribe@pulsar.apache.org))
* on the [#dev channel on Pulsar Slack](https://apache-pulsar.slack.com/channels/dev) ([join](https://pulsar.apache.org/community#section-discussions))
* in apache/pulsar [GitHub discussions Q&A](https://github.com/apache/pulsar/discussions/categories/q-a)
`;
}

module.exports = async ({ github, context, core }) => {
const eventPullRequest = context.payload.pull_request;
if (!eventPullRequest) {
core.info(`The '${context.eventName}' event isn't a pull request event, skipping the check.`);
return;
}
const { owner, repo } = context.repo;
const number = eventPullRequest.number;
const label = process.env.READY_TO_TEST_LABEL || DEFAULT_READY_TO_TEST_LABEL;
const trunkBranches = parsePatterns(process.env.TRUNK_BRANCHES || DEFAULT_TRUNK_BRANCHES);

// The event payload is a snapshot of the pull request from the time the workflow run was triggered.
// Refresh the state so that re-running the workflow picks up changes made after that, such as
// adding the label or marking the pull request as ready for review.
const { data: pullRequest } = await github.rest.pulls.get({ owner, repo, pull_number: number });

if ((pullRequest.labels || []).some(prLabel => prLabel.name === label)) {
core.info(`Found the '${label}' label on #${number}.`);
return;
}
core.info(`There is no '${label}' label on #${number}.`);

// Each blocker explains why the CI didn't run and what to do about it. The remedies are rendered as
// the first steps of the instructions so that they match the checks which actually failed.
const stackRemedy = 'Wait for this pull request to reach the bottom of the stack: once the pull '
+ 'requests below it have been merged or closed, it becomes the lowest open pull request of the '
+ 'stack and its CI runs in apache/pulsar.';
const blockers = [];
if (pullRequest.draft) {
blockers.push({
reason: 'The pull request is a **draft**, so it isn\'t ready to be reviewed and tested yet.',
remedy: 'Mark the pull request as ready for review once it is ready to be tested and reviewed.'
});
}

const stack = await resolveStack({ github, core, owner, repo, number, baseRef: pullRequest.base.ref });
if (stack.available && stack.inStack) {
const positionText = stack.position != null
? `entry ${stack.position} of ${stack.size} in stack #${stack.number}`
: `part of stack #${stack.number}`;
core.info(`#${number} is ${positionText}. At the bottom of the stack: ${stack.isBottom}.`);
if (!stack.isBottom) {
const bottom = stack.bottomPullRequest;
const bottomLink = bottom ? ` ([#${bottom.number}](${bottom.url}))` : '';
blockers.push({
reason: `The pull request is ${positionText}. Only the pull request at the bottom of the `
+ `stack, that is the lowest one which hasn't been merged or closed yet${bottomLink}, runs `
+ `the CI in apache/pulsar.`,
remedy: stackRemedy
});
}
} else if (!matchesAnyPattern(pullRequest.base.ref, trunkBranches)) {
// Not resolved as a GitHub stack: a pull request that targets a branch which isn't a trunk branch
// is a dependent pull request stacked on top of another one.
core.info(`#${number} targets the '${pullRequest.base.ref}' branch which isn't a trunk branch.`);
blockers.push({
reason: `The pull request targets the \`${pullRequest.base.ref}\` branch instead of a trunk `
+ `branch (${trunkBranches.map(pattern => `\`${pattern}\``).join(', ')}), so it is stacked on `
+ `top of another pull request. Only the pull request at the bottom of a stack runs the CI in `
+ `apache/pulsar.`,
remedy: stackRemedy
});
}

if (blockers.length === 0) {
core.info(`#${number} is ready for running the CI.`);
return;
}

await core.summary
.addRaw(renderSummary({ pullRequestUrl: eventPullRequest.html_url, blockers, label }))
.write();
core.setFailed(`#${number} isn't ready for running the CI in ${owner}/${repo}. `
+ `See the job summary for instructions on how to proceed.`);
};
4 changes: 4 additions & 0 deletions .github/workflows/ci-go-functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ jobs:
echo docs_only=false >> $GITHUB_OUTPUT
fi

- name: Check if the PR is ready for running CI
if: ${{ steps.check_changes.outputs.docs_only != 'true' && github.repository == 'apache/pulsar' && github.event_name == 'pull_request' }}
uses: ./.github/actions/check-pr-ready-to-test

check-style:
needs: preconditions
if: ${{ needs.preconditions.outputs.docs_only != 'true' }}
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/ci-python-functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

name: CI - Python Functions
on:
pull_request:
branches:
- master
paths:
- '.github/workflows/**'
- 'pulsar-functions/instance/src/main/python/**'
- 'pulsar-functions/instance/src/test/python/**'
- 'pulsar-functions/instance/src/scripts/**'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
preconditions:
name: Preconditions
runs-on: ubuntu-24.04
outputs:
docs_only: ${{ steps.check_changes.outputs.docs_only }}
steps:
- name: checkout
uses: actions/checkout@v6

- name: Detect changed files
id: changes
uses: apache/pulsar-test-infra/paths-filter@master
with:
filters: .github/changes-filter.yaml
list-files: csv

- name: Check changed files
id: check_changes
run: |
if [[ "${GITHUB_EVENT_NAME}" != "schedule" ]]; then
echo "docs_only=${{ fromJSON(steps.changes.outputs.all_count) == fromJSON(steps.changes.outputs.docs_count) && fromJSON(steps.changes.outputs.docs_count) > 0 }}" >> $GITHUB_OUTPUT
else
echo docs_only=false >> $GITHUB_OUTPUT
fi

- name: Check if the PR is ready for running CI
if: ${{ steps.check_changes.outputs.docs_only != 'true' && github.repository == 'apache/pulsar' && github.event_name == 'pull_request' }}
uses: ./.github/actions/check-pr-ready-to-test

instance-tests:
needs: preconditions
if: ${{ needs.preconditions.outputs.docs_only != 'true' }}
name: Python ${{ matrix.python-version }} Functions instance tests
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
python-version: ['3.12', '3.13']

steps:
- name: checkout
uses: actions/checkout@v6

- name: Tune Runner VM
uses: ./.github/actions/tune-runner-vm

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Run Python instance tests
run: |
./pulsar-functions/instance/src/scripts/run_python_instance_tests.sh
Loading
Loading