|
60 | 60 | import org.jenkinsci.plugins.workflow.job.WorkflowRun;
|
61 | 61 |
|
62 | 62 | import static hudson.ExtensionList.lookupSingleton;
|
| 63 | +import hudson.plugins.git.extensions.impl.CloneOption; |
| 64 | +import jenkins.plugins.git.traits.CloneOptionTrait; |
| 65 | +import jenkins.scm.api.trait.SCMSourceTrait; |
63 | 66 | import static org.hamcrest.Matchers.contains;
|
64 | 67 | import static org.hamcrest.Matchers.containsInAnyOrder;
|
65 | 68 | import static org.hamcrest.Matchers.instanceOf;
|
|
81 | 84 | import static org.hamcrest.Matchers.nullValue;
|
82 | 85 | import static org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever.PROHIBITED_DOUBLE_DOT;
|
83 | 86 | import static org.junit.Assume.assumeFalse;
|
| 87 | +import org.jvnet.hudson.test.FlagRule; |
84 | 88 |
|
85 | 89 | public class SCMSourceRetrieverTest {
|
86 | 90 |
|
87 | 91 | @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
|
88 | 92 | @Rule public JenkinsRule r = new JenkinsRule();
|
89 | 93 | @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
|
90 | 94 | @Rule public SubversionSampleRepoRule sampleRepoSvn = new SubversionSampleRepoRule();
|
| 95 | + @Rule public FlagRule<Boolean> includeSrcTest = new FlagRule<>(() -> SCMSourceRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES, v -> SCMSourceRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES = v); |
91 | 96 |
|
92 | 97 | @Issue("JENKINS-40408")
|
93 | 98 | @Test public void lease() throws Exception {
|
@@ -366,6 +371,107 @@ public static class BasicSCMSource extends SCMSource {
|
366 | 371 | assertFalse(ws.exists());
|
367 | 372 | }
|
368 | 373 |
|
| 374 | + @Test public void cloneMode() throws Exception { |
| 375 | + sampleRepo.init(); |
| 376 | + sampleRepo.write("vars/myecho.groovy", "def call() {echo 'something special'}"); |
| 377 | + sampleRepo.write("README.md", "Summary"); |
| 378 | + sampleRepo.git("rm", "file"); |
| 379 | + sampleRepo.git("add", "."); |
| 380 | + sampleRepo.git("commit", "--message=init"); |
| 381 | + GitSCMSource src = new GitSCMSource(sampleRepo.toString()); |
| 382 | + src.setTraits(List.<SCMSourceTrait>of(new CloneOptionTrait(new CloneOption(true, null, null)))); |
| 383 | + SCMSourceRetriever scm = new SCMSourceRetriever(src); |
| 384 | + LibraryConfiguration lc = new LibraryConfiguration("echoing", scm); |
| 385 | + lc.setIncludeInChangesets(false); |
| 386 | + scm.setClone(true); |
| 387 | + GlobalLibraries.get().setLibraries(Collections.singletonList(lc)); |
| 388 | + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); |
| 389 | + p.setDefinition(new CpsFlowDefinition("@Library('echoing@master') import myecho; myecho()", true)); |
| 390 | + WorkflowRun b = r.buildAndAssertSuccess(p); |
| 391 | + assertFalse(r.jenkins.getWorkspaceFor(p).withSuffix("@libs").isDirectory()); |
| 392 | + r.assertLogContains("something special", b); |
| 393 | + r.assertLogContains("Deleted .git, README.md", b); |
| 394 | + r.assertLogContains("Using shallow clone with depth 1", b); |
| 395 | + } |
| 396 | + |
| 397 | + @Test public void cloneModeLibraryPath() throws Exception { |
| 398 | + sampleRepo.init(); |
| 399 | + sampleRepo.write("sub/path/vars/myecho.groovy", "def call() {echo 'something special'}"); |
| 400 | + sampleRepo.git("add", "sub"); |
| 401 | + sampleRepo.git("commit", "--message=init"); |
| 402 | + SCMSourceRetriever scm = new SCMSourceRetriever(new GitSCMSource(sampleRepo.toString())); |
| 403 | + LibraryConfiguration lc = new LibraryConfiguration("root_sub_path", scm); |
| 404 | + lc.setIncludeInChangesets(false); |
| 405 | + scm.setLibraryPath("sub/path/"); |
| 406 | + scm.setClone(true); |
| 407 | + GlobalLibraries.get().setLibraries(Collections.singletonList(lc)); |
| 408 | + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); |
| 409 | + p.setDefinition(new CpsFlowDefinition("@Library('root_sub_path@master') import myecho; myecho()", true)); |
| 410 | + WorkflowRun b = r.buildAndAssertSuccess(p); |
| 411 | + r.assertLogContains("something special", b); |
| 412 | + r.assertLogContains("Moving vars to top level", b); |
| 413 | + r.assertLogContains("Deleted root", b); |
| 414 | + } |
| 415 | + |
| 416 | + @Test public void cloneModeLibraryPathSecurity() throws Exception { |
| 417 | + sampleRepo.init(); |
| 418 | + sampleRepo.write("sub/path/vars/myecho.groovy", "def call() {echo 'something special'}"); |
| 419 | + sampleRepo.git("add", "sub"); |
| 420 | + sampleRepo.git("commit", "--message=init"); |
| 421 | + SCMSourceRetriever scm = new SCMSourceRetriever(new GitSCMSource(sampleRepo.toString())); |
| 422 | + LibraryConfiguration lc = new LibraryConfiguration("root_sub_path", scm); |
| 423 | + lc.setIncludeInChangesets(false); |
| 424 | + scm.setLibraryPath("sub/path/../../../jenkins_home/foo"); |
| 425 | + scm.setClone(true); |
| 426 | + GlobalLibraries.get().setLibraries(Collections.singletonList(lc)); |
| 427 | + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); |
| 428 | + p.setDefinition(new CpsFlowDefinition("@Library('root_sub_path@master') import myecho; myecho()", true)); |
| 429 | + WorkflowRun b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); |
| 430 | + r.assertLogContains("Library path may not contain '..'", b); |
| 431 | + } |
| 432 | + |
| 433 | + @Test public void cloneModeExcludeSrcTest() throws Exception { |
| 434 | + sampleRepo.init(); |
| 435 | + sampleRepo.write("vars/myecho.groovy", "def call() {echo 'something special'}"); |
| 436 | + sampleRepo.write("src/test/X.groovy", "// irrelevant"); |
| 437 | + sampleRepo.write("README.md", "Summary"); |
| 438 | + sampleRepo.git("add", "."); |
| 439 | + sampleRepo.git("commit", "--message=init"); |
| 440 | + SCMSourceRetriever scm = new SCMSourceRetriever(new GitSCMSource(sampleRepo.toString())); |
| 441 | + LibraryConfiguration lc = new LibraryConfiguration("echoing", scm); |
| 442 | + lc.setIncludeInChangesets(false); |
| 443 | + scm.setClone(true); |
| 444 | + GlobalLibraries.get().setLibraries(Collections.singletonList(lc)); |
| 445 | + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); |
| 446 | + p.setDefinition(new CpsFlowDefinition("@Library('echoing@master') import myecho; myecho()", true)); |
| 447 | + SCMSourceRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES = false; |
| 448 | + WorkflowRun b = r.buildAndAssertSuccess(p); |
| 449 | + assertFalse(r.jenkins.getWorkspaceFor(p).withSuffix("@libs").isDirectory()); |
| 450 | + r.assertLogContains("something special", b); |
| 451 | + r.assertLogContains("Excluding src/test/ from checkout", b); |
| 452 | + } |
| 453 | + |
| 454 | + @Test public void cloneModeIncludeSrcTest() throws Exception { |
| 455 | + sampleRepo.init(); |
| 456 | + sampleRepo.write("vars/myecho.groovy", "def call() {echo(/got ${new test.X().m()}/)}"); |
| 457 | + sampleRepo.write("src/test/X.groovy", "package test; class X {def m() {'something special'}}"); |
| 458 | + sampleRepo.write("README.md", "Summary"); |
| 459 | + sampleRepo.git("add", "."); |
| 460 | + sampleRepo.git("commit", "--message=init"); |
| 461 | + SCMSourceRetriever scm = new SCMSourceRetriever(new GitSCMSource(sampleRepo.toString())); |
| 462 | + LibraryConfiguration lc = new LibraryConfiguration("echoing", scm); |
| 463 | + lc.setIncludeInChangesets(false); |
| 464 | + scm.setClone(true); |
| 465 | + GlobalLibraries.get().setLibraries(Collections.singletonList(lc)); |
| 466 | + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); |
| 467 | + p.setDefinition(new CpsFlowDefinition("@Library('echoing@master') import myecho; myecho()", true)); |
| 468 | + SCMSourceRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES = true; |
| 469 | + WorkflowRun b = r.buildAndAssertSuccess(p); |
| 470 | + assertFalse(r.jenkins.getWorkspaceFor(p).withSuffix("@libs").isDirectory()); |
| 471 | + r.assertLogContains("got something special", b); |
| 472 | + r.assertLogNotContains("Excluding src/test/ from checkout", b); |
| 473 | + } |
| 474 | + |
369 | 475 | @Issue("SECURITY-2441")
|
370 | 476 | @Test public void libraryNamesAreNotUsedAsCheckoutDirectories() throws Exception {
|
371 | 477 | sampleRepo.init();
|
|
0 commit comments