diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java index 730cacbc3..d72a9f8b8 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java @@ -295,6 +295,9 @@ public void setServerUrl(@CheckForNull String serverUrl) { } } + @Restricted(NoExternalUse.class) + @Deprecated(forRemoval = true) + // expose if needed in BitbucketEndpointProvider, normally could be get from endpoint if not customized @NonNull public String getEndpointJenkinsRootURL() { return AbstractBitbucketEndpoint.getEndpointJenkinsRootUrl(serverUrl); diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketWebHook.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketWebHook.java index 1dbd83d0d..79924bc33 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketWebHook.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketWebHook.java @@ -23,6 +23,7 @@ */ package com.cloudbees.jenkins.plugins.bitbucket.api; +import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.util.List; @@ -49,6 +50,7 @@ public interface BitbucketWebHook { /** * @return the list of events this webhook is notifying */ + @NonNull List getEvents(); /** diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudHook.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudHook.java index 0e9605a99..004a19224 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudHook.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudHook.java @@ -24,7 +24,9 @@ package com.cloudbees.jenkins.plugins.bitbucket.client.repository; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook; +import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.ObjectUtils; public class BitbucketCloudHook implements BitbucketWebHook { @@ -38,7 +40,7 @@ public class BitbucketCloudHook implements BitbucketWebHook { private boolean active; - private List events; + private List events = new ArrayList<>(); @Override public String getDescription() { @@ -73,7 +75,7 @@ public List getEvents() { } public void setEvents(List events) { - this.events = events; + this.events = ObjectUtils.firstNonNull(events,new ArrayList<>()); } @Override @@ -85,6 +87,7 @@ public void setUuid(String uuid) { this.uuid = uuid; } + @Override public String getSecret() { return secret; } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java index 10d45025e..9673fb6de 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java @@ -179,10 +179,10 @@ private void registerHook(BitbucketSCMSource source) throws IOException { .withTraits(source.getTraits()) .webhookConfiguration(); if (existingHook == null) { - LOGGER.log(Level.INFO, "Registering hook for {0}/{1}", new Object[]{source.getRepoOwner(), source.getRepository()}); + LOGGER.log(Level.WARNING, "Registering hook for {0}/{1}", new Object[]{source.getRepoOwner(), source.getRepository()}); bitbucket.registerCommitWebHook(hookConfig.getHook(source)); } else if (hookConfig.updateHook(existingHook, source)) { - LOGGER.log(Level.INFO, "Updating hook for {0}/{1}", new Object[]{source.getRepoOwner(), source.getRepository()}); + LOGGER.log(Level.WARNING, "Updating hook for {0}/{1}", new Object[]{source.getRepoOwner(), source.getRepository()}); bitbucket.updateCommitWebHook(existingHook); } } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java index f22930c46..bb2933397 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java @@ -28,6 +28,7 @@ import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpoint; import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpointProvider; import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketCloudHook; +import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint; import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint; import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils; import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketPluginWebhook; @@ -121,40 +122,64 @@ public String getCommittersToIgnore() { boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) { boolean updated = false; + final String serverURL = owner.getServerUrl(); + final String rootURL = getEndpointJenkinsRootURL(serverURL); final String signatureSecret = getSecret(owner.getServerUrl()); if (hook instanceof BitbucketCloudHook cloudHook) { - if (!hook.getEvents().containsAll(CLOUD_EVENTS)) { - Set events = new TreeSet<>(hook.getEvents()); - events.addAll(CLOUD_EVENTS); - cloudHook.setEvents(new ArrayList<>(events)); + String url = getCloudWebhookURL(serverURL, rootURL); + if (!Objects.equal(hook.getUrl(), url)) { + cloudHook.setUrl(url); updated = true; } + + List events = hook.getEvents(); + if (!events.containsAll(CLOUD_EVENTS)) { + Set newEvents = new TreeSet<>(events); + newEvents.addAll(CLOUD_EVENTS); + cloudHook.setEvents(new ArrayList<>(newEvents)); + updated = true; + } + if (!Objects.equal(hook.getSecret(), signatureSecret)) { cloudHook.setSecret(signatureSecret); updated = true; } - } else if (hook instanceof BitbucketPluginWebhook serverHook) { - String hookCommittersToIgnore = Util.fixEmptyAndTrim(serverHook.getCommittersToIgnore()); + } else if (hook instanceof BitbucketPluginWebhook pluginHook) { + String hookCommittersToIgnore = Util.fixEmptyAndTrim(pluginHook.getCommittersToIgnore()); String thisCommittersToIgnore = Util.fixEmptyAndTrim(committersToIgnore); if (!Objects.equal(thisCommittersToIgnore, hookCommittersToIgnore)) { - serverHook.setCommittersToIgnore(thisCommittersToIgnore); + pluginHook.setCommittersToIgnore(thisCommittersToIgnore); + updated = true; + } + + String url = getServerWebhookURL(serverURL, rootURL); + if (!url.equals(pluginHook.getUrl())) { + pluginHook.setUrl(url); + updated = true; + } + + if (!pluginHook.isActive()) { + pluginHook.setActive(true); updated = true; } - } else if (hook instanceof BitbucketServerWebhook serverHook) { - String serverURL = owner.getServerUrl(); - String url = getServerWebhookURL(serverURL, owner.getEndpointJenkinsRootURL()); + List events = pluginHook.getEvents(); + if (!events.containsAll(getNativeServerEvents(serverURL))) { + Set newEvents = new TreeSet<>(events); + newEvents.addAll(getNativeServerEvents(serverURL)); + pluginHook.setEvents(new ArrayList<>(newEvents)); + updated = true; + } + } else if (hook instanceof BitbucketServerWebhook serverHook) { + String url = getServerWebhookURL(serverURL, rootURL); if (!url.equals(serverHook.getUrl())) { serverHook.setUrl(url); updated = true; } List events = serverHook.getEvents(); - if (events == null) { - serverHook.setEvents(getNativeServerEvents(serverURL)); - updated = true; - } else if (!events.containsAll(getNativeServerEvents(serverURL))) { + if (!events.containsAll(getNativeServerEvents(serverURL))) { Set newEvents = new TreeSet<>(events); newEvents.addAll(getNativeServerEvents(serverURL)); serverHook.setEvents(new ArrayList<>(newEvents)); @@ -170,28 +195,34 @@ boolean updateHook(BitbucketWebHook hook, BitbucketSCMSource owner) { return updated; } + @NonNull + private String getEndpointJenkinsRootURL(@NonNull String serverURL) { + return AbstractBitbucketEndpoint.getEndpointJenkinsRootUrl(serverURL); + } + + @NonNull public BitbucketWebHook getHook(BitbucketSCMSource owner) { - final String serverUrl = owner.getServerUrl(); - final String rootUrl = owner.getEndpointJenkinsRootURL(); + final String serverURL = owner.getServerUrl(); + final String rootURL = getEndpointJenkinsRootURL(serverURL); final String signatureSecret = getSecret(owner.getServerUrl()); - if (BitbucketApiUtils.isCloud(serverUrl)) { + if (BitbucketApiUtils.isCloud(serverURL)) { BitbucketCloudHook hook = new BitbucketCloudHook(); hook.setEvents(CLOUD_EVENTS); hook.setActive(true); hook.setDescription(description); - hook.setUrl(rootUrl + BitbucketSCMSourcePushHookReceiver.FULL_PATH); + hook.setUrl(getCloudWebhookURL(serverURL, rootURL)); hook.setSecret(signatureSecret); return hook; } - switch (BitbucketServerEndpoint.findWebhookImplementation(serverUrl)) { + switch (BitbucketServerEndpoint.findWebhookImplementation(serverURL)) { case NATIVE: { BitbucketServerWebhook hook = new BitbucketServerWebhook(); hook.setActive(true); hook.setDescription(description); - hook.setEvents(getNativeServerEvents(serverUrl)); - hook.setUrl(getServerWebhookURL(serverUrl, rootUrl)); + hook.setEvents(getNativeServerEvents(serverURL)); + hook.setUrl(getServerWebhookURL(serverURL, rootURL)); hook.setSecret(signatureSecret); return hook; } @@ -201,7 +232,7 @@ public BitbucketWebHook getHook(BitbucketSCMSource owner) { BitbucketPluginWebhook hook = new BitbucketPluginWebhook(); hook.setActive(true); hook.setDescription(description); - hook.setUrl(getServerWebhookURL(serverUrl, rootUrl)); + hook.setUrl(getServerWebhookURL(serverURL, rootURL)); hook.setCommittersToIgnore(committersToIgnore); return hook; } @@ -256,6 +287,13 @@ private static List getNativeServerEvents(String serverUrl) { return NATIVE_SERVER_EVENTS_v7; } + private static String getCloudWebhookURL(String serverURL, String rootURL) { + return UriTemplate.buildFromTemplate(rootURL) + .template(BitbucketSCMSourcePushHookReceiver.FULL_PATH) + .build() + .expand(); + } + private static String getServerWebhookURL(String serverURL, String rootURL) { return UriTemplate.buildFromTemplate(rootURL) .template(BitbucketSCMSourcePushHookReceiver.FULL_PATH) diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java index 3c822fd14..015e0d2e4 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java @@ -91,10 +91,15 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.methods.HttpPut; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicNameValuePair; import static java.util.Objects.requireNonNull; @@ -675,17 +680,41 @@ public void registerCommitWebHook(BitbucketWebHook hook) throws IOException { @Override public void updateCommitWebHook(BitbucketWebHook hook) throws IOException { + String payload = JsonParser.toString(hook); switch (webhookImplementation) { case PLUGIN: // API documentation at https://help.moveworkforward.com/BPW/how-to-manage-configurations-using-post-webhooks-f#HowtomanageconfigurationsusingPostWebhooksforBitbucketAPIs?-UpdateapostwebhookbyID - putRequest( - UriTemplate - .fromTemplate(this.baseURL + WEBHOOK_REPOSITORY_CONFIG_PATH) - .set("owner", getUserCentricOwner()) - .set("repo", repositoryName) - .set("id", hook.getUuid()) - .expand(), JsonParser.toString(hook) - ); + String path = UriTemplate + .fromTemplate(this.baseURL + WEBHOOK_REPOSITORY_CONFIG_PATH) + .set("owner", getUserCentricOwner()) + .set("repo", repositoryName) + .set("id", hook.getUuid()) + .expand(); + logger.warning("Updating PLUGIN web hook sending " + payload); + HttpPut request = new HttpPut(path); + request.setAbsoluteRequestUri(true); + request.setEntity(new StringEntity(payload, ContentType.create("application/json", "UTF-8"))); + try (ClassicHttpResponse response = executeMethod(request)) { + int statusCode = response.getCode(); + if (statusCode == HttpStatus.SC_NOT_FOUND) { + String errorMessage = getResponseContent(response); + logger.warning("Error updating PLUGIN web hook"); + throw new FileNotFoundException("Resource " + request.getRequestUri() + " not found: " + errorMessage); + } + if (statusCode == HttpStatus.SC_NO_CONTENT) { + EntityUtils.consumeQuietly(response.getEntity()); + logger.warning("No response returned from PLUGIN rest call -> 204"); + } + String content = getResponseContent(response); + if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_CREATED) { + throw buildResponseException(response, content); + } + logger.warning("Response from PLUGIN rest call " + content); + } catch (FileNotFoundException | BitbucketRequestException e) { + throw e; + } catch (IOException e) { + throw new IOException("Communication error, requested URL: " + request, e); + } break; case NATIVE: @@ -695,7 +724,7 @@ public void updateCommitWebHook(BitbucketWebHook hook) throws IOException { .set("owner", getUserCentricOwner()) .set("repo", repositoryName) .set("id", hook.getUuid()) - .expand(), JsonParser.toString(hook) + .expand(), payload ); break; diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhook.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhook.java index 06cf3dc2f..92ccf8849 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhook.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhook.java @@ -25,10 +25,11 @@ import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook; +import com.cloudbees.jenkins.plugins.bitbucket.hooks.HookEventType; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; public class BitbucketPluginWebhook implements BitbucketWebHook { @@ -40,6 +41,19 @@ public class BitbucketPluginWebhook implements BitbucketWebHook { private String url; @JsonProperty("enabled") private boolean active; + private boolean tagCreated; + private boolean branchDeleted; + private boolean branchCreated; + private boolean repoPush; + private boolean prDeclined; + private boolean prRescoped; + private boolean prMerged; + private boolean prReopened; + private boolean prUpdated; + private boolean prCreated; + private boolean prCommented; + private boolean prDeleted; + private boolean repoMirrorSynced; @JsonInclude(JsonInclude.Include.NON_NULL) // If null, don't marshal to allow for backwards compatibility private String committersToIgnore; // Since Bitbucket Webhooks version 1.5.0 @@ -82,7 +96,64 @@ public void setActive(boolean active) { @Override @JsonIgnore public List getEvents() { - return Collections.emptyList(); + List events = new ArrayList<>(); + if (prCommented) { + events.add("prCommented"); + } + if (prCreated) { + events.add(HookEventType.SERVER_PULL_REQUEST_OPENED.getKey()); + } + if (prDeclined) { + events.add(HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey()); + } + if (prDeleted) { + events.add(HookEventType.SERVER_PULL_REQUEST_DELETED.getKey()); + } + if (prMerged) { + events.add(HookEventType.SERVER_PULL_REQUEST_MERGED.getKey()); + } + if (prReopened) { + events.add(HookEventType.SERVER_PULL_REQUEST_OPENED.getKey()); + } + if (prRescoped) { + events.add("prRescoped"); + } + if (prUpdated) { + events.add(HookEventType.SERVER_PULL_REQUEST_FROM_REF_UPDATED.getKey()); + } + if (repoMirrorSynced) { + events.add(HookEventType.SERVER_MIRROR_REPO_SYNCHRONIZED.getKey()); // not supported by the hookprocessor + } + if (repoPush) { + events.add(HookEventType.SERVER_REFS_CHANGED.getKey()); + } + if (tagCreated) { + events.add(HookEventType.SERVER_REFS_CHANGED.getKey()); + } + if (branchCreated) { + events.add(HookEventType.SERVER_REFS_CHANGED.getKey()); + } + if (branchDeleted) { + events.add(HookEventType.SERVER_REFS_CHANGED.getKey()); + } + return events; + } + + @JsonIgnore + public void setEvents(List events) { + prCommented = events.contains("prCommented"); + prCreated = events.contains(HookEventType.SERVER_PULL_REQUEST_OPENED.getKey()); + prDeclined = events.contains(HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey()); + prDeleted = events.contains(HookEventType.SERVER_PULL_REQUEST_DELETED.getKey()); + prMerged = events.contains(HookEventType.SERVER_PULL_REQUEST_MERGED.getKey()); + prReopened = prCreated; + prRescoped = events.contains("prRescoped"); + prUpdated = events.contains(HookEventType.SERVER_PULL_REQUEST_FROM_REF_UPDATED.getKey()); + repoMirrorSynced = events.contains(HookEventType.SERVER_MIRROR_REPO_SYNCHRONIZED.getKey()); // TODO not supported in hookprocessor + repoPush = events.contains(HookEventType.SERVER_REFS_CHANGED.getKey()); + tagCreated = repoPush; + branchCreated = repoPush; + branchDeleted = repoPush; } @Override @@ -99,4 +170,108 @@ public String getSecret() { return null; } + public boolean isTagCreated() { + return tagCreated; + } + + public void setTagCreated(boolean tagCreated) { + this.tagCreated = tagCreated; + } + + public boolean isBranchDeleted() { + return branchDeleted; + } + + public void setBranchDeleted(boolean branchDeleted) { + this.branchDeleted = branchDeleted; + } + + public boolean isBranchCreated() { + return branchCreated; + } + + public void setBranchCreated(boolean branchCreated) { + this.branchCreated = branchCreated; + } + + public boolean isRepoPush() { + return repoPush; + } + + public void setRepoPush(boolean repoPush) { + this.repoPush = repoPush; + } + + public boolean isPrDeclined() { + return prDeclined; + } + + public void setPrDeclined(boolean prDeclined) { + this.prDeclined = prDeclined; + } + + public boolean isPrRescoped() { + return prRescoped; + } + + public void setPrRescoped(boolean prRescoped) { + this.prRescoped = prRescoped; + } + + public boolean isPrMerged() { + return prMerged; + } + + public void setPrMerged(boolean prMerged) { + this.prMerged = prMerged; + } + + public boolean isPrReopened() { + return prReopened; + } + + public void setPrReopened(boolean prReopened) { + this.prReopened = prReopened; + } + + public boolean isPrUpdated() { + return prUpdated; + } + + public void setPrUpdated(boolean prUpdated) { + this.prUpdated = prUpdated; + } + + public boolean isPrCreated() { + return prCreated; + } + + public void setPrCreated(boolean prCreated) { + this.prCreated = prCreated; + } + + public boolean isPrCommented() { + return prCommented; + } + + public void setPrCommented(boolean prCommented) { + this.prCommented = prCommented; + } + + public boolean isPrDeleted() { + return prDeleted; + } + + public void setPrDeleted(boolean prDeleted) { + this.prDeleted = prDeleted; + } + + public boolean isRepoMirrorSynced() { + return repoMirrorSynced; + } + + public void setRepoMirrorSynced(boolean repoMirrorSynced) { + this.repoMirrorSynced = repoMirrorSynced; + } + } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketServerWebhook.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketServerWebhook.java index f348bab68..be729e892 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketServerWebhook.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketServerWebhook.java @@ -25,9 +25,11 @@ import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.ObjectUtils; public class BitbucketServerWebhook implements BitbucketWebHook { @@ -36,7 +38,7 @@ public class BitbucketServerWebhook implements BitbucketWebHook { @JsonProperty("name") private String description; private String url; - private List events; + private List events = new ArrayList<>(); private boolean active; @JsonProperty("configuration") private Map configuration = new HashMap<>(); @@ -74,7 +76,7 @@ public List getEvents() { } public void setEvents(List events) { - this.events = events; + this.events = ObjectUtils.firstNonNull(events, new ArrayList<>()); } @Override diff --git a/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhookTest.java b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhookTest.java new file mode 100644 index 000000000..859a58f56 --- /dev/null +++ b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketPluginWebhookTest.java @@ -0,0 +1,83 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Falco Nikolas + * + * 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.server.client.repository; + +import com.cloudbees.jenkins.plugins.bitbucket.hooks.HookEventType; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class BitbucketPluginWebhookTest { + + private BitbucketPluginWebhook sut; + + @BeforeEach + void setup() { + sut = new BitbucketPluginWebhook(); + } + + @Test + void test_getEvents() { + sut.setPrCommented(true); + sut.setTagCreated(true); + sut.setPrCreated(true); + sut.setPrDeclined(true); + sut.setPrDeleted(true); + sut.setPrMerged(true); + assertThat(sut.getEvents()).containsOnly( + "prCommented", + HookEventType.SERVER_REFS_CHANGED.getKey(), + HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey(), + HookEventType.SERVER_PULL_REQUEST_DELETED.getKey(), + HookEventType.SERVER_PULL_REQUEST_OPENED.getKey(), + HookEventType.SERVER_PULL_REQUEST_MERGED.getKey()); + } + + @Test + void test_setEvents() { + sut.setEvents(List.of( + HookEventType.SERVER_REFS_CHANGED.getKey(), + HookEventType.SERVER_MIRROR_REPO_SYNCHRONIZED.getKey(), + HookEventType.SERVER_PULL_REQUEST_OPENED.getKey(), + HookEventType.SERVER_PULL_REQUEST_FROM_REF_UPDATED.getKey(), + HookEventType.SERVER_PULL_REQUEST_DELETED.getKey(), + HookEventType.SERVER_PULL_REQUEST_DECLINED.getKey(), + HookEventType.SERVER_PULL_REQUEST_MERGED.getKey())); + + assertThat(sut.isPrCreated()).isTrue(); + assertThat(sut.isPrDeclined()).isTrue(); + assertThat(sut.isPrCommented()).isFalse(); + assertThat(sut.isPrMerged()).isTrue(); + assertThat(sut.isPrReopened()).isTrue(); + assertThat(sut.isPrRescoped()).isFalse(); + assertThat(sut.isPrUpdated()).isTrue(); + assertThat(sut.isBranchCreated()).isTrue(); + assertThat(sut.isBranchDeleted()).isTrue(); + assertThat(sut.isRepoMirrorSynced()).isTrue(); + assertThat(sut.isRepoPush()).isTrue(); + assertThat(sut.isTagCreated()).isTrue(); + } +}