Skip to content

Commit

Permalink
Remove subversion test dep (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
jglick authored Aug 7, 2024
1 parent fab3b11 commit e57b346
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 190 deletions.
27 changes: 0 additions & 27 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,32 +194,5 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>subversion</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-common</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>subversion</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit-cli</artifactId>
<version>1.10.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import jenkins.model.Jenkins;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.scm.impl.subversion.SubversionSCMSource;
import static org.hamcrest.CoreMatchers.*;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
Expand Down Expand Up @@ -74,17 +73,16 @@ public class FolderLibrariesTest {
Folder d = r.jenkins.createProject(Folder.class, "d");
r.configRoundtrip(d);
assertNull(d.getProperties().get(FolderLibraries.class));
LibraryConfiguration foo = new LibraryConfiguration("foo", new SCMSourceRetriever(new SubversionSCMSource("foo", "https://phony.jenkins.io/foo/")));
LibraryConfiguration bar = new LibraryConfiguration("bar", new SCMRetriever(new GitSCM("https://phony.jenkins.io/bar.git")));
bar.setDefaultVersion("master");
bar.setImplicit(true);
bar.setAllowVersionOverride(false);
d.getProperties().add(new FolderLibraries(Arrays.asList(foo, bar)));
d.getProperties().add(new FolderLibraries(Arrays.asList(bar)));
r.configRoundtrip(d);
FolderLibraries prop = d.getProperties().get(FolderLibraries.class);
assertNotNull(prop);
List<LibraryConfiguration> libs = prop.getLibraries();
r.assertEqualDataBoundBeans(Arrays.asList(foo, bar), libs);
r.assertEqualDataBoundBeans(Arrays.asList(bar), libs);
}

@Test public void registration() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import jenkins.model.Jenkins;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.scm.impl.subversion.SubversionSCMSource;
import org.htmlunit.HttpMethod;
import org.htmlunit.WebRequest;
import org.htmlunit.html.HtmlPage;
Expand Down Expand Up @@ -108,14 +107,13 @@ static void checkDefaultVersionRestricted(JenkinsRule r, GitSampleRepoRule sampl

static void configRoundtrip(JenkinsRule r, AbstractGlobalLibraries gl, Permission... alicePrivileges) throws Exception {
assertEquals(Collections.emptyList(), gl.getLibraries());
LibraryConfiguration foo = new LibraryConfiguration("foo", new SCMSourceRetriever(new SubversionSCMSource("foo", "https://phony.jenkins.io/foo/")));
LibraryConfiguration bar = new LibraryConfiguration("bar", new SCMSourceRetriever(new GitSCMSource(null, "https://phony.jenkins.io/bar.git", "", "origin", "+refs/heads/*:refs/remotes/origin/*", "*", "", true)));
LibraryCachingConfiguration cachingConfiguration = new LibraryCachingConfiguration(120, "develop", "master stable");
foo.setCachingConfiguration(cachingConfiguration);
bar.setCachingConfiguration(cachingConfiguration);
bar.setDefaultVersion("master");
bar.setImplicit(true);
bar.setAllowVersionOverride(false);
gl.setLibraries(Arrays.asList(foo, bar));
gl.setLibraries(Arrays.asList(bar));
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(alicePrivileges).everywhere().to("alice")
Expand All @@ -124,16 +122,16 @@ static void configRoundtrip(JenkinsRule r, AbstractGlobalLibraries gl, Permissio
assertThat(configurePage.getWebResponse().getContentAsString(), containsString("https://phony.jenkins.io/bar.git"));
r.submit(configurePage.getFormByName("config")); // JenkinsRule.configRoundtrip expanded to include login
List<LibraryConfiguration> libs = gl.getLibraries();
r.assertEqualDataBoundBeans(Arrays.asList(foo, bar), libs);
r.assertEqualDataBoundBeans(Arrays.asList(bar), libs);
libs = gl.getLibraries();
r.assertEqualDataBoundBeans(Arrays.asList(foo, bar), libs);
boolean noFoo = true;
r.assertEqualDataBoundBeans(Arrays.asList(bar), libs);
boolean noBar = true;
for (LibraryConfiguration lib : libs) {
if ("foo".equals(lib.getName())) {
noFoo = false;
if ("bar".equals(lib.getName())) {
noBar = false;
r.assertEqualDataBoundBeans(lib.getCachingConfiguration(), cachingConfiguration);
}
}
assertFalse("Missing a library called foo (should not happen)", noFoo);
assertFalse("Missing a library called bar (should not happen)", noBar);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.UserRemoteConfig;
import hudson.scm.ChangeLogSet;
import hudson.scm.SubversionSCM;
import hudson.slaves.WorkspaceList;
import java.time.ZonedDateTime;
import java.util.Collection;
Expand All @@ -43,8 +42,6 @@
import java.util.Map;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.scm.impl.subversion.SubversionSCMSource;
import jenkins.scm.impl.subversion.SubversionSampleRepoRule;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
Expand Down Expand Up @@ -73,7 +70,6 @@ public class LibraryAdderTest {
@Rule public JenkinsRule r = new JenkinsRule();
@Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
@Rule public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule();
@Rule public SubversionSampleRepoRule sampleSvnRepo = new SubversionSampleRepoRule();

@Test public void smokes() throws Exception {
sampleRepo.init();
Expand Down Expand Up @@ -121,57 +117,6 @@ public class LibraryAdderTest {
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
}

@Test public void interpolationSvn() throws Exception {
sampleSvnRepo.init();
sampleSvnRepo.write("src/pkg/Lib.groovy", "package pkg; class Lib {static String CONST = 'initial'}");
sampleSvnRepo.svnkit("add", sampleSvnRepo.wc() + "/src");
sampleSvnRepo.svnkit("commit", "--message=init", sampleSvnRepo.wc());
sampleSvnRepo.svnkit("copy", "--message=tagged", sampleSvnRepo.trunkUrl(), sampleSvnRepo.tagsUrl() + "/initial");
sampleSvnRepo.write("src/pkg/Lib.groovy", "package pkg; class Lib {static String CONST = 'modified'}");
sampleSvnRepo.svnkit("commit", "--message=modified", sampleSvnRepo.wc());
LibraryConfiguration stuff = new LibraryConfiguration("stuff", new SCMRetriever(new SubversionSCM(sampleSvnRepo.prjUrl() + "/${library.stuff.version}")));
stuff.setDefaultVersion("trunk");
stuff.setImplicit(true);
GlobalLibraries.get().setLibraries(Collections.singletonList(stuff));
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("@Library('stuff@trunk') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("@Library('stuff@tags/initial') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using initial", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("@Library('stuff') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("echo(/using ${pkg.Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
}

@Test public void properSvn() throws Exception {
sampleSvnRepo.init();
sampleSvnRepo.write("src/pkg/Lib.groovy", "package pkg; class Lib {static String CONST = 'initial'}");
sampleSvnRepo.svnkit("add", sampleSvnRepo.wc() + "/src");
sampleSvnRepo.svnkit("commit", "--message=init", sampleSvnRepo.wc());
long tag = sampleSvnRepo.revision();
sampleSvnRepo.svnkit("copy", "--message=tagged", sampleSvnRepo.trunkUrl(), sampleSvnRepo.tagsUrl() + "/initial");
sampleSvnRepo.write("src/pkg/Lib.groovy", "package pkg; class Lib {static String CONST = 'modified'}");
sampleSvnRepo.svnkit("commit", "--message=modified", sampleSvnRepo.wc());
LibraryConfiguration stuff = new LibraryConfiguration("stuff", new SCMSourceRetriever(new SubversionSCMSource(null, sampleSvnRepo.prjUrl())));
stuff.setDefaultVersion("trunk");
stuff.setImplicit(true);
GlobalLibraries.get().setLibraries(Collections.singletonList(stuff));
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("@Library('stuff@trunk') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("@Library('stuff@tags/initial') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using initial", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("@Library('stuff') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
p.setDefinition(new CpsFlowDefinition("echo(/using ${pkg.Lib.CONST}/)", true));
r.assertLogContains("using modified", r.buildAndAssertSuccess(p));
// Note that LibraryAdder.parse uses indexOf not lastIndexOf, so we can have an @ inside a revision
// (the converse is that we may not have an @ inside a library name):
p.setDefinition(new CpsFlowDefinition("@Library('stuff@trunk@" + tag + "') import pkg.Lib; echo(/using ${Lib.CONST}/)", true));
r.assertLogContains("using initial", r.buildAndAssertSuccess(p));
}

@Issue("JENKINS-41497")
@Test public void dontIncludeChangesetsOverriden() throws Exception {
sampleRepo.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@

package org.jenkinsci.plugins.workflow.libs;

import com.cloudbees.hudson.plugins.folder.Folder;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.AbortException;
import hudson.FilePath;
import hudson.Functions;
import hudson.model.Item;
import hudson.model.Result;
import hudson.model.TaskListener;
Expand All @@ -37,9 +35,6 @@
import hudson.slaves.WorkspaceList;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
Expand All @@ -53,9 +48,6 @@
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.SCMSourceCriteria;
import jenkins.scm.api.SCMSourceDescriptor;
import jenkins.scm.impl.subversion.SubversionSCMSource;
import jenkins.scm.impl.subversion.SubversionSampleRepoRule;
import org.apache.commons.io.FileUtils;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
Expand Down Expand Up @@ -85,9 +77,7 @@
import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.Matchers.nullValue;
import static org.jenkinsci.plugins.workflow.libs.SCMBasedRetriever.PROHIBITED_DOUBLE_DOT;
import static org.junit.Assume.assumeFalse;
import org.jvnet.hudson.test.FlagRule;
import org.jvnet.hudson.test.LoggerRule;

Expand All @@ -96,7 +86,6 @@ public class SCMSourceRetrieverTest {
@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();
@Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
@Rule public SubversionSampleRepoRule sampleRepoSvn = new SubversionSampleRepoRule();
@Rule public FlagRule<Boolean> includeSrcTest = new FlagRule<>(() -> SCMBasedRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES, v -> SCMBasedRetriever.INCLUDE_SRC_TEST_IN_LIBRARIES = v);
@Rule public LoggerRule logging = new LoggerRule().record(SCMBasedRetriever.class, Level.FINE);

Expand Down Expand Up @@ -487,87 +476,4 @@ public static class BasicSCMSource extends SCMSource {
r.assertLogNotContains("Excluding src/test/ from checkout", b);
}

@Issue("SECURITY-2441")
@Test public void libraryNamesAreNotUsedAsCheckoutDirectories() throws Exception {
sampleRepo.init();
sampleRepo.write("vars/globalLibVar.groovy", "def call() { echo('global library') }");
sampleRepo.git("add", "vars");
sampleRepo.git("commit", "--message=init");
LibraryConfiguration globalLib = new LibraryConfiguration("library",
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
globalLib.setDefaultVersion("master");
globalLib.setImplicit(true);
GlobalLibraries.get().setLibraries(Collections.singletonList(globalLib));
// Create a folder library with the same name as the global library so it takes precedence.
sampleRepoSvn.init();
sampleRepoSvn.write("vars/folderLibVar.groovy", "def call() { jenkins.model.Jenkins.get().setSystemMessage('folder library') }");
// Copy .git folder from the Git repo for the global library into the SVN repo for the folder library as data.
FileUtils.copyDirectory(new File(sampleRepo.getRoot(), ".git"), new File(sampleRepoSvn.wc(), ".git"));
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/vars");
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/.git");
sampleRepoSvn.svnkit("commit", "--message=init", sampleRepoSvn.wc());
LibraryConfiguration folderLib = new LibraryConfiguration("library",
new SCMSourceRetriever(new SubversionSCMSource(null, sampleRepoSvn.prjUrl())));
folderLib.setDefaultVersion("trunk");
folderLib.setImplicit(true);
Folder f = r.jenkins.createProject(Folder.class, "folder1");
f.getProperties().add(new FolderLibraries(Collections.singletonList(folderLib)));
// Create a job that uses the folder library, which will take precedence over the global library, since they have the same name.
WorkflowJob p = f.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("folderLibVar()", true));
// First build fails as expected since it is not trusted. The folder library is checked out.
WorkflowRun b1 = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains("Only using first definition of library library", b1);
r.assertLogContains("Scripts not permitted to use staticMethod jenkins.model.Jenkins get", b1);
// Attacker deletes the folder library, then reruns the build.
// The existing checkout of the SVN repo should not be reused as the Git repo for the global library.
f.getProperties().clear();
WorkflowRun b2 = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains("No such DSL method 'folderLibVar'", b2);
assertThat(r.jenkins.getSystemMessage(), nullValue());
}

@Issue("SECURITY-2463")
@Test public void checkoutDirectoriesAreNotReusedByDifferentScms() throws Exception {
assumeFalse(Functions.isWindows()); // Checkout hook is not cross-platform.
sampleRepo.init();
sampleRepo.write("vars/foo.groovy", "def call() { echo('using global lib') }");
sampleRepo.git("add", "vars");
sampleRepo.git("commit", "--message=init");
LibraryConfiguration globalLib = new LibraryConfiguration("library",
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
globalLib.setDefaultVersion("master");
globalLib.setImplicit(true);
GlobalLibraries.get().setLibraries(Collections.singletonList(globalLib));
// Create a folder library with the same name as the global library so it takes precedence.
sampleRepoSvn.init();
sampleRepoSvn.write("vars/foo.groovy", "def call() { echo('using folder lib') }");
// Copy .git folder from the Git repo for the global library into the SVN repo for the folder library as data.
File gitDirInSvnRepo = new File(sampleRepoSvn.wc(), ".git");
FileUtils.copyDirectory(new File(sampleRepo.getRoot(), ".git"), gitDirInSvnRepo);
String jenkinsRootDir = r.jenkins.getRootDir().toString();
// Add a Git post-checkout hook to the .git folder in the SVN repo.
Path postCheckoutHook = gitDirInSvnRepo.toPath().resolve("hooks/post-checkout");
// Always create hooks directory for compatibility with https://github.com/jenkinsci/git-plugin/pull/1207.
Files.createDirectories(postCheckoutHook.getParent());
Files.write(postCheckoutHook, ("#!/bin/sh\ntouch '" + jenkinsRootDir + "/hook-executed'\n").getBytes(StandardCharsets.UTF_8));
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/vars");
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/.git");
sampleRepoSvn.svnkit("propset", "svn:executable", "ON", sampleRepoSvn.wc() + "/.git/hooks/post-checkout");
sampleRepoSvn.svnkit("commit", "--message=init", sampleRepoSvn.wc());
LibraryConfiguration folderLib = new LibraryConfiguration("library",
new SCMSourceRetriever(new SubversionSCMSource(null, sampleRepoSvn.prjUrl())));
folderLib.setDefaultVersion("trunk");
folderLib.setImplicit(true);
Folder f = r.jenkins.createProject(Folder.class, "folder1");
f.getProperties().add(new FolderLibraries(Collections.singletonList(folderLib)));
// Run the build using the folder library (which uses the SVN repo).
WorkflowJob p = f.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("foo()", true));
r.buildAndAssertSuccess(p);
// Delete the folder library, and rerun the build so the global library is used.
f.getProperties().clear();
WorkflowRun b2 = r.buildAndAssertSuccess(p);
assertFalse("Git checkout should not execute hooks from SVN repo", new File(r.jenkins.getRootDir(), "hook-executed").exists());
}
}

0 comments on commit e57b346

Please sign in to comment.