Skip to content

Commit c6eb2a3

Browse files
committed
Add Bitbucket Server Version option
This works around incompatibilities between older versions of bitbucket and bitbucket v7.x. Let's users specify their version.
1 parent ad50683 commit c6eb2a3

File tree

5 files changed

+125
-9
lines changed

5 files changed

+125
-9
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
package com.cloudbees.jenkins.plugins.bitbucket.endpoints;
2525

26+
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerVersion;
2627
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerWebhookImplementation;
2728
import com.cloudbees.plugins.credentials.common.StandardCredentials;
2829
import com.damnhandy.uri.template.UriTemplate;
@@ -34,6 +35,7 @@
3435
import hudson.util.ListBoxModel;
3536
import java.net.MalformedURLException;
3637
import java.net.URL;
38+
import java.util.Objects;
3739
import javax.annotation.Nonnull;
3840
import jenkins.scm.api.SCMName;
3941
import org.apache.commons.lang.StringUtils;
@@ -80,6 +82,11 @@ public class BitbucketServerEndpoint extends AbstractBitbucketEndpoint {
8082
@NonNull
8183
private BitbucketServerWebhookImplementation webhookImplementation = BitbucketServerWebhookImplementation.PLUGIN;
8284

85+
/**
86+
* The server version for this endpoint.
87+
*/
88+
private BitbucketServerVersion serverVersion = BitbucketServerVersion.VERSION_7;
89+
8390
/**
8491
* Whether to always call the can merge api when retrieving pull requests.
8592
*/
@@ -134,12 +141,32 @@ public void setCallCanMerge(boolean callCanMerge) {
134141
}
135142

136143
public boolean isCallChanges() {
137-
return callChanges;
144+
return callChanges && BitbucketServerVersion.VERSION_7.equals(serverVersion);
138145
}
139146

140147
@DataBoundSetter
141148
public void setCallChanges(boolean callChanges) {
142-
this.callChanges = callChanges;
149+
this.callChanges = callChanges && BitbucketServerVersion.VERSION_7.equals(serverVersion);
150+
}
151+
152+
@NonNull
153+
public static BitbucketServerVersion findServerVersion(String serverUrl) {
154+
final AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl);
155+
if (endpoint instanceof BitbucketServerEndpoint) {
156+
return ((BitbucketServerEndpoint) endpoint).getServerVersion();
157+
}
158+
159+
return BitbucketServerVersion.VERSION_7;
160+
}
161+
162+
@NonNull
163+
public BitbucketServerVersion getServerVersion() {
164+
return this.serverVersion;
165+
}
166+
167+
@DataBoundSetter
168+
public void setServerVersion(@NonNull BitbucketServerVersion serverVersion) {
169+
this.serverVersion = Objects.requireNonNull(serverVersion);
143170
}
144171

