Skip to content
Merged
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
38 changes: 7 additions & 31 deletions docs/USER_GUIDE.adoc
Original file line number Diff line number Diff line change
@@ -1,37 +1,13 @@
= Bitbucket Branch Source Plugin

[IMPORTANT]
=====================================================================
On March 5th, 2020, link:https://confluence.atlassian.com/bitbucketserver/bitbucket-server-7-0-release-notes-990546638.html[Atlassian releases Bitbucket Server 7]
which removed some undocumented features related to pull requests.

. With Bitbucket Server 7.x, Jenkins Pipeline jobs can no longer perform a lightweight checkout of the `Jenkinsfile` if you are using the merge strategy for builds.
.. This is due to Bitbucket Server 7.x no longer storing the merge commit for PRs to `refs/pull-requests/*/merge` which was a prerequisite for lightweight checkout.
.. Bitbucket Server Pipeline jobs will automatically fall back to heavyweight checkout.
.. link:https://jira.atlassian.com/browse/BSERV-12284?focusedCommentId=2389584&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-2389584[Atlassian
has explained their reasons for making this change] and has made it clear they will not be re-adding this behavior.
. For Jenkins Pipeline jobs to function for pull requests on Bitbucket Data Center 8.x and above, you need to enable "Call Changes api" option in the plugin configuration.
.. Since Bitbucket Server 7.x no longer automatically creates the required refs for pull requests. Calls to this new API are required to trigger ref creation.

=====================================================================

[id=bitbucket-sect-intro]

_Bitbucket Branch Source plugin_ allows use of Bitbucket Cloud and Data Center
as a multi-branch project source in two different ways:
_Bitbucket Branch Source plugin_ allows use of Bitbucket Cloud and Data Center as a multi-branch project source in two different ways:

* *Single repository source*: automatic creation of jobs for branches and pull requests in a specific repository.
* *Organization folders*: automatic creation of multi-branch projects for each visible repository in a specific Bitbucket Team or Project.

IMPORTANT: This plugin officially supports versions of Bitbucket Data Center not declared in link:https://confluence.atlassian.com/support/atlassian-end-of-support-policy-201851003.html[End Of Support (EOS)].

[id=bitbucket-data_center]
== Bitbucket Data Center compatibility

_Bitbucket Data Center_ is supported but does no longer support lightweight checkout for pull requests when merge strategy is used for build.

IMPORTANT: In order to have the pull request process working the "Call Changes api" option must be
enabled in _Manage Jenkins_ » _Configure System_
IMPORTANT: Since version 937.0.0 this plugin officially supports *only* versions of Bitbucket Data Center *not* declared as in link:https://confluence.atlassian.com/support/atlassian-end-of-support-policy-201851003.html[End Of Support (EOS)].

[id=bitbucket-scm-source]
== Branches and pull requests auto-discovering
Expand Down Expand Up @@ -105,7 +81,7 @@ The default Bitbucket avatar is a generated SVG image, since this plugin does no
[id=bitbucket-webhooks]
== Webhooks registering

The use of https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html[Bitbucket webhooks]
The use of link:https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html[Bitbucket webhooks]
allows to trigger builds on branches and pull requests just when a new commit is done. Bitbucket plugin exposes a special
service to listen to these webhook requests and acts accordingly by triggering a new reindex and finally
triggering builds on matching branches or pull requests.
Expand All @@ -115,11 +91,11 @@ check "Manage hooks" and select a "Credential" with enough access to add webhook
it can be a System scoped credential, which will restrict its usage from Pipelines.
You can setup a custom Jenkins URL to be used as callback URL by the webhooks.

For Bitbucket Data Center only it is possible chose which webhooks implementation server side to use:
For Bitbucket Data Center only, it is possible chose which webhooks implementation server side to use:

- Native implementation will configure the webhooks provided by default with the Server, so it will always be available.

