Skip to content

Commit

Permalink
Merge pull request #111 from jglick/withCredentialsId-JENKINS-45806
Browse files Browse the repository at this point in the history
[JENKINS-45806] withCredentialsId needed
  • Loading branch information
jglick committed Aug 24, 2017
2 parents 622153c + 8a429bf commit df23704
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 4 deletions.
16 changes: 13 additions & 3 deletions src/main/java/hudson/plugins/mercurial/HgExe.java
Expand Up @@ -151,10 +151,20 @@ public HgExe(@CheckForNull MercurialInstallation inst, @CheckForNull StandardUse
} finally {
os.close();
}
for (ArgumentListBuilder b : new ArgumentListBuilder[] {base, baseNoDebug}) {
b.add("--config");
ARGB: for (ArgumentListBuilder b : new ArgumentListBuilder[] {base, baseNoDebug}) {
// TODO do we really want to pass -l username? Usually the username is ‘hg’ and encoded in the URL. But seems harmless at least on bitbucket.
b.addMasked(String.format("ui.ssh=ssh -i %s -l %s", sshPrivateKey.getRemote(), cc.getUsername()));
String sshAuthOpts = String.format(" -i %s -l %s", sshPrivateKey.getRemote(), cc.getUsername());
// First check to see if the config already specified `ui.ssh=ssh …`; if so, just append to it.
List<String> args = b.toList();
for (int i = 0; i < args.size() - 1; i++) {
if (args.get(i).equals("--config") && args.get(i + 1).startsWith("ui.ssh=")) {
b.add("--config");
b.addMasked(args.get(i + 1) + sshAuthOpts); // second --config should override the first
continue ARGB;
}
}
b.add("--config");
b.addMasked("ui.ssh=ssh" + sshAuthOpts);
}
} else {
sshPrivateKey = null;
Expand Down
Expand Up @@ -155,7 +155,7 @@ public void setCredentialsId(@CheckForNull String credentialsId) {
this.credentialsId = credentialsId;
}

@DataBoundSetter public void setTraits(@CheckForNull List<SCMSourceTrait> traits) {
@DataBoundSetter public void setTraits(@CheckForNull List<? extends SCMSourceTrait> traits) {
this.traits = SCMTrait.asSetList(traits);
}

Expand Down Expand Up @@ -190,6 +190,7 @@ public void setCredentialsId(@CheckForNull String credentialsId) {
@CheckForNull SCMHeadEvent<?> event, @Nonnull final TaskListener listener)
throws IOException, InterruptedException {
try (MercurialSCMSourceRequest request= new MercurialSCMSourceContext<>(criteria, observer)
.withCredentialsId(credentialsId)
.withTraits(traits)
.newRequest(this, listener) ) {
MercurialInstallation inst = MercurialSCM.findInstallation(request.installation());
Expand All @@ -198,6 +199,7 @@ public void setCredentialsId(@CheckForNull String credentialsId) {
return;
}
if (!inst.isUseCaches()) {
// TODO https://stackoverflow.com/a/11900786/12916 suggests that it may be possible to use a noncaching installation
listener.error("Mercurial installation " + request.installation() + " does not support caches");
return;
}
Expand Down
@@ -0,0 +1,96 @@
/*
* The MIT License
*
* Copyright 2017 CloudBees, Inc.
*
* 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.mercurial;

import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.domains.Domain;
import hudson.FilePath;
import hudson.model.Slave;
import hudson.plugins.mercurial.traits.MercurialInstallationSCMSourceTrait;
import hudson.util.StreamTaskListener;
import java.util.Collections;
import jenkins.branch.BranchSource;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject;
import org.jenkinsci.test.acceptance.docker.DockerRule;
import org.junit.ClassRule;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;

public class MercurialSCMSource2Test {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();
@Rule public MercurialRule m = new MercurialRule(r);
@Rule public DockerRule<MercurialContainer> containerRule = new DockerRule<MercurialContainer>(MercurialContainer.class);
@Rule public TemporaryFolder tmp = new TemporaryFolder();

@Issue("JENKINS-42278")
@Test public void withCredentialsId() throws Exception {
m.hg("version"); // test environment needs to be able to run Mercurial
MercurialContainer container = containerRule.get();
Slave slave = container.createSlave(r);
m.withNode(slave);
MercurialInstallation inst = container.createInstallation(r, MercurialContainer.Version.HG4, false, false, false, "", slave);
assertNotNull(inst);
m.withInstallation(inst);
FilePath sampleRepo = slave.getRootPath().child("sampleRepo");
sampleRepo.mkdirs();
m.hg(sampleRepo, "init");
// Tricky because the SSH URL will not work on that agent; it is actually only valid on the master.
// So we need to check out on the master, which is where branch indexing happens as well.
sampleRepo.child("Jenkinsfile").write("node('master') {checkout scm}", null);
m.hg(sampleRepo, "commit", "--addremove", "--message=flow");
MercurialSCMSource s = new MercurialSCMSource("ssh://test@" + container.ipBound(22) + ":" + container.port(22) + "/" + sampleRepo);
CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(),
new BasicSSHUserPrivateKey(CredentialsScope.GLOBAL, "creds", "test", new BasicSSHUserPrivateKey.FileOnMasterPrivateKeySource(container.getPrivateKey().getAbsolutePath()), null, null));
s.setCredentialsId("creds");
String toolHome = inst.forNode(slave, StreamTaskListener.fromStdout()).getHome();
assertNotNull(toolHome);
String remoteHgLoc = inst.executableWithSubstitution(toolHome);
r.jenkins.getDescriptorByType(MercurialInstallation.DescriptorImpl.class).setInstallations(
new MercurialInstallation("default", "", "hg", false, true, null, false,
"[ui]\nssh = ssh -o UserKnownHostsFile=" + tmp.newFile("known_hosts") + " -o StrictHostKeyChecking=no\n" +
"remotecmd = " + remoteHgLoc, null));
s.setTraits(Collections.singletonList(new MercurialInstallationSCMSourceTrait("default")));
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
mp.getSourcesList().add(new BranchSource(s));
WorkflowJob p = PipelineTest.scheduleAndFindBranchProject(mp, "default");
assertEquals(1, mp.getItems().size());
r.waitUntilNoActivity();
WorkflowRun b = p.getLastBuild();
assertNotNull(b);
r.assertBuildStatusSuccess(b);
}

}

0 comments on commit df23704

Please sign in to comment.