145172
/**
@@ -181,6 +208,14 @@ private Object readResolve() {
181208
if (getBitbucketJenkinsRootUrl() != null) {
182209
setBitbucketJenkinsRootUrl(getBitbucketJenkinsRootUrl());
183210
}
211+
if (serverVersion == null) {
212+
if (Boolean.TRUE.equals(callChanges)) {
213+
serverVersion = BitbucketServerVersion.VERSION_7;
214+
} else {
215+
serverVersion = BitbucketServerVersion.VERSION_6;
216+
}
217+
}
218+
184219
return this;
185220
}
186221

@@ -218,6 +253,16 @@ public ListBoxModel doFillWebhookImplementationItems() {
218253
return items;
219254
}
220255

256+
@Restricted(NoExternalUse.class)
257+
public ListBoxModel doFillServerVersionItems() {
258+
ListBoxModel items = new ListBoxModel();
259+
for (BitbucketServerVersion serverVersion : BitbucketServerVersion.values()) {
260+
items.add(serverVersion, serverVersion.name());
261+
}
262+
263+
return items;
264+
}
265+
221266
/**
222267
* Checks that the supplied URL is valid.
223268
*

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource;
2727
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook;
2828
import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketRepositoryHook;
29+
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint;
2930
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint;
31+
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration;
3032
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint;
33+
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerVersion;
3134
import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketServerWebhook;
3235
import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.NativeBitbucketServerWebhook;
3336
import com.damnhandy.uri.template.UriTemplate;
@@ -56,19 +59,25 @@ public class WebhookConfiguration {
5659
));
5760

5861
/**
59-
* The list of events available in Bitbucket Server.
62+
* The list of events available in Bitbucket Server v7.x.
6063
*/
61-
private static final List<String> NATIVE_SERVER_EVENTS = Collections.unmodifiableList(Arrays.asList(
64+
private static final List<String> NATIVE_SERVER_EVENTS_v7 = Collections.unmodifiableList(Arrays.asList(
6265
HookEventType.SERVER_REFS_CHANGED.getKey(),
6366
HookEventType.SERVER_PULL_REQUEST_OPENED.getKey(),
6467
HookEventType.SERVER_PULL_REQUEST_MERGED.getKey(),
6568
HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey(),
6669
HookEventType.SERVER_PULL_REQUEST_DELETED.getKey(),
6770
HookEventType.SERVER_PULL_REQUEST_MODIFIED.getKey(),
6871
HookEventType.SERVER_PULL_REQUEST_REVIEWER_UPDATED.getKey(),
72+
// only on v7.x and above
6973
HookEventType.SERVER_PULL_REQUEST_FROM_REF_UPDATED.getKey()
7074
));
7175

76+
/**
77+
* The list of events available in Bitbucket Server v6.x.
78+
*/
79+
private static final List<String> NATIVE_SERVER_EVENTS_v6 = Collections.unmodifiableList(NATIVE_SERVER_EVENTS_v7.subList(0, 6));
80+
7281
/**
7382
* The title of the webhook.
7483
*/
@@ -131,7 +140,8 @@ boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) {
131140
boolean updated = false;
132141

133142
NativeBitbucketServerWebhook serverHook = (NativeBitbucketServerWebhook) hook;
134-
String url = getNativeServerWebhookUrl(owner.getServerUrl(), owner.getEndpointJenkinsRootUrl());
143+
String serverUrl = owner.getServerUrl();
144+
String url = getNativeServerWebhookUrl(serverUrl, owner.getEndpointJenkinsRootUrl());
135145

136146
if (!url.equals(serverHook.getUrl())) {
137147
serverHook.setUrl(url);
@@ -140,11 +150,11 @@ boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) {
140150

141151
List<String> events = serverHook.getEvents();
142152
if (events == null) {
143-
serverHook.setEvents(NATIVE_SERVER_EVENTS);
153+
serverHook.setEvents(getNativeServerEvents(serverUrl));
144154
updated = true;
145-
} else if (!events.containsAll(NATIVE_SERVER_EVENTS)) {
155+
} else if (!events.containsAll(getNativeServerEvents(serverUrl))) {
146156
Set<String> newEvents = new TreeSet<>(events);
147-
newEvents.addAll(NATIVE_SERVER_EVENTS);
157+
newEvents.addAll(getNativeServerEvents(serverUrl));
148158
serverHook.setEvents(new ArrayList<>(newEvents));
149159
updated = true;
150160
}
@@ -158,6 +168,7 @@ boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) {
158168
public BitbucketWebHook getHook(BitbucketSCMSource owner) {
159169
final String serverUrl = owner.getServerUrl();
160170
final String rootUrl = owner.getEndpointJenkinsRootUrl();
171+
161172
if (BitbucketCloudEndpoint.SERVER_URL.equals(serverUrl)) {
162173
BitbucketRepositoryHook hook = new BitbucketRepositoryHook();
163174
hook.setEvents(CLOUD_EVENTS);
@@ -171,7 +182,7 @@ public BitbucketWebHook getHook(BitbucketSCMSource owner) {
171182
case NATIVE: {
172183
NativeBitbucketServerWebhook hook = new NativeBitbucketServerWebhook();
173184
hook.setActive(true);
174-
hook.setEvents(NATIVE_SERVER_EVENTS);
185+
hook.setEvents(getNativeServerEvents(serverUrl));
175186
hook.setDescription(description);
176187
hook.setUrl(getNativeServerWebhookUrl(serverUrl, rootUrl));
177188
return hook;
@@ -189,6 +200,19 @@ public BitbucketWebHook getHook(BitbucketSCMSource owner) {
189200
}
190201
}
191202

203+
private static List<String> getNativeServerEvents(String serverUrl) {
204+
AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl);
205+
if (endpoint instanceof BitbucketServerEndpoint) {
206+
if (((BitbucketServerEndpoint)endpoint).getServerVersion().equals(BitbucketServerVersion.VERSION_6)) {
207+
return NATIVE_SERVER_EVENTS_v6;
208+
}
209+
}
210+
211+
// Not specifically v6, use v7.
212+
// Better to give an error than quietly not register some events.
213+
return NATIVE_SERVER_EVENTS_v7;
214+
}
215+
192216
private static String getNativeServerWebhookUrl(String serverUrl, String rootUrl) {
193217
return UriTemplate.buildFromTemplate(rootUrl)
194218
.template(BitbucketSCMSourcePushHookReceiver.FULL_PATH)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* The MIT License
3+
*
4+
* Copyright (c) 2016-2020, CloudBees Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.server;
25+
26+
import hudson.model.ModelObject;
27+
28+
public enum BitbucketServerVersion implements ModelObject {
29+
VERSION_7 {
30+
@Override
31+
public String getDisplayName() {
32+
return "Bitbucket v7.x (and later)";
33+
}
34+
},
35+
36+
VERSION_6 {
37+
@Override
38+
public String getDisplayName() {
39+
return "Bitbucket v6.x (and earlier)";
40+
}
41+
}}

src/main/resources/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint/config-detail.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
<f:entry title="${%Server URL}" field="serverUrl">
88
<f:textbox/>
99
</f:entry>
10+
<f:entry title="${%Server Version}" field="serverVersion">
11+
<f:select />
12+
</f:entry>
1013
<f:entry field="callCanMerge">
1114
<f:checkbox title="${%Call Can Merge}" default="true"/>
1215
</f:entry>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div>
2+
Select the version of Bitbucket server for this endpoint. Some feature may not work if this setting does not match the version of the server point to by this endpoint.
3+
</div>

0 commit comments

Comments
 (0)