Skip to content

Commit 0e0a8e7

Browse files
tariochDohbedohbitwiseman
authored
Avoid fetching all PRs (#445)
* Do not add PRs if event doesn't match repo * Reuse PR information from Bitbucket webhook events fixes #443 * Do not return pull requests for deleted/declined prs * Fetch single PR by id instead of fetching all and then filtering * [JENKINS-65719] Integrate PR setup in getById * [JENKINS-65719] unused imports and checkstyle Co-authored-by: Allan Burdajewicz <allan.burdajewicz@gmail.com> Co-authored-by: Liam Newman <bitwiseman@gmail.com>
1 parent d49972b commit 0e0a8e7

File tree

10 files changed

+595
-213
lines changed

10 files changed

+595
-213
lines changed

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

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint;
4141
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint;
4242
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration;
43+
import com.cloudbees.jenkins.plugins.bitbucket.hooks.HasPullRequests;
4344
import com.cloudbees.plugins.credentials.CredentialsNameProvider;
4445
import com.cloudbees.plugins.credentials.CredentialsProvider;
4546
import com.cloudbees.plugins.credentials.common.StandardCredentials;
@@ -550,6 +551,11 @@ protected void retrieve(@CheckForNull SCMSourceCriteria criteria, @NonNull SCMHe
550551
@Override
551552
protected Iterable<BitbucketPullRequest> create() {
552553
try {
554+
if (event instanceof HasPullRequests) {
555+
HasPullRequests hasPrEvent = (HasPullRequests) event;
556+
return hasPrEvent.getPullRequests(BitbucketSCMSource.this);
557+
}
558+
553559
return (Iterable<BitbucketPullRequest>) buildBitbucketClient().getPullRequests();
554560
} catch (IOException | InterruptedException e) {
555561
throw new BitbucketSCMSource.WrappedException(e);
@@ -802,8 +808,13 @@ protected SCMRevision retrieve(SCMHead head, TaskListener listener) throws IOExc
802808
: buildBitbucketClient(h).getBranches();
803809
sourceRevision = findCommit(h.getBranchName(), branches, listener);
804810
} else {
805-
final List<? extends BitbucketPullRequest> pullRequests = bitbucket.getPullRequests();
806-
sourceRevision = findPRCommit(h.getId(), pullRequests, listener);
811+
try {
812+
BitbucketPullRequest pr = bitbucket.getPullRequestById(Integer.parseInt(h.getId()));
813+
sourceRevision = findPRCommit(pr, listener);
814+
} catch (NumberFormatException nfe) {
815+
LOGGER.log(Level.WARNING, "Cannot parse the PR id {0}", h.getId());
816+
sourceRevision = null;
817+
}
807818
}
808819
if (sourceRevision == null) {
809820
LOGGER.log(Level.WARNING, "No revision found in {0}/{1} for PR-{2} [{3}]",
@@ -840,7 +851,7 @@ protected SCMRevision retrieve(SCMHead head, TaskListener listener) throws IOExc
840851
}
841852
}
842853

843-
private BitbucketCommit findCommit(String branchName, List<? extends BitbucketBranch> branches, TaskListener listener) {
854+
private BitbucketCommit findCommit(@NonNull String branchName, List<? extends BitbucketBranch> branches, TaskListener listener) {
844855
for (final BitbucketBranch b : branches) {
845856
if (branchName.equals(b.getName())) {
846857
String revision = b.getRawNode();
@@ -862,28 +873,22 @@ private BitbucketCommit findCommit(String branchName, List<? extends BitbucketBr
862873
return null;
863874
}
864875

865-
private BitbucketCommit findPRCommit(String prId, List<? extends BitbucketPullRequest> pullRequests, TaskListener listener) {
866-
for (BitbucketPullRequest pr : pullRequests) {
867-
if (prId.equals(pr.getId())) {
868-
// if I use getCommit() the branch closure is trigger immediately
869-
BitbucketBranch branch = pr.getSource().getBranch();
870-
String hash = branch.getRawNode();
871-
if (hash == null) {
872-
if (BitbucketCloudEndpoint.SERVER_URL.equals(getServerUrl())) {
873-
listener.getLogger().format("Cannot resolve the hash of the revision in PR-%s%n",
874-
prId);
875-
} else {
876-
listener.getLogger().format("Cannot resolve the hash of the revision in PR-%s. "
877-
+ "Perhaps you are using Bitbucket Server previous to 4.x%n",
878-
prId);
879-
}
880-
return null;
881-
}
882-
return new BranchHeadCommit(branch);
876+
private BitbucketCommit findPRCommit(BitbucketPullRequest pr, TaskListener listener) {
877+
// if I use getCommit() the branch closure is trigger immediately
878+
BitbucketBranch branch = pr.getSource().getBranch();
879+
String hash = branch.getRawNode();
880+
if (hash == null) {
881+
if (BitbucketCloudEndpoint.SERVER_URL.equals(getServerUrl())) {
882+
listener.getLogger().format("Cannot resolve the hash of the revision in PR-%s%n",
883+
pr.getId());
884+
} else {
885+
listener.getLogger().format("Cannot resolve the hash of the revision in PR-%s. "
886+
+ "Perhaps you are using Bitbucket Server previous to 4.x%n",
887+
pr.getId());
883888
}
889+
return null;
884890
}
885-
listener.getLogger().format("Cannot find the PR-%s%n", prId);
886-
return null;
891+
return new BranchHeadCommit(branch);
887892
}
888893

889894
@Override

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClient.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,7 @@ public List<BitbucketPullRequestValue> getPullRequests() throws InterruptedExcep
298298
} while (page.getNext() != null);
299299

300300
// PRs with missing destination branch are invalid and should be ignored.
301-
pullRequests.removeIf(pr -> pr.getSource().getRepository() == null
302-
|| pr.getSource().getCommit() == null
303-
|| pr.getDestination().getBranch() == null
304-
|| pr.getDestination().getCommit() == null);
301+
pullRequests.removeIf(this::shouldIgnore);
305302

306303
for (BitbucketPullRequestValue pullRequest : pullRequests) {
307304
setupClosureForPRBranch(pullRequest);
@@ -310,6 +307,19 @@ public List<BitbucketPullRequestValue> getPullRequests() throws InterruptedExcep
310307
return pullRequests;
311308
}
312309

310+
/**
311+
* PRs with missing source / destination branch are invalid and should be ignored.
312+
*
313+
* @param pr a {@link BitbucketPullRequest}
314+
* @return
315+
*/
316+
private boolean shouldIgnore(BitbucketPullRequest pr) {
317+
return pr.getSource().getRepository() == null
318+
|| pr.getSource().getCommit() == null
319+
|| pr.getDestination().getBranch() == null
320+
|| pr.getDestination().getCommit() == null;
321+
}
322+
313323
/**
314324
* Make available commit informations in a lazy way.
315325
*

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.List;
4040
import java.util.ListIterator;
4141
import java.util.Locale;
42+
import java.util.Optional;
4243
import java.util.Set;
4344
import jenkins.model.GlobalConfiguration;
4445
import jenkins.model.Jenkins;
@@ -265,6 +266,21 @@ public synchronized AbstractBitbucketEndpoint findEndpoint(@CheckForNull String
265266
return null;
266267
}
267268

269+
/**
270+
* Checks to see if the supplied server URL is defined in the global configuration.
271+
*
272+
* @param serverUrl the server url to check.
273+
* @param clazz
274+
* @return the global configuration for the specified server url or {@code null} if not defined.
275+
*/
276+
public synchronized Optional<AbstractBitbucketEndpoint> findEndpoint(@CheckForNull String serverUrl,
277+
Class<? extends AbstractBitbucketEndpoint> clazz) {
278+
return getEndpoints().stream()
279+
.filter(clazz::isInstance)
280+
.filter(endpoint -> normalizeServerUrl(serverUrl).equals(endpoint.getServerUrl()))
281+
.findFirst();
282+
}
283+
268284
/**
269285
* Fix a serverUrl.
270286
*
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.cloudbees.jenkins.plugins.bitbucket.hooks;
2+
3+
4+
import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource;
5+
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketPullRequest;
6+
7+
public interface HasPullRequests {
8+
9+
Iterable<BitbucketPullRequest> getPullRequests(BitbucketSCMSource src) throws InterruptedException;
10+
11+
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void process(HookEventType hookEvent, String payload, BitbucketType insta
9393
SCMHeadEvent.fireNow(new HeadEvent(serverUrl, eventType, pullRequestEvent, origin));
9494
}
9595

96-
private static final class HeadEvent extends NativeServerHeadEvent<NativeServerPullRequestEvent> {
96+
private static final class HeadEvent extends NativeServerHeadEvent<NativeServerPullRequestEvent> implements HasPullRequests {
9797
private HeadEvent(String serverUrl, Type type, NativeServerPullRequestEvent payload, String origin) {
9898
super(serverUrl, type, payload, origin);
9999
}
@@ -152,5 +152,13 @@ protected Map<SCMHead, SCMRevision> heads(@NonNull BitbucketSCMSource source) {
152152

153153
return result;
154154
}
155+
156+
@Override
157+
public Iterable<BitbucketPullRequest> getPullRequests(BitbucketSCMSource src) throws InterruptedException {
158+
if (Type.REMOVED.equals(getType())) {
159+
return Collections.emptySet();
160+
}
161+
return Collections.singleton(getPayload().getPullRequest());
162+
}
155163
}
156164
}

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.cloudbees.jenkins.plugins.bitbucket.JsonParser;
3131
import com.cloudbees.jenkins.plugins.bitbucket.PullRequestSCMHead;
3232
import com.cloudbees.jenkins.plugins.bitbucket.PullRequestSCMRevision;
33+
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketPullRequest;
3334
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRepositoryType;
3435
import com.cloudbees.jenkins.plugins.bitbucket.server.client.BitbucketServerAPIClient;
3536
import com.cloudbees.jenkins.plugins.bitbucket.server.client.pullrequest.BitbucketServerPullRequest;
@@ -42,8 +43,10 @@
4243
import edu.umd.cs.findbugs.annotations.NonNull;
4344
import java.io.FileNotFoundException;
4445
import java.io.IOException;
46+
import java.util.ArrayList;
4547
import java.util.Collection;
4648
import java.util.HashMap;
49+
import java.util.List;
4750
import java.util.Map;
4851
import java.util.Objects;
4952
import java.util.Set;
@@ -111,7 +114,7 @@ public void process(HookEventType hookEvent, String payload, BitbucketType insta
111114
}
112115
}
113116

114-
private static final class HeadEvent extends NativeServerHeadEvent<Collection<NativeServerRefsChangedEvent.Change>> {
117+
private static final class HeadEvent extends NativeServerHeadEvent<Collection<NativeServerRefsChangedEvent.Change>> implements HasPullRequests {
115118
private final NativeServerRefsChangedEvent refsChangedEvent;
116119
private final Map<CacheKey, Map<String, BitbucketServerPullRequest>> cachedPullRequests = new HashMap<>();
117120

@@ -129,6 +132,10 @@ protected BitbucketServerRepository getRepository() {
129132
@Override
130133
protected Map<SCMHead, SCMRevision> heads(BitbucketSCMSource source) {
131134
final Map<SCMHead, SCMRevision> result = new HashMap<>();
135+
if (!eventMatchesRepo(source)) {
136+
return result;
137+
}
138+
132139
addBranchesAndTags(source, result);
133140
try {
134141
addPullRequests(source, result);
@@ -139,10 +146,6 @@ protected Map<SCMHead, SCMRevision> heads(BitbucketSCMSource source) {
139146
}
140147

141148
private void addBranchesAndTags(BitbucketSCMSource src, Map<SCMHead, SCMRevision> result) {
142-
if (!eventMatchesRepo(src)) {
143-
return;
144-
}
145-
146149
for (final NativeServerRefsChangedEvent.Change change : getPayload()) {
147150
String refType = change.getRef().getType();
148151

@@ -272,6 +275,17 @@ private Map<String, BitbucketServerPullRequest> loadPullRequests(BitbucketSCMSou
272275

273276
return pullRequests;
274277
}
278+
279+
@Override
280+
public Collection<BitbucketPullRequest> getPullRequests(BitbucketSCMSource src) throws InterruptedException {
281+
List<BitbucketPullRequest> prs = new ArrayList<>();
282+
for (final NativeServerRefsChangedEvent.Change change : getPayload()) {
283+
Map<String, BitbucketServerPullRequest> prsForChange = getPullRequests(src, change);
284+
prs.addAll(prsForChange.values());
285+
}
286+
287+
return prs;
288+
}
275289
}
276290

277291
private static final class CacheKey {

0 commit comments

Comments
 (0)