/*
* The MIT License
*
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Alan Harder
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.plugins.copyartifact;
import hudson.FilePath;
import hudson.Functions;
import hudson.Launcher;
import hudson.matrix.Axis;
import hudson.matrix.AxisList;
import hudson.matrix.Combination;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixProject;
import hudson.matrix.TextAxis;
import hudson.matrix.MatrixRun;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenModuleSetBuild;
import hudson.model.*;
import hudson.model.Cause.UserCause;
import hudson.plugins.copyartifact.testutils.CopyArtifactUtil;
import hudson.plugins.copyartifact.testutils.FileWriteBuilder;
import hudson.plugins.copyartifact.testutils.WrapperBuilder;
import hudson.remoting.VirtualChannel;
import hudson.security.ACL;
import hudson.security.Permission;
import hudson.security.AuthorizationMatrixProperty;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import hudson.security.ProjectMatrixAuthorizationStrategy;
import hudson.slaves.DumbSlave;
import hudson.slaves.SlaveComputer;
import hudson.tasks.ArtifactArchiver;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildTrigger;
import hudson.tasks.Builder;
import hudson.util.FormValidation;
import hudson.util.VersionNumber;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import jenkins.security.QueueItemAuthenticatorConfiguration;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.jvnet.hudson.test.ExtractResourceSCM;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.CaptureEnvironmentBuilder;
import org.jvnet.hudson.test.FailureBuilder;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.MockFolder;
import org.jvnet.hudson.test.ToolInstallations;
import org.jvnet.hudson.test.UnstableBuilder;
import org.jvnet.hudson.test.recipes.LocalData;
import org.jvnet.hudson.test.recipes.WithPlugin;
import com.cloudbees.hudson.plugins.folder.Folder;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.google.common.collect.Sets;
import org.jvnet.hudson.test.TestBuilder;
import static org.junit.Assert.*;
/**
* Test interaction of copyartifact plugin with Jenkins core.
* @author Alan Harder
*/
public class CopyArtifactTest {
@Rule
public final JenkinsRule rule = new JenkinsRule();
@Rule
public TestName name = new TestName();
// Tests using slaves fails with Jenkins < 1.520 on Windows.
// See https://wiki.jenkins-ci.org/display/JENKINS/Unit+Test+on+Windows
private void purgeSlaves() {
List<Computer> disconnectingComputers = new ArrayList<Computer>();
List<VirtualChannel> closingChannels = new ArrayList<VirtualChannel>();
for (Computer computer: rule.jenkins.getComputers()) {
if (!(computer instanceof SlaveComputer)) {
continue;
}
// disconnect slaves.
// retrieve the channel before disconnecting.
// even a computer gets offline, channel delays to close.
if (!computer.isOffline()) {
VirtualChannel ch = computer.getChannel();
computer.disconnect(null);
disconnectingComputers.add(computer);
closingChannels.add(ch);
}
}
try {
// Wait for all computers disconnected and all channels closed.
for (Computer computer: disconnectingComputers) {
computer.waitUntilOffline();
}
for (VirtualChannel ch: closingChannels) {
ch.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@After
public void tearDown() throws Exception {
if(Functions.isWindows()) {
purgeSlaves();
}
}
private FreeStyleProject createProject(String otherProject, String parameters, String filter,
String target, boolean stable, boolean flatten, boolean optional, boolean fingerprintArtifacts)
throws IOException {
FreeStyleProject p = rule.createFreeStyleProject();
CopyArtifact copyArtifact = CopyArtifactUtil.createCopyArtifact(otherProject, parameters, new StatusBuildSelector(stable), filter, target, flatten, optional, fingerprintArtifacts);
p.getBuildersList().add(copyArtifact);
return p;
}
@Deprecated
private FreeStyleProject createProject(String otherProject, String parameters, String filter,
String target, boolean stable, boolean flatten, boolean optional)
throws IOException {
return createProject(otherProject, parameters, filter, target, stable, flatten, optional, true);
}
private static class ArtifactBuilder extends Builder {
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
// Make some files to archive as artifacts
FilePath ws = build.getWorkspace();
ws.child("foo.txt").touch(System.currentTimeMillis());
ws.child("subdir").mkdirs();
ws.child("subdir/subfoo.txt").touch(System.currentTimeMillis());
ws.child("deepfoo/a/b").mkdirs();
ws.child("deepfoo/a/b/c.log").touch(System.currentTimeMillis());
ws.child(".hg").mkdirs();
ws.child(".hg/defaultexclude.txt").touch(System.currentTimeMillis());
// For matrix tests write one more file:
String foo = build.getBuildVariables().get("FOO");
if (foo != null) ws.child(foo + ".txt").touch(System.currentTimeMillis());
return true;
}
}
private FreeStyleProject createArtifactProject(String name) throws IOException {
FreeStyleProject p = name != null ? rule.createFreeStyleProject(name) : rule.createFreeStyleProject();
p.getBuildersList().add(new ArtifactBuilder());
p.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
return p;
}
private FreeStyleProject createArtifactProject() throws IOException {
return createArtifactProject(null);
}
private String createUniqueProjectName() {
return "test" + rule.jenkins.getItems().size();
}
/**
* Creates an empty Maven project with an unique name.
*
* @return an empty Maven project with an unique name.
*/
private MavenModuleSet createMavenProject() throws IOException {
MavenModuleSet mavenModuleSet = rule.jenkins.createProject(MavenModuleSet.class, createUniqueProjectName());
mavenModuleSet.setRunHeadless(true);
return mavenModuleSet;
}
/**
* Creates an empty Matrix project with an unique name.
*
* @return an empty Matrix project with an unique name.
*/
private MatrixProject createMatrixProject() throws IOException {
return rule.jenkins.createProject(MatrixProject.class, createUniqueProjectName());
}
private MatrixProject createMatrixArtifactProject() throws IOException {
MatrixProject p = createMatrixProject();
p.setAxes(new AxisList(new Axis("FOO", "one", "two")));
p.getBuildersList().add(new ArtifactBuilder());
p.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
return p;
}
private void assertFile(boolean exists, String path, AbstractBuild<?,?> b)
throws IOException, InterruptedException {
if (b.getWorkspace().child(path).exists() != exists)
assertEquals(path + ": " + rule.getLog(b), exists, !exists);
}
@Test
public void testMissingProject() throws Exception {
FreeStyleProject p = createProject("invalid", null, "", "", false, false, false, true);
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testMissingBuild() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "", "", false, false, false, true);
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testMissingStableBuild() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "", "", true, false, false, true);
// Make an unstable build in "other"
other.getBuildersList().add(new UnstableBuilder());
rule.assertBuildStatus(Result.UNSTABLE, other.scheduleBuild2(0, new UserCause()).get());
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testMissingArtifact() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "*.txt", "", false, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testCopyAllWithFingerprints() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "", "", false, false, false, true);
FreeStyleBuild s = rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(true, "deepfoo/a/b/c.log", b);
// testing fingerprints
String d = b.getWorkspace().child("foo.txt").digest();
Fingerprint f = Hudson.getInstance().getFingerprintMap().get(d);
assertSame(f.getOriginal().getRun(),s);
assertTrue(f.getRangeSet(p).includes(b.getNumber()));
}
@Test
public void testCopyAllWithoutFingerprints() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "", "", false, false, false, false);
FreeStyleBuild s = rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(true, "deepfoo/a/b/c.log", b);
// testing no fingerprints
String d = b.getWorkspace().child("foo.txt").digest();
assertNull(Hudson.getInstance().getFingerprintMap().get(d));
}
@Test
public void testCopyWithFilter() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "**/bogus*, **/sub*, bogus/**", "",
false, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(false, "foo.txt", b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(false, "deepfoo/a/b/c.log", b);
}
@Test
public void testCopyToTarget() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "deep*/**", "new/deep/dir",
true, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(false, "foo.txt", b);
assertFile(false, "new/deep/dir/foo.txt", b);
assertFile(true, "new/deep/dir/deepfoo/a/b/c.log", b);
}
@Test
public void testCopyToSlave() throws Exception {
DumbSlave node = rule.createSlave();
SlaveComputer c = node.getComputer();
c.connect(false).get(); // wait until it's connected
if(c.isOffline())
fail("Slave failed to go online: " + c.getLog());
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "", "", false, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
p.setAssignedLabel(node.getSelfLabel());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertSame(node, b.getBuiltOn());
assertFile(true, "foo.txt", b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(true, "deepfoo/a/b/c.log", b);
}
@Test
public void testParameters() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject("$PROJSRC", null, "$BASE/*.txt", "$TARGET/bar",
false, false, false, true);
ParameterDefinition paramDef = new StringParameterDefinition("PROJSRC", other.getName(), "");
ParameterDefinition paramDef2 = new StringParameterDefinition("BASE", "", "");
ParameterDefinition paramDef3 = new StringParameterDefinition("TARGET", "foo", "");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef, paramDef2, paramDef3);
p.addProperty(paramsDef);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("PROJSRC", other.getName()),
new StringParameterValue("BASE", "*r"),
new StringParameterValue("TARGET", "foo"))).get();
rule.assertBuildStatusSuccess(b);
assertFile(false, "foo/bar/foo.txt", b);
assertFile(true, "foo/bar/subdir/subfoo.txt", b);
}
@Issue("JENKINS-36554")
@Test
public void testEmptyParameter() throws Exception {
FreeStyleProject copiee = createArtifactProject();
FreeStyleProject copier = rule.createFreeStyleProject();
copier.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("EMPTY", "")
));
CopyArtifact ca = new CopyArtifact(String.format("%s${EMPTY}", copiee.getFullDisplayName()));
copier.getBuildersList().add(ca);
rule.buildAndAssertSuccess(copiee);
rule.buildAndAssertSuccess(copier);
}
/** Test copying artifacts from a particular configuration of a matrix job */
@Test
public void testMatrixJob() throws Exception {
MatrixProject other = createMatrixArtifactProject();
FreeStyleProject p = createProject(other.getName() + "/FOO=two", null, "", "",
true, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "two.txt", b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(true, "deepfoo/a/b/c.log", b);
}
/** Test artifact copy between matrix jobs, for artifact from matching axis */
@Test
public void testMatrixToMatrix() throws Exception {
MatrixProject other = createMatrixArtifactProject(),
p = createMatrixProject();
p.setAxes(new AxisList(new Axis("FOO", "one", "two"))); // should match other job
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName() + "/FOO=$FOO", null,
new StatusBuildSelector(true), "", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
MatrixBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
MatrixRun r = b.getRun(new Combination(Collections.singletonMap("FOO", "one")));
assertFile(true, "one.txt", r);
assertFile(false, "two.txt", r);
r = b.getRun(new Combination(Collections.singletonMap("FOO", "two")));
assertFile(false, "one.txt", r);
assertFile(true, "two.txt", r);
}
private static class ArchMatrixBuilder extends Builder {
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
// Get matrix axis value
String arch = build.getBuildVariables().get("ARCH");
FilePath ws = build.getWorkspace();
ws.child("target").mkdirs();
// One fixed filename:
ws.child("target/readme.txt").touch(System.currentTimeMillis());
// Use axis value in one filename:
ws.child("target/" + arch + ".out").touch(System.currentTimeMillis());
return true;
}
}
/** Test copying artifacts from all configurations of a matrix job */
@Test
public void testMatrixAll() throws Exception {
MatrixProject mp = createMatrixProject();
mp.setAxes(new AxisList(new Axis("ARCH", "sparc", "x86")));
mp.getBuildersList().add(new ArchMatrixBuilder());
mp.getPublishersList().add(new ArtifactArchiver("target/*", "", false, false));
rule.assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get());
FreeStyleProject p = createProject(mp.getName(), null, "", "", true, false, false, true);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "ARCH=sparc/target/readme.txt", b);
assertFile(true, "ARCH=sparc/target/sparc.out", b);
assertFile(true, "ARCH=x86/target/readme.txt", b);
assertFile(true, "ARCH=x86/target/x86.out", b);
}
private MavenModuleSet setupMavenJob() throws Exception {
ToolInstallations.configureDefaultMaven();
MavenModuleSet mp = createMavenProject();
mp.setGoals("clean package");
mp.setScm(new ExtractResourceSCM(getClass().getResource("maven-job.zip")));
return mp;
}
private static final VersionNumber MAVEN_POM_CUTOFF = new VersionNumber("1.405");
private static String pomName(String module, String version) {
return module + '/' + version + '/' +
(MAVEN_POM_CUTOFF.isNewerThan(Hudson.getVersion()) ? "pom.xml"
: (module + '-' + version + ".pom"));
}
/** Test copying from a particular module of a maven job */
@Test
public void testMavenJob() throws Exception {
MavenModuleSet mp = setupMavenJob();
rule.assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get());
FreeStyleProject p = createProject(mp.getName() + "/org.jvnet.hudson.main.test.multimod$moduleB",
null, "", "", true, false, false, true);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
String dir = "org.jvnet.hudson.main.test.multimod/";
assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b);
assertFile(true, dir + pomName("moduleB", "1.0-SNAPSHOT"), b);
}
/** Test copying all artifacts from a maven job */
@Test
public void testMavenAll() throws Exception {
MavenModuleSet mp = setupMavenJob();
rule.assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get());
FreeStyleProject p = createProject(mp.getName(), null, "", "", true, false, false, true);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
String dir = "org.jvnet.hudson.main.test.multimod/";
assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b);
assertFile(true, dir + pomName("moduleA", "1.0-SNAPSHOT"), b);
assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b);
assertFile(true, dir + pomName("moduleB", "1.0-SNAPSHOT"), b);
assertFile(true, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b);
assertFile(true, dir + pomName("moduleC", "1.0-SNAPSHOT"), b);
// Test with filter
p = createProject(mp.getName(), null, "**/*.jar", "", true, false, false, true);
b = p.scheduleBuild2(0, new UserCause()).get();
assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleA", "1.0-SNAPSHOT"), b);
assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b);
assertFile(true, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleC", "1.0-SNAPSHOT"), b);
}
/** Test copying from maven job where artifacts manually archived instead of automatic */
@Test
public void testMavenJobWithArchivePostBuildStep() throws Exception {
MavenModuleSet mp = setupMavenJob();
// Turn off automatic archiving and use a post-build step instead.
// Artifacts will be stored with the parent build instead of the child module builds.
mp.setIsArchivingDisabled(true);
mp.getPublishersList().add(new ArtifactArchiver("moduleB/*.xml", "", false, false));
rule.assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get());
FreeStyleProject p = createProject(mp.getName(), null, "", "", true, false, false, true);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
// Archived artifact should be copied:
assertFile(true, "moduleB/pom.xml", b);
// None of the maven artifacts should be archived or copied:
String dir = "org.jvnet.hudson.main.test.multimod/";
assertFile(false, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleA", "1.0-SNAPSHOT"), b);
assertFile(false, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b);
assertFile(false, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleC", "1.0-SNAPSHOT"), b);
}
/** Test copy from workspace instead of artifacts area */
@Test
public void testCopyFromWorkspace() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(), p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), null, new WorkspaceSelector(),
"**/*.txt", "", true, false, true));
// Run a build that places a file in the workspace, but does not archive anything
other.getBuildersList().add(new ArtifactBuilder());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "subfoo.txt", b);
assertFile(false, "c.log", b);
}
/** Test copy from workspace containing default ant excludes */
@Test
public void testCopyFromWorkspaceWithDefaultExcludes() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(), p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "", new WorkspaceSelector(),
"", "", false, false));
// Run a build that places a file in the workspace, but does not archive anything
other.getBuildersList().add(new ArtifactBuilder());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, ".hg/defaultexclude.txt", b);
}
@Test
public void testExcludes() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(), p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "", new WorkspaceSelector(),
"**", ".hg/**", "", false, false, true));
// Run a build that places a file in the workspace, but does not archive anything
other.getBuildersList().add(new ArtifactBuilder());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "subdir/subfoo.txt", b);
assertFile(false, ".hg/defaultexclude.txt", b);
}
@Test
public void testCopyFromWorkspaceWithDefaultExcludesWithFlatten() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(), p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "", new WorkspaceSelector(),
"", "", true, false));
// Run a build that places a file in the workspace, but does not archive anything
other.getBuildersList().add(new ArtifactBuilder());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "defaultexclude.txt", b);
}
@Test
public void testExcludesWithFlatten() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(), p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "", new WorkspaceSelector(),
"**", ".hg/**", "", true, false, true));
// Run a build that places a file in the workspace, but does not archive anything
other.getBuildersList().add(new ArtifactBuilder());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "subfoo.txt", b);
assertFile(false, "defaultexclude.txt", b);
}
/** projectName in CopyArtifact build steps should be updated if a job is renamed */
@Test
public void testJobRename() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "", "", true, false, false, true);
assertEquals("before", other.getName(),
((CopyArtifact)p.getBuilders().get(0)).getProjectName());
String newName = other.getName() + "-new";
other.renameTo(newName);
assertEquals("after", newName,
((CopyArtifact)p.getBuilders().get(0)).getProjectName());
// Test reference to a matrix configuration
MatrixProject otherm = createMatrixProject(),
mp = createMatrixProject();
mp.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(otherm.getName(), "FOO=$FOO",
new SavedBuildSelector(), "", "", false, false, true));
assertEquals("before", otherm.getName(),
((CopyArtifact)mp.getBuilders().get(0)).getProjectName());
otherm.renameTo(newName = otherm.getName() + "-new");
assertEquals("after", newName,
((CopyArtifact)mp.getBuilders().get(0)).getProjectName());
}
@Test
public void testSavedBuildSelector() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
other.addProperty(paramsDef);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new SavedBuildSelector(), "*.txt", "", false, false, true));
FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get();
rule.assertBuildStatusSuccess(b);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
b.keepLog(true);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
}
@Test
public void testSpecificBuildSelector() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
other.addProperty(paramsDef);
SpecificBuildSelector sbs = new SpecificBuildSelector("1");
assertEquals("1", sbs.getBuildNumber());
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), null, sbs, "*.txt", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
}
@Test
public void testSpecificBuildSelectorParameter() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParameterDefinition paramDef2 = new StringParameterDefinition("BAR", "1");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
other.addProperty(paramsDef);
ParametersDefinitionProperty paramsDef2 = new ParametersDefinitionProperty(paramDef2);
p.addProperty(paramsDef2);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new SpecificBuildSelector("$BAR"), "*.txt", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("BAR", "1"))).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
}
@Test
public void testParameterizedBuildSelector() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
ParameterDefinition pParamDef = new StringParameterDefinition("PBS", "foo");
ParametersDefinitionProperty pParamsDef = new ParametersDefinitionProperty(pParamDef);
p.addProperty(pParamsDef);
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
other.addProperty(paramsDef);
ParameterizedBuildSelector pbs = new ParameterizedBuildSelector("PBS");
assertEquals("PBS", pbs.getParameterName());
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), null, pbs, "*.txt", "", false, false, true));
FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get();
rule.assertBuildStatusSuccess(b);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
b.keepLog(true);
b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("PBS", "<SavedBuildSelector/>"))).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
}
@Test
public void testPermalinkBuildSelector() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
other.addProperty(paramsDef);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new PermalinkBuildSelector("lastStableBuild"), "*.txt", "", false, false, true));
FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get();
rule.assertBuildStatusSuccess(b);
other.getBuildersList().add(new UnstableBuilder());
rule.assertBuildStatus(Result.UNSTABLE, other.scheduleBuild2(0, new UserCause()).get());
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
// Invalid permalink
p.getBuildersList().replace(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new PermalinkBuildSelector("fooBuild"), "*.txt", "", false, false, true));
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testTriggeredBuildSelector() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new TriggeredBuildSelector(false), "*.txt", "", false, false, true));
other.getPublishersList().add(new BuildTrigger(p.getFullName(), false));
rule.jenkins.rebuildDependencyGraph();
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
// p#1 was triggered, now building.
FreeStyleBuild b = p.getBuildByNumber(1);
for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); }
assertNotNull(b);
while (b.isBuilding()) Thread.sleep(10);
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
// Verify error if build not triggered by upstream job:
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
// test fallback
//run a failing build to make sure the fallback selects the last successful build
other.getPublishersList().clear();
other.getBuildersList().add(new FailureBuilder());
rule.assertBuildStatus(Result.FAILURE, other.scheduleBuild2(0, new UserCause()).get());
p.getBuildersList().remove(CopyArtifact.class);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new TriggeredBuildSelector(true), "*.txt", "", false, false, true));
rule.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testTriggeredBuildSelectorWithParentOfParent() throws Exception {
FreeStyleProject grandparent = createArtifactProject(),
parent = rule.createFreeStyleProject(),
p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(grandparent.getName(), null,
new TriggeredBuildSelector(false), "*.txt", "", false, false, true));
parent.getPublishersList().add(new BuildTrigger(p.getFullName(), false));
grandparent.getPublishersList().add(new BuildTrigger(parent.getFullName(), false));
rule.jenkins.rebuildDependencyGraph();
rule.assertBuildStatusSuccess(grandparent.scheduleBuild2(0, new UserCause()));
// parent#1 was triggered
FreeStyleBuild b = parent.getBuildByNumber(1);
for (int i = 0; b == null && i < 2000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); }
assertNotNull(b);
while (b.isBuilding()) Thread.sleep(10);
rule.assertBuildStatusSuccess(b);
// p#1 was triggered, now building.
b = p.getBuildByNumber(1);
for (int i = 0; b == null && i < 2000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); }
assertNotNull(b);
while (b.isBuilding()) Thread.sleep(10);
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
// Verify error if build not triggered by upstream job:
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
// test fallback
//run a failing build to make sure the fallback selects the last successful build
grandparent.getPublishersList().clear();
grandparent.getBuildersList().add(new FailureBuilder());
rule.assertBuildStatus(Result.FAILURE, grandparent.scheduleBuild2(0, new UserCause()).get());
p.getBuildersList().remove(CopyArtifact.class);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(grandparent.getName(), null,
new TriggeredBuildSelector(true), "*.txt", "", false, false, true));
rule.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0, new UserCause()).get());
}
/**
* When copying from a particular matrix configuration, the upstream project
* is the matrix parent.
*/
@Test
public void testTriggeredBuildSelectorFromMatrix() throws Exception {
MatrixProject other = createMatrixArtifactProject();
FreeStyleProject p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName() + "/FOO=two",
null, new TriggeredBuildSelector(false), "*.txt", "", false, false, true));
other.getPublishersList().add(new BuildTrigger(p.getFullName(), false));
rule.jenkins.rebuildDependencyGraph();
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
// p#1 was triggered, now building.
FreeStyleBuild b = p.getBuildByNumber(1);
for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); }
assertNotNull(b);
while (b.isBuilding()) Thread.sleep(10);
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
assertFile(true, "two.txt", b);
}
/**
* When copying to a matrix job, need to check the upstream cause of the
* matrix parent.
*/
@Test
public void testTriggeredBuildSelectorToMatrix() throws Exception {
FreeStyleProject other = createArtifactProject();
MatrixProject p = createMatrixProject();
p.setAxes(new AxisList(new Axis("FOO", "one", "two")));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(),
null, new TriggeredBuildSelector(false), "*.txt", "", false, false, true));
other.getPublishersList().add(new BuildTrigger(p.getFullName(), false));
rule.jenkins.rebuildDependencyGraph();
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
// p#1 was triggered, now building.
MatrixBuild b = p.getBuildByNumber(1);
for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); }
assertNotNull(b);
while (b.isBuilding()) Thread.sleep(10);
rule.assertBuildStatusSuccess(b);
MatrixRun r = b.getRuns().get(0);
assertFile(true, "foo.txt", r);
}
@Test
public void testFlatten() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = createProject(other.getName(), null, "", "newdir", false, true, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "newdir/foo.txt", b);
assertFile(true, "newdir/subfoo.txt", b);
assertFile(true, "newdir/c.log", b);
}
@Test
public void testOptional_MissingProject() throws Exception {
// Missing project still fails even when copy is optional
FreeStyleProject p = createProject("invalid", null, "", "", false, false, true, true);
rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testOptional_MissingBuild() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "", "", false, false, true, true);
rule.assertBuildStatusSuccess(p.scheduleBuild2(0, new UserCause()).get());
}
@Test
public void testOptional_MissingArtifact() throws Exception {
FreeStyleProject other = rule.createFreeStyleProject(),
p = createProject(other.getName(), null, "*.txt", "", false, false, true, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
rule.assertBuildStatusSuccess(p.scheduleBuild2(0, new UserCause()).get());
}
/**
* Test that a user is prevented from bypassing permissions on other jobs when configuring
* a copyartifact build step.
*/
@Test
public void testPermission() throws Exception {
// any users can be authenticated with the password same to the user id.
rule.jenkins.setSecurityRealm(rule.createDummySecurityRealm());
ProjectMatrixAuthorizationStrategy pmas = new ProjectMatrixAuthorizationStrategy();
pmas.add(Jenkins.READ, Jenkins.ANONYMOUS.getName());
pmas.add(Jenkins.READ, "joe");
rule.jenkins.setAuthorizationStrategy(pmas);
// only joe can access project "src"
FreeStyleProject src = rule.createFreeStyleProject();
{
Map<Permission, Set<String>> auths = new HashMap<Permission, Set<String>>();
auths.put(Item.READ, Sets.newHashSet("joe"));
src.addProperty(new AuthorizationMatrixProperty(auths));
}
// test access from anonymous
{
FreeStyleProject dest = rule.createFreeStyleProject();
dest.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
src.getName(),
"",
new StatusBuildSelector(true),
"",
"",
false,
false,
true
));
Map<Permission, Set<String>> auths = new HashMap<Permission, Set<String>>();
auths.put(Item.READ, Sets.newHashSet(Jenkins.ANONYMOUS.getName()));
auths.put(Item.CONFIGURE, Sets.newHashSet(Jenkins.ANONYMOUS.getName()));
dest.addProperty(new AuthorizationMatrixProperty(auths));
WebClient wc = rule.createWebClient();
try {
wc.getPage(src);
fail("Job should not be accessible to anonymous");
} catch(FailingHttpStatusCodeException e) {
assertEquals("Job should not be accessible to anonymous", 404, e.getStatusCode());
}
rule.submit(wc.getPage(dest, "configure").getFormByName("config"));
dest = rule.jenkins.getItemByFullName(dest.getFullName(), FreeStyleProject.class);
CopyArtifact ca = dest.getBuildersList().getAll(CopyArtifact.class).get(0);
assertEquals("Should ignore/clear value for inaccessible project", "", ca.getProjectName());
}
// test access from joe
{
FreeStyleProject dest = rule.createFreeStyleProject();
dest.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
src.getName(),
"",
new StatusBuildSelector(true),
"",
"",
false,
false,
true
));
Map<Permission, Set<String>> auths = new HashMap<Permission, Set<String>>();
auths.put(Item.READ, Sets.newHashSet("joe"));
auths.put(Item.CONFIGURE, Sets.newHashSet("joe"));
dest.addProperty(new AuthorizationMatrixProperty(auths));
WebClient wc = rule.createWebClient();
wc.login("joe", "joe");
assertNotNull(wc.getPage(src));
rule.submit(wc.getPage(dest, "configure").getFormByName("config"));
dest = rule.jenkins.getItemByFullName(dest.getFullName(), FreeStyleProject.class);
CopyArtifact ca = dest.getBuildersList().getAll(CopyArtifact.class).get(0);
assertEquals("Should ignore/clear value for inaccessible project", src.getName(), ca.getProjectName());
}
}
/**
* When the source project name is parameterized, cannot check at configure time whether
* the project is accessible. In this case, permission check is done when the build runs.
* Only jobs accessible to all authenticated users are allowed.
*/
@LocalData
@Test
public void testPermissionWhenParameterized() throws Exception {
FreeStyleProject p = createProject("test$JOB", null, "", "", false, false, false, true);
ParameterDefinition paramDef = new StringParameterDefinition("JOB", "job1");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
p.addProperty(paramsDef);
// Build step should succeed when this parameter expands to a job accessible
// to authenticated users (even if triggered by anonymous, as in this case):
SecurityContextHolder.clearContext();
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("JOB", "Job2"))).get();
assertFile(true, "foo2.txt", b);
rule.assertBuildStatusSuccess(b);
// Build step should fail for a job not accessible to all authenticated users,
// even when accessible to the user starting the job, as in this case:
SecurityContext old = ACL.impersonate(
new UsernamePasswordAuthenticationToken("joe","joe"));
try {
b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("JOB", "Job"))).get();
assertFile(false, "foo.txt", b);
rule.assertBuildStatus(Result.FAILURE, b);
} finally {
SecurityContextHolder.setContext(old);
}
}
@LocalData
@Test
public void testPermissionWhenParameterizedForMatrixConfig() throws Exception {
// This test fails before Jenkins 1.406
if (new VersionNumber("1.406").isNewerThan(Hudson.getVersion())) return; // Skip
FreeStyleProject p = createProject("testMatrix/FOO=$FOO", null, "", "", false, false, false, true);
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "FOO");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
p.addProperty(paramsDef);
// Build step should succeed when this parameter expands to a job accessible to
// authenticated users, even when selecting a single matrix config, not the parent job:
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "foo"))).get();
assertFile(true, "foo.txt", b);
rule.assertBuildStatusSuccess(b);
}
@LocalData
@Test
public void testPermissionWhenParameterizedForMavenModule() throws Exception {
// This test fails before Jenkins 1.406
if (new VersionNumber("1.406").isNewerThan(Hudson.getVersion())) return; // Skip
MavenModuleSet mp = setupMavenJob();
mp.addProperty(new AuthorizationMatrixProperty(
Collections.singletonMap(Item.READ, Collections.singleton("authenticated"))));
rule.assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get());
FreeStyleProject p = createProject(mp.getName() + "/org.jvnet.hudson.main.test.multimod$FOO",
null, "", "", false, false, false, true);
ParameterDefinition paramDef = new StringParameterDefinition("FOO", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
p.addProperty(paramsDef);
// Build step should succeed when this parameter expands to a job accessible to
// authenticated users, even when selecting a single maven module, not the parent job:
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "$moduleA"))).get();
String dir = "org.jvnet.hudson.main.test.multimod/";
assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b);
assertFile(true, dir + pomName("moduleA", "1.0-SNAPSHOT"), b);
assertFile(false, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b);
assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b);
rule.assertBuildStatusSuccess(b);
}
/**
* Test that info about selected builds is added into the environment for later build steps.
*/
@Test
public void testEnvData() throws Exception {
// Also test conversion of job name to env var name, only keeping letters:
FreeStyleProject other = createArtifactProject("My (Test) Job"),
p = createProject(other.getName(), null, "", "", false, false, false, true);
CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder();
p.getBuildersList().add(envStep);
// Bump up the build number a bit:
for (int i = 0; i < 3; i++) other.assignBuildNumber();
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("4", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_MY_TEST_JOB"));
}
@Issue("JENKINS-16028")
@Test
public void testEnvDataInMavenProject() throws Exception {
FreeStyleProject upstream = rule.createFreeStyleProject("upstream");
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "foobar"));
upstream.getPublishersList().add(new ArtifactArchiver("**/*", "", false, false));
FreeStyleBuild upstreamBuild = upstream.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(upstreamBuild);
MavenModuleSet downstream = setupMavenJob();
downstream.getPrebuilders().add(CopyArtifactUtil.createCopyArtifact(
"upstream",
"",
new SpecificBuildSelector(Integer.toString(upstreamBuild.getNumber())),
"**/*",
"",
"",
false,
false,
false
));
CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder();
downstream.getPrebuilders().add(envStep);
MavenModuleSetBuild downstreamBuild = downstream.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(downstreamBuild);
assertFile(true, "artifact.txt", downstreamBuild);
assertEquals(
Integer.toString(upstreamBuild.getNumber()),
envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_UPSTREAM")
);
}
@Issue("JENKINS-18762")
@Test
public void testEnvDataWrapped() throws Exception {
FreeStyleProject upstream = rule.createFreeStyleProject("upstream");
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "foobar"));
upstream.getPublishersList().add(new ArtifactArchiver("**/*", "", false, false));
FreeStyleBuild upstreamBuild = upstream.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(upstreamBuild);
FreeStyleProject downstream = rule.createFreeStyleProject();
downstream.getBuildersList().add(new WrapperBuilder(CopyArtifactUtil.createCopyArtifact(
"upstream",
"",
new SpecificBuildSelector(Integer.toString(upstreamBuild.getNumber())),
"**/*",
"",
"",
false,
false,
false
)));
CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder();
downstream.getBuildersList().add(envStep);
FreeStyleBuild downstreamBuild = downstream.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(downstreamBuild);
assertFile(true, "artifact.txt", downstreamBuild);
assertEquals(
Integer.toString(upstreamBuild.getNumber()),
envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_UPSTREAM")
);
}
/**
* Test filtering on parameters, ie. last stable build with parameter FOO=bar.
*/
@Test
public void testFilterByParameters() throws Exception {
FreeStyleProject other = createArtifactProject("Foo job");
other.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("FOO", ""),
new BooleanParameterDefinition("BAR", false, ""),
new ChoiceParameterDefinition("BAZ", new String[] { "foo", "bar", "baz" }, "")));
// #1: FOO=foo BAR=false BAZ=baz
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(
new StringParameterValue("FOO", "foo"),
new BooleanParameterValue("BAR", false),
new StringParameterValue("BAZ", "baz"))).get());
// #2: FOO=bar BAR=true BAZ=foo
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(
new StringParameterValue("FOO", "bar"),
new BooleanParameterValue("BAR", true),
new StringParameterValue("BAZ", "foo"))).get());
// #3: FOO=foo BAR=true BAZ=bar
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(
new StringParameterValue("FOO", "foo"),
new BooleanParameterValue("BAR", true),
new StringParameterValue("BAZ", "bar"))).get());
FreeStyleProject p = createProject(other.getName(), "FOO=bar", "*.txt", "", true, false, false, true);
CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder();
p.getBuildersList().add(envStep);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
p = createProject(other.getName(), "BAR=false", "*.txt", "", true, false, false, true);
p.getBuildersList().add(envStep);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("1", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
p = createProject(other.getName(), "BAZ=foo,BAR=true", "*.txt", "", true, false, false, true);
p.getBuildersList().add(envStep);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
p = createProject(other.getName(), "FOO=foo,BAR=false,BAZ=baz", "*.txt", "", true, false, false, true);
p.getBuildersList().add(envStep);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("1", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
p = createProject(other.getName(), "BAZ=bar,FOO=bogus", "*.txt", "", true, false, false, true);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatus(Result.FAILURE, b);
// Test matching other build variables besides parameters
p = createProject(other.getName(), "BUILD_NUMBER=2", "*.txt", "", true, false, false, true);
p.getBuildersList().add(envStep);
b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
// Test coverage for EnvAction
boolean ok = false;
for (Action a : b.getActions()) {
if ("hudson.plugins.copyartifact.CopyArtifact$EnvAction".equals(a.getClass().getName())) {
assertNull(a.getIconFileName());
assertNull(a.getDisplayName());
assertNull(a.getUrlName());
ok = true;
}
}
assertTrue(ok);
}
@Test
public void testFilterByMetaParameters() throws Exception {
FreeStyleProject other = createArtifactProject("Foo job");
other.addProperty(new ParametersDefinitionProperty(new BooleanParameterDefinition("BAR", false, "")));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(new BooleanParameterValue("BAR", false))).get());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(new BooleanParameterValue("BAR", true))).get());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(new BooleanParameterValue("BAR", false))).get());
FreeStyleProject p = createProject(other.getName(), "$VAR=true", "*.txt", "", true, false, false, true);
p.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("VAR", "")));
CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder();
p.getBuildersList().add(envStep);
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("VAR", "BAR"))).get();
rule.assertBuildStatusSuccess(b);
assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB"));
}
@Test
public void testSavedBuildSelectorWithParameterFilter() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
other.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", "")));
FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "buildone"))).get();
rule.assertBuildStatusSuccess(b);
b.keepLog(true);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "FOO=buildone",
new SavedBuildSelector(), "*.txt", "", false, false, true));
rule.assertBuildStatusSuccess(b = other.scheduleBuild2(0, new UserCause()).get());
b.keepLog(true); // Keep #2 too, but it doesn't have FOO=buildone so should not be selected
rule.assertBuildStatusSuccess(b = p.scheduleBuild2(0, new UserCause()).get());
assertFile(true, "foo.txt", b);
assertFile(true, "buildone.txt", b);
assertFile(false, "subdir/subfoo.txt", b);
}
// Verify build fails if given build# does not match params
@Test
public void testSpecificBuildSelectorWithParameterFilter() throws Exception {
FreeStyleProject other = createArtifactProject(),
p = rule.createFreeStyleProject();
other.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", "")));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(other.getName(), "FOO=bogus",
new SpecificBuildSelector("1"), "*.txt", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(),
new ParametersAction(new StringParameterValue("FOO", "foo"))).get());
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()));
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatus(Result.FAILURE, b);
assertFile(false, "foo.txt", b);
}
// Verify BuildSelector defaults to false
@Test
public void testBuildSelectorDefault() {
assertFalse(new BuildSelector() { }.isSelectable(null, null));
}
// Test field getters
@Test
public void testFields() throws Exception {
FreeStyleProject p = rule.createFreeStyleProject();
CopyArtifact ca = CopyArtifactUtil.createCopyArtifact(p.getFullName(), null, new SavedBuildSelector(), "filter", "target", false, true, true);
assertEquals(p.getFullName(), ca.getProjectName());
assertSame(SavedBuildSelector.class, ca.getBuildSelector().getClass());
assertEquals("filter", ca.getFilter());
assertEquals("target", ca.getTarget());
assertFalse(ca.isFlatten());
assertTrue(ca.isOptional());
ca = CopyArtifactUtil.createCopyArtifact("foo", null, null, null, null, true, false, true);
assertTrue(ca.isFlatten());
assertFalse(ca.isOptional());
}
@Test
public void testFieldValidation() throws Exception {
FreeStyleProject p = rule.createFreeStyleProject();
CopyArtifact.DescriptorImpl descriptor = rule.jenkins.getDescriptorByType(CopyArtifact.DescriptorImpl.class);
assertNotNull(descriptor);
// Valid value
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, p.getFullName()).kind);
// Empty value
assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjectName(p, "").kind);
// Parameterized value
assertSame(FormValidation.Kind.WARNING, descriptor.doCheckProjectName(p, "$FOO").kind);
//JENKINS-32526: Check that it behaves gracefully for an unknown context.
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, p.getFullName()).kind);
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "").kind);
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "$FOO").kind);
// Just returns OK if no permission
rule.jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy());
SecurityContextHolder.clearContext();
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, "").kind);
assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(null, "").kind);
// Other descriptor methods
assertTrue(descriptor.isApplicable(null));
assertTrue(descriptor.getDisplayName().length() > 0);
}
@LocalData
@Test
public void testProjectNameSplit() throws Exception {
FreeStyleProject copier = Jenkins.getInstance().getItemByFullName("copier", FreeStyleProject.class);
assertNotNull(copier);
String configXml = copier.getConfigFile().asString();
assertFalse(configXml, configXml.contains("<projectName>"));
assertTrue(configXml, configXml.contains("<project>plain</project>"));
assertTrue(configXml, configXml.contains("<project>parameterized</project>"));
assertTrue(configXml, configXml.contains("<parameters>good=true</parameters>"));
assertTrue(configXml, configXml.contains("<project>matrix/which=two</project>"));
MatrixProject matrixCopier = Jenkins.getInstance().getItemByFullName("matrix-copier", MatrixProject.class);
assertNotNull(matrixCopier);
configXml = matrixCopier.getConfigFile().asString();
assertFalse(configXml, configXml.contains("<projectName>"));
// When a project is specified with a variable, it is split improperly.
assertTrue(configXml, configXml.contains("<project>matrix</project>"));
assertTrue(configXml, configXml.contains("<parameters>which=${which}</parameters>"));
}
// A builder wrapping another builder.
public static class WrapBuilder extends Builder {
private Builder wrappedBuilder;
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
return wrappedBuilder.perform(build, launcher, listener);
}
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
@Override
public String getDisplayName() {
return "WrapBuilder";
}
}
}
@LocalData
@Test
public void testWrappedCopierProjectNameSplit() throws Exception {
// Project "copier" is configured with CopyArtifact wrapped with WrapBuilder.
// This causes failure of upgrading on loaded.
// Upgrading is performed when build is triggered.
FreeStyleProject copier = Jenkins.getInstance().getItemByFullName("copier", FreeStyleProject.class);
assertNotNull(copier);
String configXml = copier.getConfigFile().asString();
// not upgraded on loaded
assertTrue(configXml, configXml.contains("<projectName>plain</projectName>"));
// upgraded when a build is triggered.
FreeStyleBuild b = copier.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
FilePath fileToTest = b.getWorkspace().child("from-plain/tag.txt");
assertTrue(fileToTest.exists());
assertEquals("jenkins-plain-2\n", fileToTest.readToString());
configXml = copier.getConfigFile().asString();
assertFalse(configXml, configXml.contains("<projectName>"));
assertTrue(configXml, configXml.contains("<project>plain</project>"));
}
@Issue("JENKINS-17447")
@LocalData
@Test
public void testRenameBeforeProjectNameSplit() throws Exception {
rule.jenkins.getItemByFullName("old", FreeStyleProject.class).renameTo("new");
FreeStyleProject nue = rule.jenkins.getItemByFullName("new", FreeStyleProject.class);
rule.assertBuildStatusSuccess(nue.scheduleBuild2(0));
FreeStyleProject copier = rule.jenkins.getItemByFullName("copier", FreeStyleProject.class);
rule.assertBuildStatusSuccess(copier.scheduleBuild2(0));
assertEquals("jenkins-new-1\n", copier.getLastBuild().getWorkspace().child("stuff").readToString());
}
@Test
public void testRelative() throws Exception {
MockFolder folder = rule.jenkins.createProject(MockFolder.class, "folder");
FreeStyleProject other = folder.createProject(FreeStyleProject.class, "foo");
other.getBuildersList().add(new ArtifactBuilder());
other.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
FreeStyleProject p = createProject("folder/foo", null, "", "", true, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
}
@Test
public void testAbsolute() throws Exception {
MockFolder folder = rule.jenkins.createProject(MockFolder.class, "folder");
FreeStyleProject other = folder.createProject(FreeStyleProject.class, "foo");
other.getBuildersList().add(new ArtifactBuilder());
other.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
FreeStyleProject p = createProject("/folder/foo", null, "", "", true, false, false, true);
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
}
@Issue("JENKINS-19833")
@Test
public void testMostlyAbsolute() throws Exception {
MockFolder folder = rule.jenkins.createProject(MockFolder.class, "folder");
FreeStyleProject other = folder.createProject(FreeStyleProject.class, "foo");
other.getBuildersList().add(new ArtifactBuilder());
other.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
MockFolder folder2 = rule.jenkins.createProject(MockFolder.class, "other");
FreeStyleProject p = folder2.createProject(FreeStyleProject.class, "bar");
// "folder/foo" should be resolved as "/folder/foo" even from "/other/bar", for backward compatibility
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact("folder/foo", null, new StatusBuildSelector(true), "", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
}
@Test
public void testAbsoluteFromFolder() throws Exception {
FreeStyleProject other = rule.jenkins.createProject(FreeStyleProject.class, "foo");
other.getBuildersList().add(new ArtifactBuilder());
other.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
MockFolder folder = rule.jenkins.createProject(MockFolder.class, "folder");
FreeStyleProject p = folder.createProject(FreeStyleProject.class, "bar");
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact("/foo", null, new StatusBuildSelector(true), "", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
}
@Test
public void testRelativeFromFolder() throws Exception {
FreeStyleProject other = rule.jenkins.createProject(FreeStyleProject.class, "foo");
other.getBuildersList().add(new ArtifactBuilder());
other.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
MockFolder folder = rule.jenkins.createProject(MockFolder.class, "folder");
FreeStyleProject p = folder.createProject(FreeStyleProject.class, "bar");
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact("../foo", null, new StatusBuildSelector(true), "", "", false, false, true));
rule.assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
}
@Test
public void testSameFolder() throws Exception {
Folder folder = rule.jenkins.createProject(Folder.class, "folder");
FreeStyleProject src = folder.createProject(FreeStyleProject.class, "src");
src.getBuildersList().add(new ArtifactBuilder());
src.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
rule.assertBuildStatusSuccess(src.scheduleBuild2(0));
FreeStyleProject dest = folder.createProject(FreeStyleProject.class, "dest");
dest.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(src.getName(), null, new StatusBuildSelector(true), "", "", false, false, true));
FreeStyleBuild b = dest.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
WebClient wc = rule.createWebClient();
rule.submit(wc.getPage(dest, "configure").getFormByName("config"));
dest = rule.jenkins.getItemByFullName(dest.getFullName(), FreeStyleProject.class);
CopyArtifact ca = (CopyArtifact)dest.getBuildersList().get(0);
assertEquals(src.getName(), ca.getProjectName());
}
@Test
public void testSameFolderFromMatrix() throws Exception {
Folder folder = rule.jenkins.createProject(Folder.class, "folder");
MatrixProject src = folder.createProject(MatrixProject.class, "src");
src.setAxes(new AxisList(new TextAxis("axis1", "value1", "value2")));
src.getBuildersList().add(new ArtifactBuilder());
src.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
rule.assertBuildStatusSuccess(src.scheduleBuild2(0));
String projectNameToCopyFrom = String.format("%s/axis1=value1", src.getName());
FreeStyleProject dest = folder.createProject(FreeStyleProject.class, "dest");
dest.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(projectNameToCopyFrom, null, new StatusBuildSelector(true), "", "", false, false, true));
FreeStyleBuild b = dest.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertFile(true, "foo.txt", b);
WebClient wc = rule.createWebClient();
rule.submit(wc.getPage(dest, "configure").getFormByName("config"));
dest = rule.jenkins.getItemByFullName(dest.getFullName(), FreeStyleProject.class);
CopyArtifact ca = (CopyArtifact)dest.getBuildersList().get(0);
assertEquals(projectNameToCopyFrom, ca.getProjectName());
}
@Issue("JENKINS-20940")
@Test
public void testSameFolderToMatrix() throws Exception {
Folder folder = rule.jenkins.createProject(Folder.class, "foler");
FreeStyleProject src = folder.createProject(FreeStyleProject.class, "src");
src.getBuildersList().add(new ArtifactBuilder());
src.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
rule.assertBuildStatusSuccess(src.scheduleBuild2(0));
MatrixProject dest = folder.createProject(MatrixProject.class, "dest");
dest.setAxes(new AxisList(new TextAxis("axis1", "value1", "value2")));
dest.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(src.getName(), null, new StatusBuildSelector(true), "", "", false, false, true));
MatrixBuild b = dest.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
for(MatrixRun r: b.getExactRuns()) {
assertFile(true, "foo.txt", r);
}
WebClient wc = rule.createWebClient();
rule.submit(wc.getPage(dest, "configure").getFormByName("config"));
dest = rule.jenkins.getItemByFullName(dest.getFullName(), MatrixProject.class);
CopyArtifact ca = (CopyArtifact)dest.getBuildersList().get(0);
assertEquals(src.getName(), ca.getProjectName());
}
@Test
@LocalData
public void testOldCopyArtifactConfigIsLoadedCorrectly() throws Exception {
FreeStyleProject p = (FreeStyleProject) rule.jenkins.getItem("copy-artifact");
CopyArtifact trigger = (CopyArtifact) p.getBuilders().get(0);
assertTrue(trigger.isFingerprintArtifacts());
}
@LocalData // enable Jenkins security
@Test
public void testCopyArtifactPermissionProperty() throws Exception {
// invalid permission configuration can hang builds.
final int TIMEOUT = 60;
// LocalData provides following user/password pairs:
// test1/test1 : have all privileges except accessing jobs.
User test1 = User.get("test1");
// Prepare projects:
// copiee: a project creates an artifact.
// copier: a project copies an artifact from copiee.
// matrixCopiee: a matrix project creates an artifact.
// matrixCopier: a matrix project copies an artifact from copiee.
// Only allowed users can access projects.
FreeStyleProject copiee = createArtifactProject();
FreeStyleProject copier = createProject("${copyfrom}", null, "foo.txt", "", false, false, false);
copier.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("copyfrom", copiee.getFullName())
));
MatrixProject matrixCopiee = createMatrixArtifactProject();
MatrixProject matrixCopier = createMatrixProject();
matrixCopier.setAxes(new AxisList(new Axis("FOO", "one", "two"))); // this matches axes of matrixCopiee
matrixCopier.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(matrixCopiee.getName() + "/FOO=$FOO", null,
new StatusBuildSelector(true), "", "", false, false));
// test permissions
// not all user can access projects.
assertFalse(copiee.getACL().hasPermission(test1.impersonate(), Item.READ));
assertFalse(copier.getACL().hasPermission(test1.impersonate(), Item.READ));
assertFalse(matrixCopiee.getACL().hasPermission(test1.impersonate(), Item.READ));
assertFalse(matrixCopier.getACL().hasPermission(test1.impersonate(), Item.READ));
// prepare an artifact
rule.assertBuildStatusSuccess(copiee.scheduleBuild2(0));
rule.assertBuildStatusSuccess(matrixCopiee.scheduleBuild2(0));
// Without CopyArtifactPermissionProperty, build fails with access check.
rule.assertBuildStatus(Result.FAILURE, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
rule.assertBuildStatus(Result.FAILURE, matrixCopier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
copiee.addProperty(new CopyArtifactPermissionProperty(copier.getFullName()));
matrixCopiee.addProperty(new CopyArtifactPermissionProperty(matrixCopier.getFullName()));
// By using CopyArtifactPermissionProperty,
// builds succeed.
rule.assertBuildStatusSuccess(copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
rule.assertBuildStatusSuccess(matrixCopier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
@Test
public void testWebConfiguration() throws Exception {
FreeStyleProject upstream1 = rule.createFreeStyleProject();
FreeStyleProject upstream2 = rule.createFreeStyleProject();
FreeStyleProject p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream1.getName(),
"",
new StatusBuildSelector(true),
"",
"",
"",
false,
true,
true,
""
));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream2.getName(),
"param=value",
new TriggeredBuildSelector(false),
"**",
"foobar.txt",
"targetdir",
true,
false,
false,
"SomeSuffix"
));
p.save();
WebClient wc = rule.createWebClient();
rule.submit(wc.getPage(p, "configure").getFormByName("config"));
p = rule.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
List<CopyArtifact> caList = p.getBuildersList().getAll(CopyArtifact.class);
assertEquals(2, caList.size());
{
CopyArtifact ca = caList.get(0);
assertEquals(upstream1.getName(), ca.getProjectName());
assertEquals(null, ca.getParameters());
assertEquals(StatusBuildSelector.class, ca.getBuildSelector().getClass());
assertEquals("", ca.getFilter());
assertEquals("", ca.getExcludes());
assertEquals("", ca.getTarget());
assertFalse(ca.isFlatten());
assertTrue(ca.isOptional());
assertTrue(ca.isFingerprintArtifacts());
assertNull(ca.getResultVariableSuffix());
}
{
CopyArtifact ca = caList.get(1);
assertEquals(upstream2.getName(), ca.getProjectName());
assertEquals("param=value", ca.getParameters());
assertEquals(TriggeredBuildSelector.class, ca.getBuildSelector().getClass());
assertEquals("**", ca.getFilter());
assertEquals("foobar.txt", ca.getExcludes());
assertEquals("targetdir", ca.getTarget());
assertTrue(ca.isFlatten());
assertFalse(ca.isOptional());
assertFalse(ca.isFingerprintArtifacts());
assertEquals("SomeSuffix", ca.getResultVariableSuffix());
}
}
private boolean isFilePermissionSupported() throws Exception {
return rule.jenkins.getRootPath().mode() != -1;
}
@Test
public void testFilePermission() throws Exception {
if (!isFilePermissionSupported()) {
Logger.getLogger(CopyArtifactTest.class.getName()).warning(String.format(
"Skipped %s as file permission is not supported on this platform",
name.getMethodName()
));
return;
}
FreeStyleProject copiee = rule.createFreeStyleProject();
FreeStyleBuild copieeBuild = copiee.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(copieeBuild);
// As I cannot trust ArtifactArchiver (JENKINS-14269),
// creates artifacts manually.
FilePath artifactDir = new FilePath(copieeBuild.getArtifactsDir());
artifactDir.child("artifact.txt").write("some content", Charset.defaultCharset().name());
artifactDir.child("artifact.txt").chmod(0644);
artifactDir.child("artifactWithExecute.txt").write("some content", Charset.defaultCharset().name());
artifactDir.child("artifactWithExecute.txt").chmod(0755);
artifactDir.child("subdir").mkdirs();
artifactDir.child("subdir/artifactInSubdir.txt").write("some content", Charset.defaultCharset().name());
artifactDir.child("subdir/artifactInSubdir.txt").chmod(0644);
artifactDir.child("subdir/artifactWithExecuteInSubdir.txt").write("some content", Charset.defaultCharset().name());
artifactDir.child("subdir/artifactWithExecuteInSubdir.txt").chmod(0755);
assertEquals(0644, artifactDir.child("artifact.txt").mode() & 0777);
assertEquals(0755, artifactDir.child("artifactWithExecute.txt").mode() & 0777);
assertEquals(0644, artifactDir.child("subdir/artifactInSubdir.txt").mode() & 0777);
assertEquals(0755, artifactDir.child("subdir/artifactWithExecuteInSubdir.txt").mode() & 0777);
// on master, without flatten
{
FreeStyleProject p = rule.createFreeStyleProject();
p.setAssignedNode(rule.jenkins);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
copiee.getFullName(),
"",
new SpecificBuildSelector(Integer.toString(copieeBuild.getNumber())),
"",
"",
"",
false,
false,
false
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertEquals(rule.jenkins, b.getBuiltOn());
FilePath w = b.getWorkspace();
assertEquals(0644, w.child("artifact.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecute.txt").mode() & 0777);
assertEquals(0644, w.child("subdir/artifactInSubdir.txt").mode() & 0777);
assertEquals(0755, w.child("subdir/artifactWithExecuteInSubdir.txt").mode() & 0777);
}
// on master, with flatten
{
FreeStyleProject p = rule.createFreeStyleProject();
p.setAssignedNode(rule.jenkins);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
copiee.getFullName(),
"",
new SpecificBuildSelector(Integer.toString(copieeBuild.getNumber())),
"",
"",
"",
true, // flatten
false,
false
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertEquals(rule.jenkins, b.getBuiltOn());
FilePath w = b.getWorkspace();
assertEquals(0644, w.child("artifact.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecute.txt").mode() & 0777);
assertEquals(0644, w.child("artifactInSubdir.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecuteInSubdir.txt").mode() & 0777);
}
DumbSlave node = rule.createOnlineSlave();
// on slave, without flatten
{
FreeStyleProject p = rule.createFreeStyleProject();
p.setAssignedNode(node);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
copiee.getFullName(),
"",
new SpecificBuildSelector(Integer.toString(copieeBuild.getNumber())),
"",
"",
"",
false,
false,
false
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertEquals(node, b.getBuiltOn());
FilePath w = b.getWorkspace();
assertEquals(0644, w.child("artifact.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecute.txt").mode() & 0777);
assertEquals(0644, w.child("subdir/artifactInSubdir.txt").mode() & 0777);
assertEquals(0755, w.child("subdir/artifactWithExecuteInSubdir.txt").mode() & 0777);
}
// on slave, with flatten
{
FreeStyleProject p = rule.createFreeStyleProject();
p.setAssignedNode(node);
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
copiee.getFullName(),
"",
new SpecificBuildSelector(Integer.toString(copieeBuild.getNumber())),
"",
"",
"",
true, // flatten
false,
false
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(b);
assertEquals(node, b.getBuiltOn());
FilePath w = b.getWorkspace();
assertEquals(0644, w.child("artifact.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecute.txt").mode() & 0777);
assertEquals(0644, w.child("artifactInSubdir.txt").mode() & 0777);
assertEquals(0755, w.child("artifactWithExecuteInSubdir.txt").mode() & 0777);
}
}
@Issue("JENKINS-20546")
@Test
public void testSymlinks() throws Exception {
FreeStyleProject p1 = rule.createFreeStyleProject("p1");
p1.getBuildersList().add(new TestBuilder() {
@Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
build.getWorkspace().child("plain").write("text", null);
build.getWorkspace().child("link1").symlinkTo("plain", listener);
build.getWorkspace().child("link2").symlinkTo("nonexistent", listener);
return true;
}
});
p1.getPublishersList().add(new ArtifactArchiver("**", "", false, false));
rule.buildAndAssertSuccess(p1);
FreeStyleProject p2 = rule.createFreeStyleProject("p2");
p2.getBuildersList().add(CopyArtifactUtil.createCopyArtifact("p1", null, new StatusBuildSelector(true), null, "", false, false, true));
FreeStyleBuild b = rule.buildAndAssertSuccess(p2);
FilePath ws = b.getWorkspace();
assertEquals("text", ws.child("plain").readToString());
assertEquals("plain", ws.child("link1").readLink());
assertEquals("nonexistent", ws.child("link2").readLink());
}
@Issue("JENKINS-32832")
@Test
public void testSymlinksInDirectory() throws Exception {
FreeStyleProject p1 = rule.createFreeStyleProject("p1");
p1.getBuildersList().add(new TestBuilder() {
@Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
build.getWorkspace().child("plain").write("text", null);
build.getWorkspace().child("dir").mkdirs();
build.getWorkspace().child("dir/link1").symlinkTo("../plain", listener);
return true;
}
});
p1.getPublishersList().add(new ArtifactArchiver("**"));
rule.buildAndAssertSuccess(p1);
FreeStyleProject p2 = rule.createFreeStyleProject("p2");
p2.getBuildersList().add(CopyArtifactUtil.createCopyArtifact("p1", null, new StatusBuildSelector(true), null, "", false, false, true));
FreeStyleBuild b = rule.buildAndAssertSuccess(p2);
FilePath ws = b.getWorkspace();
assertEquals("text", ws.child("plain").readToString());
assertEquals(
StringUtils.join(
new String[]{"..", "plain"},
File.separator
),
ws.child("dir/link1").readLink()
);
}
private static class TestQueueItemAuthenticator extends jenkins.security.QueueItemAuthenticator {
private final org.acegisecurity.Authentication auth;
public TestQueueItemAuthenticator(org.acegisecurity.Authentication auth) {
this.auth = auth;
}
@Override
@javax.annotation.CheckForNull
public org.acegisecurity.Authentication authenticate(Queue.Item item) {
return auth;
}
}
@LocalData
@Test
public void testQueueItemAuthenticator() throws Exception {
// This test may hang without timeout with improper authorization configuration.
int TIMEOUT = 60;
// LocalData provides following user/password pairs:
// admin/admin : have all privileges
// test1/test1 : have all privileges except accessing jobs.
// test2/test2 : have all privileges except accessing jobs.
User admin = User.get("admin");
User test1 = User.get("test1");
User test2 = User.get("test2");
// Prepare projects:
// copiee: a project creates an artifact.
// copier: a project copies an artifact from copiee.
// permissions:
// test1 can access copiee, copier
// test2 can access copier
//
FreeStyleProject copiee = createArtifactProject();
Map<Permission, Set<String>> copieePermissions
= new HashMap<Permission, Set<String>>();
copieePermissions.put(Item.READ, Sets.newHashSet(test1.getId()));
copiee.addProperty(new AuthorizationMatrixProperty(copieePermissions));
FreeStyleProject copier = createProject("${copyfrom}", null, "foo.txt", "", false, false, false);
copier.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("copyfrom", copiee.getFullName())
));
Map<Permission, Set<String>> copierPermissions
= new HashMap<Permission, Set<String>>();
copierPermissions.put(Item.READ, Sets.newHashSet(test1.getId(), test2.getId()));
copierPermissions.put(Item.BUILD, Sets.newHashSet(test1.getId(), test2.getId(), Jenkins.ANONYMOUS.getName()));
copier.addProperty(new AuthorizationMatrixProperty(copierPermissions));
// test permissions
assertTrue (copiee.getACL().hasPermission(admin.impersonate(), Item.READ));
assertTrue (copiee.getACL().hasPermission(test1.impersonate(), Item.READ));
assertFalse(copiee.getACL().hasPermission(test2.impersonate(), Item.READ));
assertTrue (copier.getACL().hasPermission(admin.impersonate(), Item.BUILD));
assertTrue (copier.getACL().hasPermission(test1.impersonate(), Item.BUILD));
assertTrue (copier.getACL().hasPermission(test2.impersonate(), Item.BUILD));
assertTrue (copier.getACL().hasPermission(Jenkins.ANONYMOUS, Item.BUILD));
// Computer.BUILD is required since Jenkins 1.521.
assertTrue (Jenkins.getInstance().getACL().hasPermission(admin.impersonate(), Computer.BUILD));
assertTrue (Jenkins.getInstance().getACL().hasPermission(test1.impersonate(), Computer.BUILD));
assertTrue (Jenkins.getInstance().getACL().hasPermission(test2.impersonate(), Computer.BUILD));
assertTrue (Jenkins.getInstance().getACL().hasPermission(Jenkins.ANONYMOUS, Computer.BUILD));
// prepare an artifact
rule.assertBuildStatusSuccess(copiee.scheduleBuild2(0));
// Without QueueItemAuthenticator, build fails with access check.
{
rule.assertBuildStatus(Result.FAILURE, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
// Set QueueItemAuthenticator to run with authorization of admin.
// This succeeds.
{
QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(
new TestQueueItemAuthenticator(admin.impersonate())
);
rule.assertBuildStatus(Result.SUCCESS, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
// Set QueueItemAuthenticator to run with authorization of test1.
// This succeeds.
{
QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(
new TestQueueItemAuthenticator(test1.impersonate())
);
rule.assertBuildStatus(Result.SUCCESS, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
// Set QueueItemAuthenticator to run with authorization of test2.
// This fails.
{
QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(
new TestQueueItemAuthenticator(test2.impersonate())
);
rule.assertBuildStatus(Result.FAILURE, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
// Set QueueItemAuthenticator to run with anonymous authentication.
// This fails.
{
QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(
new TestQueueItemAuthenticator(Jenkins.ANONYMOUS)
);
rule.assertBuildStatus(Result.FAILURE, copier.scheduleBuild2(0).get(TIMEOUT, TimeUnit.SECONDS));
}
}
@Issue("JENKINS-28972")
@LocalData
@WithPlugin("copyartifact-extension-test.hpi") // JENKINS-28792 reproduces only when classes are located in different class loaders.
@Test
public void testSimpleBuildSelectorDescriptorInOtherPlugin() throws Exception {
WebClient wc = rule.createWebClient();
// An extension using SimpleBuildSelectorDescriptorSelector
{
FreeStyleProject p = rule.jenkins.getItemByFullName("UsingSimpleBuildSelectorDescriptorSelector", FreeStyleProject.class);
assertNotNull(p);
wc.getPage(p, "configure");
}
// An extension using SimpleBuildSelectorDescriptorSelector without configuration pages.
{
FreeStyleProject p = rule.jenkins.getItemByFullName("NoConfigPageSimpleBuildSelectorDescriptorSelector", FreeStyleProject.class);
assertNotNull(p);
wc.getPage(p, "configure");
}
// An extension extending SimpleBuildSelectorDescriptorSelector.
// (Even though generally it is useless)
{
FreeStyleProject p = rule.jenkins.getItemByFullName("ExtendingSimpleBuildSelectorDescriptorSelector", FreeStyleProject.class);
assertNotNull(p);
wc.getPage(p, "configure");
}
}
@Test
public void testIsValidVariableName() throws Exception {
assertTrue(CopyArtifact.isValidVariableName("VarName"));
assertTrue(CopyArtifact.isValidVariableName("Var_Name"));
assertFalse(CopyArtifact.isValidVariableName(null));
assertFalse(CopyArtifact.isValidVariableName(""));
assertFalse(CopyArtifact.isValidVariableName(" "));
assertFalse(CopyArtifact.isValidVariableName("=/?!\""));
}
@Test
public void testResultVariableSuffix() throws Exception {
FreeStyleProject srcProject = createArtifactProject("SRC-PROJECT1");
FreeStyleBuild srcBuild = srcProject.scheduleBuild2(0).get();
rule.assertBuildStatusSuccess(srcBuild);
// if no result variable suffix is provided
// the default suffix (SRC_PROJECT) is used.
{
FreeStyleProject p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
srcProject.getFullName(),
null, // parameters
new PermalinkBuildSelector("lastStableBuild"),
"*.txt", // filter
"", // excludes
"", // target
false, // flatten
false, // optional
true, // fingerprintArtifacts
"" // resultVariableSuffix
));
CaptureEnvironmentBuilder ceb = new CaptureEnvironmentBuilder();
p.getBuildersList().add(ceb);
rule.assertBuildStatusSuccess(p.scheduleBuild2(0));
assertEquals(
Integer.toString(srcBuild.getNumber()),
ceb.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_SRC_PROJECT_")
);
}
// if result variable suffix is provided
// it is used for the variable name to store.
{
FreeStyleProject p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
srcProject.getFullName(),
null, // parameters
new PermalinkBuildSelector("lastStableBuild"),
"*.txt", // filter
"", // excludes
"", // target
false, // flatten
false, // optional
true, // fingerprintArtifacts
"DEST1" // resultVariableSuffix
));
CaptureEnvironmentBuilder ceb = new CaptureEnvironmentBuilder();
p.getBuildersList().add(ceb);
rule.assertBuildStatusSuccess(p.scheduleBuild2(0));
assertEquals(
Integer.toString(srcBuild.getNumber()),
ceb.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_DEST1")
);
assertNull(ceb.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_SRC_PROJECT_"));
}
// if result variable suffix is invalid,
// the default suffix (SRC_PROJECT) is used.
{
FreeStyleProject p = rule.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
srcProject.getFullName(),
null, // parameters
new PermalinkBuildSelector("lastStableBuild"),
"*.txt", // filter
"", // excludes
"", // target
false, // flatten
false, // optional
true, // fingerprintArtifacts
"= =!?" // resultVariableSuffix
));
CaptureEnvironmentBuilder ceb = new CaptureEnvironmentBuilder();
p.getBuildersList().add(ceb);
rule.assertBuildStatusSuccess(p.scheduleBuild2(0));
assertEquals(
Integer.toString(srcBuild.getNumber()),
ceb.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_SRC_PROJECT_")
);
}
}
}