1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.release.phase;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.apache.maven.project.MavenProject;
28 import org.apache.maven.scm.ScmException;
29 import org.apache.maven.scm.ScmFile;
30 import org.apache.maven.scm.ScmFileSet;
31 import org.apache.maven.scm.ScmFileStatus;
32 import org.apache.maven.scm.ScmVersion;
33 import org.apache.maven.scm.command.checkin.CheckInScmResult;
34 import org.apache.maven.scm.manager.NoSuchScmProviderException;
35 import org.apache.maven.scm.manager.ScmManager;
36 import org.apache.maven.scm.provider.ScmProvider;
37 import org.apache.maven.scm.provider.ScmProviderStub;
38 import org.apache.maven.scm.repository.ScmRepository;
39 import org.apache.maven.scm.repository.ScmRepositoryException;
40 import org.apache.maven.shared.release.ReleaseExecutionException;
41 import org.apache.maven.shared.release.ReleaseFailureException;
42 import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
43 import org.apache.maven.shared.release.config.ReleaseUtils;
44 import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
45 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
46 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
47 import org.apache.maven.shared.release.stubs.ScmManagerStub;
48 import org.apache.maven.shared.release.util.ReleaseUtil;
49 import org.junit.Test;
50
51 import static org.junit.Assert.assertEquals;
52 import static org.junit.Assert.assertNull;
53 import static org.junit.Assert.assertTrue;
54 import static org.junit.Assert.fail;
55 import static org.mockito.ArgumentMatchers.argThat;
56 import static org.mockito.ArgumentMatchers.eq;
57 import static org.mockito.ArgumentMatchers.isA;
58 import static org.mockito.ArgumentMatchers.isNull;
59 import static org.mockito.Mockito.mock;
60 import static org.mockito.Mockito.verify;
61 import static org.mockito.Mockito.verifyNoMoreInteractions;
62 import static org.mockito.Mockito.when;
63
64
65
66
67
68
69 public class ScmCommitPreparationPhaseTest extends AbstractReleaseTestCase {
70 private static final String PREFIX = "[maven-release-manager] prepare release ";
71
72 @Override
73 public void setUp() throws Exception {
74 super.setUp();
75
76 phase = lookup(ReleasePhase.class, "scm-commit-release");
77 }
78
79 @Test
80 public void testIsCorrectImplementation() {
81 assertEquals(ScmCommitReleasePhase.class, phase.getClass());
82 }
83
84 @Test
85 public void testResolvesCorrectBranchImplementation() throws Exception {
86 assertTrue(lookup(ReleasePhase.class, "scm-commit-branch") instanceof ScmCommitBranchPhase);
87 }
88
89 @Test
90 public void testCommit() throws Exception {
91
92 List<MavenProject> reactorProjects = createReactorProjects();
93 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
94 builder.setScmSourceUrl("scm-url");
95 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
96 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
97 builder.setScmReleaseLabel("release-label");
98
99 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), rootProject.getFile());
100
101 ScmProvider scmProviderMock = mock(ScmProvider.class);
102 when(scmProviderMock.checkIn(
103 isA(ScmRepository.class),
104 argThat(new IsScmFileSetEquals(fileSet)),
105 isNull(ScmVersion.class),
106 eq(PREFIX + "release-label")))
107 .thenReturn(new CheckInScmResult(
108 "...",
109 Collections.singletonList(
110 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
111
112 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
113 stub.setScmProvider(scmProviderMock);
114
115
116 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
117
118
119 verify(scmProviderMock)
120 .checkIn(
121 isA(ScmRepository.class), argThat(new IsScmFileSetEquals(fileSet)),
122 isNull(ScmVersion.class), eq(PREFIX + "release-label"));
123 verifyNoMoreInteractions(scmProviderMock);
124 }
125
126 @Test
127 public void testCommitAlternateMessage() throws Exception {
128
129 List<MavenProject> reactorProjects = createReactorProjects();
130 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
131 builder.setScmSourceUrl("scm-url");
132 builder.setScmCommentPrefix("[release]");
133 builder.setScmReleaseCommitComment("@{prefix} Release of @{groupId}:@{artifactId} @{releaseLabel}");
134 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
135 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
136 builder.setScmReleaseLabel("release-label");
137
138 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), rootProject.getFile());
139
140 ScmProvider scmProviderMock = mock(ScmProvider.class);
141 when(scmProviderMock.checkIn(
142 isA(ScmRepository.class),
143 argThat(new IsScmFileSetEquals(fileSet)),
144 isNull(ScmVersion.class),
145 eq("[release] Release of groupId:artifactId release-label")))
146 .thenReturn(new CheckInScmResult(
147 "...",
148 Collections.singletonList(
149 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
150
151 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
152 stub.setScmProvider(scmProviderMock);
153
154
155 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
156
157
158 verify(scmProviderMock)
159 .checkIn(
160 isA(ScmRepository.class), argThat(new IsScmFileSetEquals(fileSet)),
161 isNull(ScmVersion.class), eq("[release] Release of groupId:artifactId release-label"));
162 verifyNoMoreInteractions(scmProviderMock);
163 }
164
165 @Test
166 public void testCommitMultiModule() throws Exception {
167
168 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
169 String dir = "scm-commit/multiple-poms";
170 List<MavenProject> reactorProjects = createReactorProjects(dir, dir, null);
171 builder.setScmSourceUrl("scm-url");
172 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
173 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
174 builder.setScmReleaseLabel("release-label");
175
176 List<File> poms = new ArrayList<>();
177 for (Iterator<MavenProject> i = reactorProjects.iterator(); i.hasNext(); ) {
178 MavenProject project = i.next();
179 poms.add(project.getFile());
180 }
181 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), poms);
182
183 ScmProvider scmProviderMock = mock(ScmProvider.class);
184 when(scmProviderMock.checkIn(
185 isA(ScmRepository.class),
186 argThat(new IsScmFileSetEquals(fileSet)),
187 isNull(ScmVersion.class),
188 eq(PREFIX + "release-label")))
189 .thenReturn(new CheckInScmResult(
190 "...",
191 Collections.singletonList(
192 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
193 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
194 stub.setScmProvider(scmProviderMock);
195
196
197 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
198
199
200 verify(scmProviderMock)
201 .checkIn(
202 isA(ScmRepository.class), argThat(new IsScmFileSetEquals(fileSet)),
203 isNull(ScmVersion.class), eq(PREFIX + "release-label"));
204 verifyNoMoreInteractions(scmProviderMock);
205 }
206
207 @Test
208 public void testCommitDevelopment() throws Exception {
209
210 phase = (ReleasePhase) lookup(ReleasePhase.class, "scm-commit-development");
211
212 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
213 List<MavenProject> reactorProjects = createReactorProjects();
214 builder.setScmSourceUrl("scm-url");
215 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
216 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
217 builder.setScmReleaseLabel("release-label");
218
219 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), rootProject.getFile());
220
221 ScmProvider scmProviderMock = mock(ScmProvider.class);
222 when(scmProviderMock.checkIn(
223 isA(ScmRepository.class),
224 argThat(new IsScmFileSetEquals(fileSet)),
225 isNull(ScmVersion.class),
226 eq("[maven-release-manager] prepare for next development iteration")))
227 .thenReturn(new CheckInScmResult(
228 "...",
229 Collections.singletonList(
230 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
231
232 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
233 stub.setScmProvider(scmProviderMock);
234
235
236 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
237
238
239 verify(scmProviderMock)
240 .checkIn(
241 isA(ScmRepository.class),
242 argThat(new IsScmFileSetEquals(fileSet)),
243 isNull(ScmVersion.class),
244 eq("[maven-release-manager] prepare for next development iteration"));
245 verifyNoMoreInteractions(scmProviderMock);
246 }
247
248 @Test
249 public void testCommitDevelopmentAlternateMessage() throws Exception {
250
251 phase = (ReleasePhase) lookup(ReleasePhase.class, "scm-commit-development");
252
253 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
254 List<MavenProject> reactorProjects = createReactorProjects();
255 builder.setScmSourceUrl("scm-url");
256 builder.setScmCommentPrefix("[release]");
257 builder.setScmDevelopmentCommitComment(
258 "@{prefix} Bump version of @{groupId}:@{artifactId} after @{releaseLabel}");
259 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
260 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
261 builder.setScmReleaseLabel("release-label");
262
263 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), rootProject.getFile());
264
265 ScmProvider scmProviderMock = mock(ScmProvider.class);
266 when(scmProviderMock.checkIn(
267 isA(ScmRepository.class),
268 argThat(new IsScmFileSetEquals(fileSet)),
269 isNull(ScmVersion.class),
270 eq("[release] Bump version of groupId:artifactId after release-label")))
271 .thenReturn(new CheckInScmResult(
272 "...",
273 Collections.singletonList(
274 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
275
276 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
277 stub.setScmProvider(scmProviderMock);
278
279
280 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
281
282
283 verify(scmProviderMock)
284 .checkIn(
285 isA(ScmRepository.class),
286 argThat(new IsScmFileSetEquals(fileSet)),
287 isNull(ScmVersion.class),
288 eq("[release] Bump version of groupId:artifactId after release-label"));
289 verifyNoMoreInteractions(scmProviderMock);
290 }
291
292 @Test
293 public void testCommitNoReleaseLabel() throws Exception {
294 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
295 List<MavenProject> reactorProjects = createReactorProjects();
296
297 try {
298 phase.execute(
299 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
300 fail("Should have thrown an exception");
301 } catch (ReleaseFailureException e) {
302 assertTrue(true);
303 }
304 }
305
306 @Test
307 public void testCommitGenerateReleasePoms() throws Exception {
308
309 List<MavenProject> reactorProjects = createReactorProjects();
310 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
311 builder.setScmSourceUrl("scm-url");
312 builder.setGenerateReleasePoms(true);
313 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
314 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
315 builder.setScmReleaseLabel("release-label");
316
317 List<File> files = new ArrayList<>();
318 files.add(rootProject.getFile());
319 files.add(ReleaseUtil.getReleasePom(rootProject));
320 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile(), files);
321
322 ScmProvider scmProviderMock = mock(ScmProvider.class);
323 when(scmProviderMock.checkIn(
324 isA(ScmRepository.class),
325 argThat(new IsScmFileSetEquals(fileSet)),
326 isNull(ScmVersion.class),
327 eq(PREFIX + "release-label")))
328 .thenReturn(new CheckInScmResult(
329 "...",
330 Collections.singletonList(
331 new ScmFile(rootProject.getFile().getPath(), ScmFileStatus.CHECKED_IN))));
332
333 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
334 stub.setScmProvider(scmProviderMock);
335
336
337 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
338
339
340 verify(scmProviderMock)
341 .checkIn(
342 isA(ScmRepository.class), argThat(new IsScmFileSetEquals(fileSet)),
343 isNull(ScmVersion.class), eq(PREFIX + "release-label"));
344 verifyNoMoreInteractions(scmProviderMock);
345 }
346
347 @Test
348 public void testSimulateCommit() throws Exception {
349 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
350 List<MavenProject> reactorProjects = createReactorProjects();
351 builder.setScmSourceUrl("scm-url");
352 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
353 builder.setWorkingDirectory(rootProject.getFile().getParentFile().getAbsolutePath());
354 builder.setScmReleaseLabel("release-label");
355
356 ScmProvider scmProviderMock = mock(ScmProvider.class);
357
358 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
359 stub.setScmProvider(scmProviderMock);
360
361 phase.simulate(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
362
363
364 verifyNoMoreInteractions(scmProviderMock);
365 }
366
367 @Test
368 public void testSimulateCommitNoReleaseLabel() throws Exception {
369 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
370 List<MavenProject> reactorProjects = createReactorProjects();
371
372 try {
373 phase.simulate(
374 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
375 fail("Should have thrown an exception");
376 } catch (ReleaseFailureException e) {
377 assertTrue(true);
378 }
379 }
380
381 @Test
382 public void testNoSuchScmProviderExceptionThrown() throws Exception {
383
384 List<MavenProject> reactorProjects = createReactorProjects();
385 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
386
387 ScmManagerStub scmManagerStub = (ScmManagerStub) lookup(ScmManager.class);
388 scmManagerStub.setException(new NoSuchScmProviderException("..."));
389
390 try {
391 phase.execute(
392 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
393
394 fail("Status check should have failed");
395 } catch (ReleaseExecutionException e) {
396
397 assertEquals(
398 "check cause",
399 NoSuchScmProviderException.class,
400 e.getCause().getClass());
401 }
402 }
403
404 @Test
405 public void testScmRepositoryExceptionThrown() throws Exception {
406
407 List<MavenProject> reactorProjects = createReactorProjects();
408 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
409
410 ScmManagerStub scmManagerStub = (ScmManagerStub) lookup(ScmManager.class);
411 scmManagerStub.setException(new ScmRepositoryException("..."));
412
413
414 try {
415 phase.execute(
416 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
417
418 fail("Status check should have failed");
419 } catch (ReleaseScmRepositoryException e) {
420
421 assertNull("Check no additional cause", e.getCause());
422 }
423 }
424
425 @Test
426 public void testScmExceptionThrown() throws Exception {
427
428 List<MavenProject> reactorProjects = createReactorProjects();
429 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
430
431 ScmProvider scmProviderMock = mock(ScmProvider.class);
432 when(scmProviderMock.checkIn(
433 isA(ScmRepository.class), isA(ScmFileSet.class), isNull(ScmVersion.class), isA(String.class)))
434 .thenThrow(new ScmException("..."));
435
436 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
437 stub.setScmProvider(scmProviderMock);
438
439
440 try {
441 phase.execute(
442 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
443
444 fail("Status check should have failed");
445 } catch (ReleaseExecutionException e) {
446 assertEquals("check cause", ScmException.class, e.getCause().getClass());
447 }
448
449
450 verify(scmProviderMock)
451 .checkIn(
452 isA(ScmRepository.class), isA(ScmFileSet.class),
453 isNull(ScmVersion.class), isA(String.class));
454 verifyNoMoreInteractions(scmProviderMock);
455 }
456
457 @Test
458 public void testScmResultFailure() throws Exception {
459 List<MavenProject> reactorProjects = createReactorProjects();
460 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
461
462 ScmManager scmManager = (ScmManager) lookup(ScmManager.class);
463 ScmProviderStub providerStub = (ScmProviderStub) scmManager.getProviderByUrl("scm-url");
464
465 providerStub.setCheckInScmResult(new CheckInScmResult("", "", "", false));
466
467 try {
468 phase.execute(
469 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
470
471 fail("Commit should have failed");
472 } catch (ReleaseScmCommandException e) {
473 assertNull("check no other cause", e.getCause());
474 }
475 }
476
477 @Test
478 public void testSuppressCommitWithRemoteTaggingFails() throws Exception {
479 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
480 List<MavenProject> reactorProjects = createReactorProjects();
481
482 builder.setRemoteTagging(true);
483 builder.setPinExternals(false);
484 builder.setSuppressCommitBeforeTagOrBranch(true);
485
486 ScmProvider scmProviderMock = mock(ScmProvider.class);
487
488 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
489 stub.setScmProvider(scmProviderMock);
490
491 try {
492 phase.execute(
493 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
494
495 fail("Commit should have failed with ReleaseFailureException");
496 } catch (ReleaseFailureException e) {
497 assertNull("check no other cause", e.getCause());
498 }
499
500
501 verifyNoMoreInteractions(scmProviderMock);
502 }
503
504 @Test
505 public void testSuppressCommitAfterBranch() throws Exception {
506 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
507 List<MavenProject> reactorProjects = createReactorProjects();
508
509 builder.setBranchCreation(true);
510 builder.setRemoteTagging(false);
511 builder.setSuppressCommitBeforeTagOrBranch(true);
512
513 ScmProvider scmProviderMock = mock(ScmProvider.class);
514
515 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
516 stub.setScmProvider(scmProviderMock);
517
518 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
519
520
521 verifyNoMoreInteractions(scmProviderMock);
522 }
523
524 private List<MavenProject> createReactorProjects() throws Exception {
525 String dir = "scm-commit/single-pom";
526 return createReactorProjects(dir, dir, null);
527 }
528
529 private static ReleaseDescriptorBuilder createReleaseDescriptorBuilder() {
530 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
531 builder.setScmSourceUrl("scm-url");
532 builder.setScmReleaseLabel("release-label");
533 builder.setWorkingDirectory(getTestFile("target/test/checkout").getAbsolutePath());
534 return builder;
535 }
536 }