- Plugin implementation (*deprecated*) relies on the configuration available via specific APIs provided by the https://marketplace.atlassian.com/apps/1215474/post-webhooks-for-bitbucket?tab=overview&hosting=datacenter[Post Webhooks for Bitbucket] plugin itself. To get it worked plugin must be already pre-installed on the server instance. This provider allows custom settings managed by the _ignore committers_ trait. _Note: This specific implementation will be moved to an individual repository as soon as https://issues.jenkins.io/browse/JENKINS-74913[JENKINS-74913] is implemented._
- Plugin implementation (*deprecated*) relies on the configuration available via specific APIs provided by the link:https://marketplace.atlassian.com/apps/1215474/post-webhooks-for-bitbucket?tab=overview&hosting=datacenter[Post Webhooks for Bitbucket] plugin itself. To get it worked plugin must be already pre-installed on the server instance. This provider allows custom settings managed by the _ignore committers_ trait. _Note: This specific implementation will be moved to an individual repository as soon as link:https://issues.jenkins.io/browse/JENKINS-74913[JENKINS-74913] is implemented._

image::images/screenshot-14.png[]

Expand All @@ -129,7 +105,7 @@ to opt out or adjust system-wide settings.
image::images/screenshot-18.png[]

IMPORTANT: In order to have the auto-registering process working fine the Jenkins base URL must be
properly configured in _Manage Jenkins_ » _System_
properly configured in _Manage Jenkins_ » _System_, in alternative the URL must be provided in the endpoint configuration.

=== Signature verification for incoming webhooks

Expand Down Expand Up @@ -237,7 +213,7 @@ image::images/screenshot-12.png[]
[id=bitbucket-mirror-support]
== Mirror support

A mirrored Git repository can be configured for fetching references.
A mirrored Git repository can be configured for fetching references. This feature is available only on Bitbucke Data Center.

The mirror is not used in the following cases:

