Skip to content

Commit bb4c78b

Browse files
committed
[JENKINS-75804] Webhook auto registration fail with PLUGIN implementation (#1071)
Add missing logic on when update a plugin hook. Add manage of which events must be subscribed.
1 parent c074de4 commit bb4c78b

File tree

7 files changed

+334
-28
lines changed

7 files changed

+334
-28
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ public void setServerUrl(@CheckForNull String serverUrl) {
295295
}
296296
}
297297

298+
@Restricted(NoExternalUse.class)
299+
@Deprecated(forRemoval = true)
300+
// expose if needed in BitbucketEndpointProvider, normally could be get from endpoint if not customized
298301
@NonNull
299302
public String getEndpointJenkinsRootURL() {
300303
return AbstractBitbucketEndpoint.getEndpointJenkinsRootUrl(serverUrl);

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketWebHook.java

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

26+
import edu.umd.cs.findbugs.annotations.NonNull;
2627
import edu.umd.cs.findbugs.annotations.Nullable;
2728
import java.util.List;
2829

@@ -49,6 +50,7 @@ public interface BitbucketWebHook {
4950
/**
5051
* @return the list of events this webhook is notifying
5152
*/
53+
@NonNull
5254
List<String> getEvents();
5355

5456
/**

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudHook.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
package com.cloudbees.jenkins.plugins.bitbucket.client.repository;
2525

2626
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook;
27+
import java.util.ArrayList;
2728
import java.util.List;
29+
import org.apache.commons.lang3.ObjectUtils;
2830

2931
public class BitbucketCloudHook implements BitbucketWebHook {
3032

@@ -38,7 +40,7 @@ public class BitbucketCloudHook implements BitbucketWebHook {
3840

3941
private boolean active;
4042

41-
private List<String> events;
43+
private List<String> events = new ArrayList<>();
4244

4345
@Override
4446
public String getDescription() {
@@ -73,7 +75,7 @@ public List<String> getEvents() {
7375
}
7476

7577
public void setEvents(List<String> events) {
76-
this.events = events;
78+
this.events = ObjectUtils.firstNonNull(events,new ArrayList<>());
7779
}
7880

7981
@Override
@@ -85,6 +87,7 @@ public void setUuid(String uuid) {
8587
this.uuid = uuid;
8688
}
8789

90+
@Override
8891
public String getSecret() {
8992
return secret;
9093
}

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

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpoint;
2929
import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpointProvider;
3030
import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketCloudHook;
31+
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint;
3132
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint;
3233
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
3334
import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketPluginWebhook;
@@ -121,40 +122,64 @@ public String getCommittersToIgnore() {
121122
boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) {
122123
boolean updated = false;
123124

125+
final String serverURL = owner.getServerUrl();
126+
final String rootURL = getEndpointJenkinsRootURL(serverURL);
124127
final String signatureSecret = getSecret(owner.getServerUrl());
125128

126129
if (hook instanceof BitbucketCloudHook cloudHook) {
127-
if (!hook.getEvents().containsAll(CLOUD_EVENTS)) {
128-
Set<String> events = new TreeSet<>(hook.getEvents());
129-
events.addAll(CLOUD_EVENTS);
130-
cloudHook.setEvents(new ArrayList<>(events));
130+
String url = getCloudWebhookURL(serverURL, rootURL);
131+
if (!Objects.equal(hook.getUrl(), url)) {
132+
cloudHook.setUrl(url);
131133
updated = true;
132134
}
135+
136+
List<String> events = hook.getEvents();
137+
if (!events.containsAll(CLOUD_EVENTS)) {
138+
Set<String> newEvents = new TreeSet<>(events);
139+
newEvents.addAll(CLOUD_EVENTS);
140+
cloudHook.setEvents(new ArrayList<>(newEvents));
141+
updated = true;
142+
}
143+
133144
if (!Objects.equal(hook.getSecret(), signatureSecret)) {
134145
cloudHook.setSecret(signatureSecret);
135146
updated = true;
136147
}
137-
} else if (hook instanceof BitbucketPluginWebhook serverHook) {
138-
String hookCommittersToIgnore = Util.fixEmptyAndTrim(serverHook.getCommittersToIgnore());
148+
} else if (hook instanceof BitbucketPluginWebhook pluginHook) {
149+
String hookCommittersToIgnore = Util.fixEmptyAndTrim(pluginHook.getCommittersToIgnore());
139150
String thisCommittersToIgnore = Util.fixEmptyAndTrim(committersToIgnore);
140151
if (!Objects.equal(thisCommittersToIgnore, hookCommittersToIgnore)) {
141-
serverHook.setCommittersToIgnore(thisCommittersToIgnore);
152+
pluginHook.setCommittersToIgnore(thisCommittersToIgnore);
153+
updated = true;
154+
}
155+
156+
String url = getServerWebhookURL(serverURL, rootURL);
157+
if (!url.equals(pluginHook.getUrl())) {
158+
pluginHook.setUrl(url);
159+
updated = true;
160+
}
161+
162+
if (!pluginHook.isActive()) {
163+
pluginHook.setActive(true);
142164
updated = true;
143165
}
144-
} else if (hook instanceof BitbucketServerWebhook serverHook) {
145-
String serverURL = owner.getServerUrl();
146-
String url = getServerWebhookURL(serverURL, owner.getEndpointJenkinsRootURL());
147166

167+
List<String> events = pluginHook.getEvents();
168+
if (!events.containsAll(getNativeServerEvents(serverURL))) {
169+
Set<String> newEvents = new TreeSet<>(events);
170+
newEvents.addAll(getNativeServerEvents(serverURL));
171+
pluginHook.setEvents(new ArrayList<>(newEvents));
172+
updated = true;
173+
}
174+
} else if (hook instanceof BitbucketServerWebhook serverHook) {
175+
String url = getServerWebhookURL(serverURL, rootURL);
148176
if (!url.equals(serverHook.getUrl())) {
149177
serverHook.setUrl(url);
150178
updated = true;
151179
}
152180

153181
List<String> events = serverHook.getEvents();
154-
if (events == null) {
155-
serverHook.setEvents(getNativeServerEvents(serverURL));
156-
updated = true;
157-
} else if (!events.containsAll(getNativeServerEvents(serverURL))) {
182+
if (!events.containsAll(getNativeServerEvents(serverURL))) {
158183
Set<String> newEvents = new TreeSet<>(events);
159184
newEvents.addAll(getNativeServerEvents(serverURL));
160185
serverHook.setEvents(new ArrayList<>(newEvents));
@@ -170,28 +195,34 @@ boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) {
170195
return updated;
171196
}
172197

198+
@NonNull
199+
private String getEndpointJenkinsRootURL(@NonNull String serverURL) {
200+
return AbstractBitbucketEndpoint.getEndpointJenkinsRootUrl(serverURL);
201+
}
202+
203+
@NonNull
173204
public BitbucketWebHook getHook(BitbucketSCMSource owner) {
174-
final String serverUrl = owner.getServerUrl();
175-
final String rootUrl = owner.getEndpointJenkinsRootURL();
205+
final String serverURL = owner.getServerUrl();
206+
final String rootURL = getEndpointJenkinsRootURL(serverURL);
176207
final String signatureSecret = getSecret(owner.getServerUrl());
177208

178-
if (BitbucketApiUtils.isCloud(serverUrl)) {
209+
if (BitbucketApiUtils.isCloud(serverURL)) {
179210
BitbucketCloudHook hook = new BitbucketCloudHook();
180211
hook.setEvents(CLOUD_EVENTS);
181212
hook.setActive(true);
182213
hook.setDescription(description);
183-
hook.setUrl(rootUrl + BitbucketSCMSourcePushHookReceiver.FULL_PATH);
214+
hook.setUrl(getCloudWebhookURL(serverURL, rootURL));
184215
hook.setSecret(signatureSecret);
185216
return hook;
186217
}
187218

188-
switch (BitbucketServerEndpoint.findWebhookImplementation(serverUrl)) {
219+
switch (BitbucketServerEndpoint.findWebhookImplementation(serverURL)) {
189220
case NATIVE: {
190221
BitbucketServerWebhook hook = new BitbucketServerWebhook();
191222
hook.setActive(true);
192223
hook.setDescription(description);
193-
hook.setEvents(getNativeServerEvents(serverUrl));
194-
hook.setUrl(getServerWebhookURL(serverUrl, rootUrl));
224+
hook.setEvents(getNativeServerEvents(serverURL));
225+
hook.setUrl(getServerWebhookURL(serverURL, rootURL));
195226
hook.setSecret(signatureSecret);
196227
return hook;
197228
}
@@ -201,7 +232,7 @@ public BitbucketWebHook getHook(BitbucketSCMSource owner) {
201232
BitbucketPluginWebhook hook = new BitbucketPluginWebhook();
202233
hook.setActive(true);
203234
hook.setDescription(description);
204-
hook.setUrl(getServerWebhookURL(serverUrl, rootUrl));
235+
hook.setUrl(getServerWebhookURL(serverURL, rootURL));
205236
hook.setCommittersToIgnore(committersToIgnore);
206237
return hook;
207238
}
@@ -256,6 +287,13 @@ private static List<String> getNativeServerEvents(String serverUrl) {
256287
return NATIVE_SERVER_EVENTS_v7;
257288
}
258289

290+
private static String getCloudWebhookURL(String serverURL, String rootURL) {
291+
return UriTemplate.buildFromTemplate(rootURL)
292+
.template(BitbucketSCMSourcePushHookReceiver.FULL_PATH)
293+
.build()
294+
.expand();
295+
}
296+
259297
private static String getServerWebhookURL(String serverURL, String rootURL) {
260298
return UriTemplate.buildFromTemplate(rootURL)
261299
.template(BitbucketSCMSourcePushHookReceiver.FULL_PATH)

0 commit comments

Comments
 (0)