Skip to content

Commit 4b9b005

Browse files
adammitchellplaytechadam.mitchelllifeofguenter
authored
Organisation Folder Scan - newly discovered repositories are now processed first (#599)
* process new repositories first * extra safety check + test Co-authored-by: adam.mitchell <[email protected]> Co-authored-by: Günter Grodotzki <[email protected]>
1 parent 6cc5419 commit 4b9b005

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@
2626
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRepository;
2727
import edu.umd.cs.findbugs.annotations.NonNull;
2828
import java.util.Collection;
29+
import java.util.LinkedHashSet;
2930
import java.util.List;
3031
import java.util.Map;
32+
import java.util.Set;
3133
import java.util.TreeMap;
34+
import java.util.stream.Collectors;
3235
import jenkins.scm.api.SCMNavigator;
3336
import jenkins.scm.api.SCMSourceObserver;
3437
import jenkins.scm.api.trait.SCMNavigatorRequest;
@@ -45,6 +48,11 @@ public class BitbucketSCMNavigatorRequest extends SCMNavigatorRequest {
4548
*/
4649
private final Map<String, BitbucketRepository> repositoryMap = new TreeMap<>();
4750

51+
/**
52+
* keep a reference to the observer so we can cross-reference
53+
*/
54+
private final SCMSourceObserver observer;
55+
4856
/**
4957
* Constructor.
5058
*
@@ -56,6 +64,7 @@ protected BitbucketSCMNavigatorRequest(@NonNull SCMNavigator source,
5664
@NonNull BitbucketSCMNavigatorContext context,
5765
@NonNull SCMSourceObserver observer) {
5866
super(source, context, observer);
67+
this.observer = observer;
5968
}
6069

6170
public void withRepositories(List<? extends BitbucketRepository> repositories) {
@@ -66,7 +75,20 @@ public void withRepositories(List<? extends BitbucketRepository> repositories) {
6675
}
6776

6877
public Collection<BitbucketRepository> repositories() {
69-
return this.repositoryMap.values();
78+
final List<String> existingRepositories = this.observer.getContext().getSCMSources().stream()
79+
.filter(BitbucketSCMSource.class::isInstance)
80+
.map(BitbucketSCMSource.class::cast)
81+
.map(BitbucketSCMSource::getRepository)
82+
.collect(Collectors.toList());
83+
// process new repositories first
84+
final Set<BitbucketRepository> newRepositories = this.repositoryMap.entrySet()
85+
.stream()
86+
.filter(e -> !existingRepositories.contains(e.getKey()))
87+
.map(Map.Entry::getValue)
88+
.collect(Collectors.toCollection(LinkedHashSet::new));
89+
// add remaining repositories back in. duplicates will be rejected
90+
newRepositories.addAll(this.repositoryMap.values());
91+
return newRepositories;
7092
}
7193

7294
public BitbucketRepository getBitbucketRepository(String repositoryName) {

src/test/java/com/cloudbees/jenkins/plugins/bitbucket/SCMNavigatorTest.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,26 @@
2323
*/
2424
package com.cloudbees.jenkins.plugins.bitbucket;
2525

26+
import com.google.common.collect.ImmutableList;
2627
import edu.umd.cs.findbugs.annotations.NonNull;
2728
import hudson.model.TaskListener;
2829
import java.io.IOException;
2930
import java.util.ArrayList;
31+
import java.util.Collections;
3032
import java.util.List;
3133
import jenkins.scm.api.SCMSource;
3234
import jenkins.scm.api.SCMSourceObserver;
3335
import jenkins.scm.api.SCMSourceObserver.ProjectObserver;
3436
import jenkins.scm.api.SCMSourceOwner;
37+
import jenkins.scm.impl.NullSCMSource;
3538
import org.junit.ClassRule;
3639
import org.junit.Test;
3740
import org.jvnet.hudson.test.JenkinsRule;
3841
import org.mockito.Mockito;
3942

4043
import static org.junit.Assert.assertEquals;
4144
import static org.junit.Assert.assertTrue;
45+
import static org.mockito.Mockito.when;
4246

4347
public class SCMNavigatorTest {
4448

@@ -52,8 +56,10 @@ public void teamRepositoriesDiscovering() throws IOException, InterruptedExcepti
5256
BitbucketSCMNavigator navigator = new BitbucketSCMNavigator("myteam", null, null);
5357
navigator.setPattern("repo(.*)");
5458
navigator.setBitbucketServerUrl("http://bitbucket.test");
59+
final SCMSourceOwner mock = Mockito.mock(SCMSourceOwner.class);
60+
when(mock.getSCMSources()).thenReturn(Collections.singletonList(new BitbucketSCMSource("myteam", "repo1")));
5561
SCMSourceObserverImpl observer = new SCMSourceObserverImpl(BitbucketClientMockUtils.getTaskListenerMock(),
56-
Mockito.mock(SCMSourceOwner.class));
62+
mock);
5763
navigator.visitSources(observer);
5864

5965
assertEquals("myteam", navigator.getRepoOwner());
@@ -62,8 +68,44 @@ public void teamRepositoriesDiscovering() throws IOException, InterruptedExcepti
6268
List<String> observed = observer.getObserved();
6369
// Only 2 repositories match the pattern
6470
assertEquals("There must be 2 repositories in the team", 2, observed.size());
65-
assertEquals("repo1", observed.get(0));
66-
assertEquals("repo2", observed.get(1));
71+
assertEquals("repo2 should be first", "repo2", observed.get(0));
72+
assertEquals("repo1 should be second", "repo1", observed.get(1));
73+
74+
List<ProjectObserver> observers = observer.getProjectObservers();
75+
for (ProjectObserver obs : observers) {
76+
List<SCMSource> sources = ((SCMSourceObserverImpl.ProjectObserverImpl) obs).getSources();
77+
// It should contain only one source
78+
assertEquals("Only one source must be created per observed repository", 1, sources.size());
79+
SCMSource scmSource = sources.get(0);
80+
assertTrue("BitbucketSCMSource instances must be added", scmSource instanceof BitbucketSCMSource);
81+
// Check correct repoOwner (team name in this case) was set
82+
assertEquals(((BitbucketSCMSource) scmSource).getRepoOwner(), "myteam");
83+
}
84+
}
85+
86+
@Test
87+
public void teamRepositoriesDiscoveringNullSource() throws IOException, InterruptedException {
88+
BitbucketMockApiFactory.add("http://bitbucket.test",
89+
BitbucketClientMockUtils.getAPIClientMock(true, false));
90+
BitbucketSCMNavigator navigator = new BitbucketSCMNavigator("myteam", null, null);
91+
navigator.setPattern("repo(.*)");
92+
navigator.setBitbucketServerUrl("http://bitbucket.test");
93+
final SCMSourceOwner mock = Mockito.mock(SCMSourceOwner.class);
94+
when(mock.getSCMSources())
95+
.thenReturn(ImmutableList.of(new BitbucketSCMSource("myteam", "repo1"),
96+
new NullSCMSource()));
97+
SCMSourceObserverImpl observer = new SCMSourceObserverImpl(BitbucketClientMockUtils.getTaskListenerMock(),
98+
mock);
99+
navigator.visitSources(observer);
100+
101+
assertEquals("myteam", navigator.getRepoOwner());
102+
assertEquals("repo(.*)", navigator.getPattern());
103+
104+
List<String> observed = observer.getObserved();
105+
// Only 2 repositories match the pattern
106+
assertEquals("There must be 2 repositories in the team", 2, observed.size());
107+
assertEquals("repo2 should be first", "repo2", observed.get(0));
108+
assertEquals("repo1 should be second", "repo1", observed.get(1));
67109

68110
List<ProjectObserver> observers = observer.getProjectObservers();
69111
for (ProjectObserver obs : observers) {

0 commit comments

Comments
 (0)