Skip to content
Merged

Dev #368

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup Java JDK
uses: actions/setup-java@v2.3.1
uses: actions/setup-java@v4
with:
java-version: 11
distribution: 'adopt'
java-version: 17
distribution: 'temurin'

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -57,17 +57,17 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@v2
# uses: github/codeql-action/autobuild@v3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

- name: Build with Maven
run: mvn -DskipTests=true -V -ntp install

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
4 changes: 2 additions & 2 deletions .github/workflows/jenkins-security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ permissions:

jobs:
security-scan:
uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2.2.1
with:
java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
# java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default.
java-version: 17 # Specify Java 17 to match the project requirements
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ node_modules/*
/.sts4-cache/
.checkstyle
.aider*
.claude
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Change Log

## 3.3.0 (2025-11-24)

### What's Changed

**New Features:**
* **Draft Pull Request Support** - Add ability to detect if a Pull Request is Draft (Bitbucket Cloud only) by @nazzer23 in https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin/pull/367
- New environment variable: `BITBUCKET_PULL_REQUEST_IS_DRAFT`
- Returns `"true"` or `"false"` (defaults to `false` if not provided by Bitbucket)
- Allows filtering/skipping builds for draft PRs in pipeline scripts

**Internal Improvements:**
* Migrate tests from JUnit4 to JUnit5 by @strangelookingnerd in https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin/pull/369
* Fix build issue in pom.xml by @s78258819-svg in https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin/pull/371

### Compatibility
* Jenkins version: >= **2.440.3** (unchanged)
* Java version: **17**

### New Contributors
* @nazzer23 made their first contribution in https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin/pull/367

**Full Changelog**: https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin/compare/bitbucket-push-and-pull-request-3.1.4...bitbucket-push-and-pull-request-3.3.0

## 3.1.4 (2024-10-29)

### Closed Issues
Expand Down
10 changes: 7 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/*
See the documentation for more options:
https://github.com/jenkins-infra/pipeline-library/
*/
buildPlugin(
forkCount: '1C', // run this number of tests in parallel for faster feedback. If the number terminates with a 'C', the value will be multiplied by the number of available CPU cores
useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
configurations: [
[platform: 'linux', jdk: 17],
[platform: 'linux', jdk: 21],
[platform: 'windows', jdk: 17],
])

])
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Talking generally, there are two filters used to 'control the branches':
| BITBUCKET_PULL_REQUEST_COMMENT_TEXT | Comment of BB Cloud Pull Request | PR | C + S | |
| BITBUCKET_PULL_REQUEST_LATEST_COMMIT_FROM_SOURCE_BRANCH | Latest commit hash on the source branch | PR | C + S | |
| BITBUCKET_PULL_REQUEST_LATEST_COMMIT_FROM_TARGET_BRANCH | Latest commit hash on the target branch | PR | C + S | |
| BITBUCKET_PULL_REQUEST_IS_DRAFT | "true" if PR is draft, "false" otherwise| PR | C | Since 3.3.0 |
| BITBUCKET_REPOSITORY_UUID | Repository identifier | P | C | |
| BITBUCKET_REPOSITORY_ID | Repository identifier | P | S | |
| BITBUCKET_REPOSITORY_URL | Repository URL | PR | C | |
Expand Down Expand Up @@ -1214,6 +1215,7 @@ pipeline {
echo "BITBUCKET_TARGET_BRANCH ${env.BITBUCKET_TARGET_BRANCH}"
echo "BITBUCKET_PULL_REQUEST_LINK ${env.BITBUCKET_PULL_REQUEST_LINK}"
echo "BITBUCKET_PULL_REQUEST_ID ${env.BITBUCKET_PULL_REQUEST_ID}"
echo "BITBUCKET_PULL_REQUEST_IS_DRAFT ${env.BITBUCKET_PULL_REQUEST_IS_DRAFT}"
echo "BITBUCKET_PAYLOAD ${env.BITBUCKET_PAYLOAD}"

echo 'Env vars for cloud push...'
Expand All @@ -1235,6 +1237,76 @@ pipeline {
}
```

## Example: Skip builds for draft pull requests (Bitbucket Cloud)

Since version 3.3.0, you can detect and skip builds for draft pull requests using the `BITBUCKET_PULL_REQUEST_IS_DRAFT` environment variable:

```groovy
pipeline {
agent any

stages {
stage('Check if Draft') {
when {
environment name: 'BITBUCKET_PULL_REQUEST_IS_DRAFT', value: 'true'
}
steps {
echo 'Skipping build for draft PR'
script {
currentBuild.result = 'NOT_BUILT'
error('Draft PRs are not built')
}
}
}

stage('Build') {
when {
environment name: 'BITBUCKET_PULL_REQUEST_IS_DRAFT', value: 'false'
}
steps {
echo 'Building non-draft PR...'
// Your build steps here
}
}

stage('Test') {
when {
environment name: 'BITBUCKET_PULL_REQUEST_IS_DRAFT', value: 'false'
}
steps {
echo 'Running tests...'
// Your test steps here
}
}
}
}
```

Or simply skip the entire pipeline at the beginning:

```groovy
pipeline {
agent any

stages {
stage('Build') {
steps {
script {
if (env.BITBUCKET_PULL_REQUEST_IS_DRAFT == 'true') {
echo 'Skipping build for draft PR'
currentBuild.result = 'NOT_BUILT'
return
}

echo 'Building...'
// Your build steps here
}
}
}
}
}
```

# Thanks and Acknowledgments

This plugin is originally based on the Sazo's fork (<https://github.com/sazo/bitbucket-plugin>)
Expand Down
15 changes: 3 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
<jenkins.baseline>2.440</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
<powermock.version>2.0.0</powermock.version>
<hpi.compatibleSinceVersion>2.9.0</hpi.compatibleSinceVersion>
<jenkins.java.level>17</jenkins.java.level>
</properties>

<name>Bitbucket Push and Pull Request Plugin</name>
<description>Bitbucket plugin for Jenkins v2.138.2 or later, allowing push and pull requests</description>
<description>Bitbucket plugin for Jenkins allowing push and pull requests</description>

<licenses>
<license>
Expand Down Expand Up @@ -192,13 +191,6 @@
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>

</dependencies>

<url>https://github.com/jenkinsci/bitbucket-push-and-pull-request-plugin</url>
Expand All @@ -213,13 +205,13 @@
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins.io/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins.io/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>

Expand All @@ -243,5 +235,4 @@
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
import org.eclipse.jgit.transport.URIish;

/**
*
*
* @author cdelmonte
*
*/
Expand Down Expand Up @@ -92,7 +92,7 @@
List<URIish> remoteScmUrls = bitbucketAction.getScmUrls().stream().map(makeUrl)
.filter(Objects::nonNull).collect(Collectors.toList());

try (ACLContext ctx = ACL.as(ACL.SYSTEM)) {
try (ACLContext ctx = ACL.as2(ACL.SYSTEM2)) {
if (globalConfig.isSingleJobSet()) {
try {
Job job = (Job) Jenkins.get().getItemByFullName(globalConfig.getSingleJob());
Expand Down Expand Up @@ -159,82 +159,80 @@
return;
}

Predicate<URIish> checkSCM = (url) -> scm instanceof GitSCM && matchGitScm(scm, url);
Predicate<URIish> checkSCM = url -> scm instanceof GitSCM && matchGitScm(scm, url);

if (remotes.stream().anyMatch(checkSCM) && !scmTriggered.contains(scm)) {
scmTriggered.add(scm);

try {
jobTrigger.bitbucketTrigger.onPost(bitbucketEvent, bitbucketAction, scm, observable);
return;

} catch (Exception e) {
logger.log(Level.WARNING, "Error: {0}", e.getMessage());
}
}

logger.log(Level.FINE, "{0} SCM doesn't match remote repo {1} or it was already triggered.",
new Object[] { job.getName(), remotes.stream().map(URIish::toString).collect(Collectors.joining(", ")) });

}));
}

private static class Trigger {
public final BitBucketPPRTrigger bitbucketTrigger;
final Optional<SCMTriggerItem> scmTriggerItem;

public Trigger(BitBucketPPRTrigger bitbucketTrigger, Optional<SCMTriggerItem> item) {
this.bitbucketTrigger = bitbucketTrigger;
this.scmTriggerItem = item;
}
}

private boolean mPJobShouldNotBeTriggered(Job<?, ?> job, BitBucketPPRHookEvent bitbucketEvent,
BitBucketPPRAction bitbucketAction) {

if (job.getDisplayName() != null) {
String displayName = job.getDisplayName();
String sourceBranchName = bitbucketAction.getSourceBranch();
String targetBranchName = bitbucketAction.getTargetBranch();

logger.log(Level.FINEST,
"Bitbucket event is : {0}, Job Name : {1}, sourceBranchName: {2}, targetBranchName: {3}",
new String[] {
bitbucketEvent.getAction(), displayName, sourceBranchName,
targetBranchName });

if (PULL_REQUEST_MERGED.equalsIgnoreCase(bitbucketEvent.getAction())) {
return !displayName.equalsIgnoreCase(targetBranchName);
}

if (PULL_REQUEST_SERVER_MERGED.equalsIgnoreCase(bitbucketEvent.getAction())) {
return !displayName.equalsIgnoreCase(targetBranchName);
}

if (sourceBranchName != null) {
return !displayName.equalsIgnoreCase(sourceBranchName);
}

if (REPOSITORY_CLOUD_PUSH.equalsIgnoreCase(bitbucketEvent.getAction())
&& targetBranchName != null) {
return !displayName.equals(targetBranchName);
}

if (REPOSITORY_SERVER_PUSH.equalsIgnoreCase(bitbucketEvent.getAction())
&& targetBranchName != null) {
return !displayName.equals(targetBranchName);
}
}

return true;
}

private Optional<BitBucketPPRTrigger> getBitBucketTrigger(Job<?, ?> job) {
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
ParameterizedJobMixIn.ParameterizedJob<?, ?> pJob =
(ParameterizedJobMixIn.ParameterizedJob<?, ?>) job;
if (job instanceof ParameterizedJobMixIn.ParameterizedJob<?, ?> pJob) {

Check warning on line 233 in src/main/java/io/jenkins/plugins/bitbucketpushandpullrequest/BitBucketPPRJobProbe.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 162-233 are not covered by tests

return pJob.getTriggers().values().stream().filter(BitBucketPPRTrigger.class::isInstance)
return pJob.getTriggers().values().stream().filter(BitBucketPPRTrigger.class::isInstance)
.findFirst().map(BitBucketPPRTrigger.class::cast);
}
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/*******************************************************************************
* The MIT License
*
*
* Copyright (C) 2018, CloudBees, Inc.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Expand All @@ -26,7 +26,7 @@


public interface BitBucketPPRPollResultListener {
public void onPollSuccess(PollingResult pollingResult);
void onPollSuccess(PollingResult pollingResult);

public void onPollError(Throwable throwable);
void onPollError(Throwable throwable);
}
Loading
Loading