Expand Down
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@
<artifactId>scribejava-core</artifactId>
<version>8.3.3</version>
</dependency>
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down Expand Up @@ -169,11 +174,6 @@
<artifactId>workflow-multibranch</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public XmlFile getConfigFile() {
XStream2 xs = new XStream2(XStream2.getDefaultDriver());
xs.alias("com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint", BitbucketCloudEndpoint.class);
xs.alias("com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint", BitbucketServerEndpoint.class);
xs.omitField(BitbucketServerEndpoint.class, "callCanMerge");
xs.omitField(BitbucketServerEndpoint.class, "callChanges");
return new XmlFile(xs, cfgFile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,12 @@ public enum HookEventType {
*/
SERVER_PULL_REQUEST_DELETED("pr:deleted", NativeServerPullRequestHookProcessor.class),

/**
* See <a href="https://confluence.atlassian.com/bitbucketserver054/event-payload-939508609.html#Eventpayload-Approved">Eventpayload-Approved</a>
*
* @since Bitbucket Server 5.4
*/
SERVER_PULL_REQUEST_APPROVED("pr:reviewer:approved", NativeServerPullRequestHookProcessor.class),

/**
* @see <a href="https://confluence.atlassian.com/bitbucketserver0510/event-payload-951390742.html#Eventpayload-Modified.1">Eventpayload: Pull Request - Modified</a>
* @since Bitbucket Server 5.10
*/
SERVER_PULL_REQUEST_MODIFIED("pr:modified", NativeServerPullRequestHookProcessor.class),

/**
* @see <a href="https://confluence.atlassian.com/bitbucketserver0510/event-payload-951390742.html#Eventpayload-ReviewersUpdated">Eventpayload: Pull Request - Reviewers Updated</a>
* @since Bitbucket Server 5.10
*/
SERVER_PULL_REQUEST_REVIEWER_UPDATED("pr:reviewer:updated", NativeServerPullRequestHookProcessor.class),

/**
* @see <a href="https://confluence.atlassian.com/bitbucketserver070/event-payload-996644369.html#Eventpayload-Sourcebranchupdated">Eventpayload-Sourcebranchupdated</a>
* @since Bitbucket Server 7.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public void process(HookEventType hookEvent, String payload, BitbucketType insta
eventType = SCMEvent.Type.REMOVED;
break;
case SERVER_PULL_REQUEST_MODIFIED,
SERVER_PULL_REQUEST_REVIEWER_UPDATED,
SERVER_PULL_REQUEST_FROM_REF_UPDATED:
eventType = SCMEvent.Type.UPDATED;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketCloudHook;
import com.cloudbees.jenkins.plugins.bitbucket.impl.endpoint.BitbucketServerEndpoint;
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerVersion;
import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketPluginWebhook;
import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketServerWebhook;
import com.damnhandy.uri.template.UriTemplate;
Expand Down Expand Up @@ -67,20 +68,16 @@ public class WebhookConfiguration {
));

/**
* The list of events available in Bitbucket Server v7.x.
* The list of events available in Bitbucket Data Center v8.x.
*/
private static final List<String> NATIVE_SERVER_EVENTS_v7 = Collections.unmodifiableList(Arrays.asList(
HookEventType.SERVER_REFS_CHANGED.getKey(),
HookEventType.SERVER_PULL_REQUEST_OPENED.getKey(),
HookEventType.SERVER_PULL_REQUEST_MERGED.getKey(),
HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey(),
HookEventType.SERVER_PULL_REQUEST_DELETED.getKey(),
// only on v5.10 and above
HookEventType.SERVER_PULL_REQUEST_MODIFIED.getKey(),
HookEventType.SERVER_PULL_REQUEST_REVIEWER_UPDATED.getKey(),
// only on v6.5 and above
HookEventType.SERVER_MIRROR_REPO_SYNCHRONIZED.getKey(),
// only on v7.x and above
HookEventType.SERVER_PULL_REQUEST_FROM_REF_UPDATED.getKey()
));

Expand All @@ -98,21 +95,6 @@ public class WebhookConfiguration {
"REPOSITORY_MIRROR_SYNCHRONIZED", // not supported by the hookprocessor
"TAG_CREATED"));

/**
* The list of events available in Bitbucket Server v6.5+.
*/
private static final List<String> NATIVE_SERVER_EVENTS_v6_5 = Collections.unmodifiableList(NATIVE_SERVER_EVENTS_v7.subList(0, 8));

/**
* The list of events available in Bitbucket Server v6.x. Applies to v5.10+.
*/
private static final List<String> NATIVE_SERVER_EVENTS_v6 = Collections.unmodifiableList(NATIVE_SERVER_EVENTS_v7.subList(0, 7));

/**
* The list of events available in Bitbucket Server v5.9-.
*/
private static final List<String> NATIVE_SERVER_EVENTS_v5 = Collections.unmodifiableList(NATIVE_SERVER_EVENTS_v7.subList(0, 5));

/**
* The title of the webhook.
*/
Expand Down Expand Up @@ -280,30 +262,13 @@ private static List<String> getNativeServerEvents(String serverURL) {
.lookupEndpoint(serverURL, BitbucketServerEndpoint.class)
.orElse(null);
if (endpoint != null) {
switch (endpoint.getServerVersion()) {
case VERSION_5:
return NATIVE_SERVER_EVENTS_v5;
case VERSION_5_10:
return NATIVE_SERVER_EVENTS_v6;
case VERSION_6:
// plugin version 2.9.1 introduced VERSION_6 setting for Bitbucket but it
// actually applies
// to Version 5.10+. In order to preserve backwards compatibility, rather than
// remove
// VERSION_6, it will use the same list as 5.10 until such time a need arises
// for it to have its
// own list
return NATIVE_SERVER_EVENTS_v6;
case VERSION_6_5:
return NATIVE_SERVER_EVENTS_v6_5;
BitbucketServerVersion serverVersion = BitbucketServerVersion.valueOf(endpoint.getServerVersion());
switch (serverVersion) {
case VERSION_7:
default:
return NATIVE_SERVER_EVENTS_v7;
}
}

// Not specifically v6, use v7.
// Better to give an error than quietly not register some events.
return NATIVE_SERVER_EVENTS_v7;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* The MIT License
*
* Copyright (c) 2025, Nikolas Falco
*
* 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, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.cloudbees.jenkins.plugins.bitbucket.impl.casc;

import com.cloudbees.jenkins.plugins.bitbucket.impl.endpoint.BitbucketServerEndpoint;
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerWebhookImplementation;
import hudson.Extension;
import io.jenkins.plugins.casc.BaseConfigurator;
import io.jenkins.plugins.casc.ConfigurationAsCode;
import io.jenkins.plugins.casc.ConfigurationContext;
import io.jenkins.plugins.casc.ConfiguratorException;
import io.jenkins.plugins.casc.model.Mapping;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.commons.lang3.StringUtils.trimToNull;

/**
* Specialised class to configure how to build a new instance of
* BitbucketServerEndpoint using {@link ConfigurationAsCode}.
*
* @since 937.0.0
*/
@Extension
@Restricted(NoExternalUse.class)
public class BitbucketServerEndpointConfigurator extends BaseConfigurator<BitbucketServerEndpoint> {
private final static Logger logger = LoggerFactory.getLogger(BitbucketServerEndpointConfigurator.class);

@Override
public Class<BitbucketServerEndpoint> getTarget() {
return BitbucketServerEndpoint.class;
}

@Override
protected BitbucketServerEndpoint instance(Mapping mapping, ConfigurationContext context) throws ConfiguratorException {
final String displayName = mapping.getScalarValue("displayName");
final String serverURL;
if (mapping.containsKey("serverUrl")) {

Check warning on line 61 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/casc/BitbucketServerEndpointConfigurator.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 61 is only partially covered, one branch is missing
serverURL = mapping.getScalarValue("serverUrl");
} else {
serverURL = mapping.getScalarValue("serverURL");

Check warning on line 64 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/casc/BitbucketServerEndpointConfigurator.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 64 is not covered by tests
}
boolean manageHooks = false;
if (mapping.containsKey("manageHooks")) {
manageHooks = Boolean.parseBoolean(trimToNull(mapping.getScalarValue("manageHooks")));
}
String credentialsId = null;
if (mapping.containsKey("credentialsId")) {
credentialsId = mapping.getScalarValue("credentialsId");
}
boolean enableHookSignature = false;
if (mapping.containsKey("enableHookSignature")) {
enableHookSignature = Boolean.parseBoolean(trimToNull(mapping.getScalarValue("enableHookSignature")));
}
String hookSignatureCredentialsId = null;
if (mapping.containsKey("hookSignatureCredentialsId")) {
credentialsId = mapping.getScalarValue("hookSignatureCredentialsId");
}
String serverVersion = null;
if (mapping.containsKey("serverVersion")) {
serverVersion = mapping.getScalarValue("serverVersion");
}
BitbucketServerWebhookImplementation webhookImplementation = null;
if (mapping.containsKey("webhookImplementation")) {
webhookImplementation = BitbucketServerWebhookImplementation.valueOf(mapping.getScalarValue("webhookImplementation"));
}
BitbucketServerEndpoint endpoint = new BitbucketServerEndpoint(displayName, serverURL, manageHooks, credentialsId, enableHookSignature, hookSignatureCredentialsId);
if (serverVersion != null) {
endpoint.setServerVersion(serverVersion);
}
if (webhookImplementation != null) {
endpoint.setWebhookImplementation(webhookImplementation);
}
// remove unmapped attributes
if (mapping.containsKey("callCanMerge")) {
logger.warn("callCanMerge is deprecated and ignore for BitbucketServerEndpoint definition, remove from your CasC definition.");
mapping.remove("callCanMerge");
}
if (mapping.containsKey("callChanges")) {
logger.warn("callChanges is deprecated and ignore for BitbucketServerEndpoint definition, remove from your CasC definition.");
mapping.remove("callChanges");
}
return endpoint;
}

}
Loading
Loading