Skip to content

Commit ec79d73

Browse files
authored
[JENKINS-76108] Alternative for setManageHooks (#1119)
Add new API interfaces to lookup builder used to instantiate a BitbucketWebhookConfiguration.
1 parent 3258c71 commit ec79d73

12 files changed

+562
-4
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/endpoint/BitbucketEndpointProvider.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import com.cloudbees.jenkins.plugins.bitbucket.api.webhook.BitbucketWebhookConfiguration;
2727
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration;
28+
import com.cloudbees.jenkins.plugins.bitbucket.impl.endpoint.AbstractBitbucketEndpoint;
2829
import com.cloudbees.jenkins.plugins.bitbucket.impl.endpoint.BitbucketCloudEndpoint;
2930
import com.cloudbees.jenkins.plugins.bitbucket.impl.endpoint.BitbucketServerEndpoint;
3031
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
@@ -171,6 +172,27 @@ public static BitbucketEndpoint registerEndpoint(@NonNull String name, @NonNull
171172
return endpoint;
172173
}
173174

175+
/**
176+
* Register a new {@link BitbucketEndpoint} to the global configuration. The
177+
* endpoint is created with default values and could be customised by the
178+
* given endpointCustomiser.
179+
* <p>
180+
* The given customiser can also return a different implementation
181+
*
182+
* @param name of the endpoint, alias for label
183+
* @param serverURL the bitbucket endpoint URL
184+
* @param webhook configuration
185+
* @param endpointCustomiser an optional customiser for the created endpoint
186+
* @return the registered endpoint instance.
187+
*/
188+
public static BitbucketEndpoint registerEndpoint(@NonNull String name, @NonNull String serverURL, @NonNull BitbucketWebhookConfiguration webhook, @Nullable UnaryOperator<BitbucketEndpoint> endpointCustomiser) {
189+
BitbucketEndpoint endpoint = registerEndpoint(name, serverURL, endpointCustomiser);
190+
if (endpoint instanceof AbstractBitbucketEndpoint ep) {
191+
ep.setWebhook(webhook);
192+
}
193+
return endpoint;
194+
}
195+
174196
/**
175197
* Removes a {@link BitbucketEndpoint} that matches the given URl from the
176198
* global configuration.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
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.api.webhook;
25+
26+
import edu.umd.cs.findbugs.annotations.NonNull;
27+
import hudson.ExtensionPoint;
28+
import org.kohsuke.accmod.Restricted;
29+
import org.kohsuke.accmod.restrictions.Beta;
30+
31+
/**
32+
* Base interface that a builder must implement or extend to provide an instance
33+
* of {@link BitbucketWebhookConfiguration}.
34+
*
35+
* @since 937.1.0
36+
*/
37+
@Restricted(Beta.class)
38+
public interface BitbucketWebhookConfigurationBuilder extends ExtensionPoint {
39+
40+
/**
41+
* Returns the identifier of built {@link BitbucketWebhookConfiguration}.
42+
*
43+
* @return configuration identifier
44+
* @see BitbucketWebhookConfiguration#getId()
45+
*/
46+
@NonNull
47+
String getId();
48+
49+
/**
50+
* Enable the auto manage of webhook for each repository in a Jenkins
51+
* project.
52+
*
53+
* @param credentialsId with admin right to add, update or delete webhook of
54+
* a bitbucket repository
55+
* @return builder itself
56+
*/
57+
BitbucketWebhookConfigurationBuilder autoManaged(@NonNull String credentialsId);
58+
59+
/**
60+
* Set the Jenkins root URL used to send event payload.
61+
*
62+
* @param callbackRootURL URL of Jenkins accessible from the Bitbucket
63+
* server instance.
64+
* @return builder itself
65+
*/
66+
BitbucketWebhookConfigurationBuilder callbackRootURL(@NonNull String callbackRootURL);
67+
68+
/**
69+
* Returns an instance of {@link BitbucketWebhookConfiguration} using the
70+
* provided configuration.
71+
*
72+
* @return instance of {@link BitbucketWebhookConfiguration}
73+
*/
74+
BitbucketWebhookConfiguration build();
75+
76+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
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.api.webhook;
25+
26+
import com.google.common.base.Objects;
27+
import edu.umd.cs.findbugs.annotations.NonNull;
28+
import edu.umd.cs.findbugs.annotations.Nullable;
29+
import hudson.ExtensionList;
30+
import org.kohsuke.accmod.Restricted;
31+
import org.kohsuke.accmod.restrictions.Beta;
32+
33+
/**
34+
* Provider of {@link BitbucketWebhookConfiguration} builders registered in the
35+
* system.
36+
*
37+
* @since 937.1.0
38+
*/
39+
@Restricted(Beta.class)
40+
public final class BitbucketWebhookConfigurationsBuilder {
41+
42+
private BitbucketWebhookConfigurationsBuilder() {
43+
}
44+
45+
/**
46+
* Returns a {@link BitbucketWebhookConfiguration} builder for the given
47+
* configuration identifier.
48+
*
49+
* @param <T> specific builder interface
50+
* @param id webhook configuration identifier
51+
* @param builderInterface class of specific builder
52+
* @return an instance of {@link BitbucketWebhookConfigurationBuilder},
53+
* {@code null} otherwise if no builder found with the given
54+
* paramenters.
55+
*/
56+
@Nullable
57+
public static <T extends BitbucketWebhookConfigurationBuilder> T lookup(@NonNull String id, Class<T> builderInterface) {
58+
return ExtensionList.lookup(builderInterface) //
59+
.stream() //
60+
.filter(provider -> Objects.equal(id, provider.getId())) //
61+
.findFirst() //
62+
.orElse(null);
63+
}
64+
65+
/**
66+
* Returns a {@link BitbucketWebhookConfiguration} builder for the given
67+
* configuration identifier.
68+
*
69+
* @param id webhook configuration identifier
70+
* @return an instance of {@link BitbucketWebhookConfigurationBuilder},
71+
* {@code null} otherwise if no builder found.
72+
*/
73+
@Nullable
74+
public static BitbucketWebhookConfigurationBuilder lookup(@NonNull String id) {
75+
return lookup(id, BitbucketWebhookConfigurationBuilder.class);
76+
}
77+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
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.api.webhook;
25+
26+
import edu.umd.cs.findbugs.annotations.NonNull;
27+
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
28+
29+
/**
30+
* This interface is intended for webhooks to meet the configuration
31+
* specifications provided natively with Atlassian products.
32+
*/
33+
public interface NativeBitbucketWebhookConfigurationBuilder extends BitbucketWebhookConfigurationBuilder {
34+
35+
/**
36+
* Enable the payload signature verification using the given
37+
* {@link StringCredentials}.
38+
*
39+
* @param credentialsId used to verify the signature sent with in payload
40+
* @return the builder that can be used to customise a new instance of
41+
* {@link BitbucketWebhookConfiguration}.
42+
*/
43+
NativeBitbucketWebhookConfigurationBuilder signature(@NonNull String credentialsId);
44+
45+
}

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/endpoint/BitbucketCloudEndpoint.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import java.util.Collection;
3939
import java.util.List;
4040
import jenkins.model.Jenkins;
41+
import org.kohsuke.accmod.Restricted;
42+
import org.kohsuke.accmod.restrictions.NoExternalUse;
4143
import org.kohsuke.stapler.DataBoundConstructor;
4244
import org.kohsuke.stapler.interceptor.RequirePOST;
4345
import org.kohsuke.stapler.verb.POST;
@@ -73,7 +75,17 @@ public class BitbucketCloudEndpoint extends AbstractBitbucketEndpoint {
7375
* Default constructor.
7476
*/
7577
public BitbucketCloudEndpoint() {
76-
this(false, 0, 0, new CloudWebhookConfiguration(false, null, false, null));
78+
this(new CloudWebhookConfiguration(false, null, false, null));
79+
}
80+
81+
/**
82+
* Internal Constructor.
83+
*
84+
* @param webhook configuration
85+
*/
86+
@Restricted(NoExternalUse.class)
87+
public BitbucketCloudEndpoint(BitbucketWebhookConfiguration webhook) {
88+
this(false, 0, 0, webhook);
7789
}
7890

7991
/**
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
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.impl.webhook;
25+
26+
import com.cloudbees.jenkins.plugins.bitbucket.api.webhook.BitbucketWebhookConfigurationBuilder;
27+
import com.cloudbees.jenkins.plugins.bitbucket.api.webhook.NativeBitbucketWebhookConfigurationBuilder;
28+
import edu.umd.cs.findbugs.annotations.NonNull;
29+
import org.kohsuke.accmod.Restricted;
30+
import org.kohsuke.accmod.restrictions.NoExternalUse;
31+
32+
@Restricted(NoExternalUse.class)
33+
public abstract class AbstractBitbucketWebhookConfigurationBuilderImpl implements NativeBitbucketWebhookConfigurationBuilder {
34+
35+
protected String credentialsId;
36+
protected String signatureId;
37+
protected String callbackRootURL;
38+
39+
@Override
40+
public NativeBitbucketWebhookConfigurationBuilder autoManaged(@NonNull String credentialsId) {
41+
this.credentialsId = credentialsId;
42+
return this;
43+
}
44+
45+
@Override
46+
public NativeBitbucketWebhookConfigurationBuilder signature(@NonNull String credentialsId) {
47+
this.signatureId = credentialsId;
48+
return this;
49+
}
50+
51+
@NonNull
52+
@Override
53+
public BitbucketWebhookConfigurationBuilder callbackRootURL(String callbackRootURL) {
54+
this.callbackRootURL = callbackRootURL;
55+
return this;
56+
}
57+
58+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
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.impl.webhook.cloud;
25+
26+
import com.cloudbees.jenkins.plugins.bitbucket.impl.webhook.AbstractBitbucketWebhookConfigurationBuilderImpl;
27+
import edu.umd.cs.findbugs.annotations.NonNull;
28+
import hudson.Extension;
29+
30+
@Extension
31+
public class CloudWebhookConfigurationBuilderImpl extends AbstractBitbucketWebhookConfigurationBuilderImpl {
32+
33+
@NonNull
34+
@Override
35+
public String getId() {
36+
return "CLOUD_NATIVE";
37+
}
38+
39+
@NonNull
40+
@Override
41+
public CloudWebhookConfiguration build() {
42+
CloudWebhookConfiguration configuration = new CloudWebhookConfiguration(
43+
credentialsId != null, credentialsId,
44+
signatureId != null, signatureId);
45+
configuration.setEndpointJenkinsRootURL(callbackRootURL);
46+
return configuration;
47+
}
48+
49+
}

0 commit comments

Comments
 (0)