2424
2525package com .cloudbees .jenkins .plugins .bitbucket ;
2626
27+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketApi ;
28+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketBranch ;
29+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketCommit ;
30+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketHref ;
31+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketRepository ;
32+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketRepositoryProtocol ;
33+ import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketRepositoryType ;
34+ import com .cloudbees .jenkins .plugins .bitbucket .endpoints .BitbucketCloudEndpoint ;
35+ import com .cloudbees .jenkins .plugins .bitbucket .filesystem .BitbucketSCMFile ;
2736import hudson .model .Action ;
2837import hudson .model .FreeStyleBuild ;
2938import hudson .model .FreeStyleProject ;
39+ import hudson .model .Result ;
40+ import hudson .model .TaskListener ;
41+ import java .io .ByteArrayInputStream ;
42+ import java .io .IOException ;
43+ import java .net .URL ;
44+ import java .util .Collections ;
3045import java .util .List ;
46+ import jenkins .branch .BranchSource ;
47+ import jenkins .plugins .git .GitSampleRepoRule ;
48+ import jenkins .scm .api .SCMSource ;
49+ import jenkins .scm .api .SCMSourceCriteria ;
50+ import org .jenkinsci .plugins .workflow .cps .CpsFlowDefinition ;
51+ import org .jenkinsci .plugins .workflow .flow .FlowDefinition ;
52+ import org .jenkinsci .plugins .workflow .job .WorkflowJob ;
53+ import org .jenkinsci .plugins .workflow .job .WorkflowRun ;
54+ import org .jenkinsci .plugins .workflow .multibranch .AbstractWorkflowBranchProjectFactory ;
55+ import org .jenkinsci .plugins .workflow .multibranch .WorkflowMultiBranchProject ;
56+ import org .junit .ClassRule ;
3157import org .junit .Rule ;
3258import org .junit .Test ;
59+ import org .jvnet .hudson .test .BuildWatcher ;
60+ import org .jvnet .hudson .test .Issue ;
3361import org .jvnet .hudson .test .JenkinsRule ;
3462import org .jvnet .hudson .test .SingleFileSCM ;
63+ import org .mockito .Mockito ;
64+ import org .mockito .internal .stubbing .answers .Returns ;
3565
3666import static org .hamcrest .MatcherAssert .assertThat ;
3767import static org .hamcrest .Matchers .hasItem ;
3868import static org .hamcrest .Matchers .instanceOf ;
69+ import static org .hamcrest .Matchers .is ;
3970import static org .hamcrest .Matchers .not ;
71+ import static org .mockito .Matchers .any ;
72+ import static org .mockito .Matchers .anyString ;
73+ import static org .mockito .Matchers .eq ;
74+ import static org .mockito .Mockito .when ;
4075
4176public class BitbucketBuildStatusNotificationsTest {
4277
78+ @ ClassRule
79+ public static BuildWatcher buildWatcher = new BuildWatcher ();
4380 @ Rule
44- public JenkinsRule r = new JenkinsRule ();
81+ public JenkinsRule r = new JenkinsRule () {
82+ @ Override
83+ public URL getURL () throws IOException {
84+ return new URL ("http://example.com:" + localPort + contextPath + "/" );
85+ }
86+ };
87+ @ Rule
88+ public GitSampleRepoRule sampleRepo = new GitSampleRepoRule ();
4589
4690 // TODO test of effectiveness of FirstCheckoutCompletedInvisibleAction (#130)
4791
@@ -50,7 +94,114 @@ public void noInappropriateFirstCheckoutCompletedInvisibleAction() throws Except
5094 FreeStyleProject p = r .createFreeStyleProject ();
5195 p .setScm (new SingleFileSCM ("file" , "contents" ));
5296 FreeStyleBuild b = r .buildAndAssertSuccess (p );
53- assertThat ((List <Action >)b .getAllActions (), not (hasItem (instanceOf (FirstCheckoutCompletedInvisibleAction .class ))));
97+ assertThat ((List <Action >) b .getAllActions (), not (hasItem (instanceOf (FirstCheckoutCompletedInvisibleAction .class ))));
98+ }
99+
100+ private WorkflowMultiBranchProject prepareFirstCheckoutCompletedInvisibleActionTest (String dsl ) throws Exception {
101+ String repoOwner = "bob" ;
102+ String repositoryName = "foo" ;
103+ String branchName = "master" ;
104+ String jenkinsfile = "Jenkinsfile" ;
105+ sampleRepo .init ();
106+ sampleRepo .write (jenkinsfile , dsl );
107+ sampleRepo .git ("add" , jenkinsfile );
108+ sampleRepo .git ("commit" , "--all" , "--message=defined" );
109+
110+ BitbucketApi api = Mockito .mock (BitbucketApi .class );
111+ BitbucketBranch branch = Mockito .mock (BitbucketBranch .class );
112+ List <? extends BitbucketBranch > branchList = Collections .singletonList (branch );
113+ when (api .getBranches ()).thenAnswer (new Returns (branchList ));
114+ when (branch .getName ()).thenReturn (branchName );
115+ when (branch .getRawNode ()).thenReturn (sampleRepo .head ());
116+ BitbucketCommit commit = Mockito .mock (BitbucketCommit .class );
117+ when (api .resolveCommit (sampleRepo .head ())).thenReturn (commit );
118+ when (commit .getDateMillis ()).thenReturn (System .currentTimeMillis ());
119+ when (api .checkPathExists (Mockito .anyString (), eq (jenkinsfile ))).thenReturn (true );
120+ when (api .getRepositoryUri (eq (BitbucketRepositoryType .GIT ),
121+ any (BitbucketRepositoryProtocol .class ),
122+ anyString (),
123+ eq (repoOwner ),
124+ eq (repositoryName )))
125+ .thenReturn (sampleRepo .fileUrl ());
126+ BitbucketRepository repository = Mockito .mock (BitbucketRepository .class );
127+ when (api .getRepository ()).thenReturn (repository );
128+ when (repository .getOwnerName ()).thenReturn (repoOwner );
129+ when (repository .getRepositoryName ()).thenReturn (repositoryName );
130+ when (repository .getScm ()).thenReturn ("git" );
131+ when (repository .getLinks ()).thenReturn (
132+ Collections .singletonMap ("clone" ,
133+ Collections .singletonList (new BitbucketHref ("http" , sampleRepo .toString ()))
134+ )
135+ );
136+ when (api .getRepository ()).thenReturn (repository );
137+ when (api .getFileContent (any (BitbucketSCMFile .class ))).thenReturn (
138+ new ByteArrayInputStream (dsl .getBytes ()));
139+ BitbucketMockApiFactory .add (BitbucketCloudEndpoint .SERVER_URL , api );
140+
141+ BitbucketSCMSource source = new BitbucketSCMSource (repoOwner , repositoryName );
142+ WorkflowMultiBranchProject owner = r .jenkins .createProject (WorkflowMultiBranchProject .class , "p" );
143+ source .setTraits (Collections .singletonList (
144+ new BranchDiscoveryTrait (true , true )
145+ ));
146+ owner .setSourcesList (Collections .singletonList (new BranchSource (source )));
147+ source .setOwner (owner );
148+ return owner ;
149+ }
150+
151+ @ Test
152+ public void firstCheckoutCompletedInvisibleAction () throws Exception {
153+ String dsl = "node { checkout scm }" ;
154+ WorkflowMultiBranchProject owner = prepareFirstCheckoutCompletedInvisibleActionTest (dsl );
155+
156+ owner .scheduleBuild2 (0 ).getFuture ().get ();
157+ owner .getComputation ().writeWholeLogTo (System .out );
158+ assertThat (owner .getIndexing ().getResult (), is (Result .SUCCESS ));
159+ r .waitUntilNoActivity ();
160+ WorkflowJob master = owner .getItem ("master" );
161+ WorkflowRun run = master .getLastBuild ();
162+ run .writeWholeLogTo (System .out );
163+ assertThat (run .getResult (), is (Result .SUCCESS ));
164+ assertThat ((List <Action >) run .getAllActions (), hasItem (instanceOf (FirstCheckoutCompletedInvisibleAction .class )));
54165 }
55166
167+ @ Issue ("JENKINS-66040" )
168+ @ Test
169+ public void shouldNotSetFirstCheckoutCompletedInvisibleActionOnOtherCheckoutWithNonDefaultFactory () throws Exception {
170+ String dsl = "node { checkout(scm: [$class: 'GitSCM', userRemoteConfigs: [[url: 'https://github.com/jenkinsci/bitbucket-branch-source-plugin.git']], branches: [[name: 'master']]]) }" ;
171+ WorkflowMultiBranchProject owner = prepareFirstCheckoutCompletedInvisibleActionTest (dsl );
172+ owner .setProjectFactory (new DummyWorkflowBranchProjectFactory (dsl ));
173+
174+ owner .scheduleBuild2 (0 ).getFuture ().get ();
175+ owner .getComputation ().writeWholeLogTo (System .out );
176+ assertThat (owner .getIndexing ().getResult (), is (Result .SUCCESS ));
177+ r .waitUntilNoActivity ();
178+ WorkflowJob master = owner .getItem ("master" );
179+ WorkflowRun run = master .getLastBuild ();
180+ run .writeWholeLogTo (System .out );
181+ assertThat (run .getResult (), is (Result .SUCCESS ));
182+ assertThat ((List <Action >) run .getAllActions (), not (hasItem (instanceOf (FirstCheckoutCompletedInvisibleAction .class ))));
183+ }
184+
185+ private static class DummyWorkflowBranchProjectFactory extends AbstractWorkflowBranchProjectFactory {
186+ private final String dsl ;
187+
188+ public DummyWorkflowBranchProjectFactory (String dsl ) {
189+ this .dsl = dsl ;
190+ }
191+
192+ @ Override
193+ protected FlowDefinition createDefinition () {
194+ return new CpsFlowDefinition (dsl , true );
195+ }
196+
197+ @ Override
198+ protected SCMSourceCriteria getSCMSourceCriteria (SCMSource source ) {
199+ return new SCMSourceCriteria () {
200+ @ Override
201+ public boolean isHead (Probe probe , TaskListener listener ) throws IOException {
202+ return true ;
203+ }
204+ };
205+ }
206+ }
56207}
0 commit comments