Skip to content
Permalink
Browse files

Initial commit for JENKINS-24754

  • Loading branch information...
MadsNielsen committed Sep 18, 2014
1 parent a9c78e0 commit a3b2dd66896ee1f8a54b4447c7523890e99e6475
@@ -383,6 +383,12 @@
<artifactId>git</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>multiple-scms</artifactId>
<version>0.3</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -12,13 +12,19 @@
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.FreeStyleProject;
import hudson.plugins.git.GitSCM;
import hudson.scm.SCM;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.multiplescms.MultiSCM;
import org.jenkinsci.plugins.pretestedintegration.exceptions.RollbackFailureException;
import org.jenkinsci.plugins.pretestedintegration.exceptions.UnsupportedConfigurationException;
import org.jenkinsci.plugins.pretestedintegration.scm.git.GitBridge;

import org.kohsuke.stapler.DataBoundConstructor;

@@ -59,6 +65,37 @@ public PretestedIntegrationBuildWrapper(final AbstractSCMBridge scmBridge) {
}
return null;
}

//For JENKINS-24754
private void validateGitScm(GitSCM scm) throws UnsupportedConfigurationException {
if(scm.getRepositories().size() > 1 && StringUtils.isBlank(((GitBridge)scmBridge).getRepoName())) {
throw new UnsupportedConfigurationException(String.format("You have not defined a repository name in your Pre Tested Integration configuration, but you have multiple scm checkouts listed in your scm config%nCurrently this is not supported"));
}
}

//For JENKINS-24754
private void validateConfiguration(AbstractProject<?,?> project) throws UnsupportedConfigurationException {

if( project.getScm() instanceof GitSCM ) {
validateGitScm((GitSCM)project.getScm());
} else if(Jenkins.getInstance().getPlugin("multiple-scms") != null && project.getScm() instanceof MultiSCM ) {
MultiSCM multiscm = (MultiSCM)project.getScm();
int gitCounter = 0;
for(SCM scm : multiscm.getConfiguredSCMs()) {
if(scm instanceof GitSCM) {
GitSCM gitMultiScm = (GitSCM)scm;
validateGitScm(gitMultiScm);
gitCounter++;
}
}

if(gitCounter > 1 && StringUtils.isBlank(((GitBridge)scmBridge).getRepoName())) {
throw new UnsupportedConfigurationException("You haave included multiple git repositories in your multi scm configuration, but have not defined a repository name in the pre tested integration configuration");
}
} else {
throw new UnsupportedConfigurationException("We only support git and mutiple scm plugins");
}
}

/**
* Jenkins hook that fires after the workspace is initialized. Calls the
@@ -76,23 +113,13 @@ public PretestedIntegrationBuildWrapper(final AbstractSCMBridge scmBridge) {
//There can be only one... at a time
BuildQueue.getInstance().enqueueAndWait();
PretestedIntegrationAction action;
try {
try {
validateConfiguration(build.getProject());
scmBridge.ensureBranch(build, launcher, listener, scmBridge.getBranch());

//Create the action. Record the state of integration branch
action = new PretestedIntegrationAction(build, launcher, listener, scmBridge);
build.addAction(action);

if(rollbackEnabled) {
/**
* If the previous build failed...then we revert to the state of master prior to that particular commit being integrated.
*/
AbstractBuild<?,?> latestBuildWithPreTest = findLatestBuildWithPreTestedIntegrationAction(build);
if(latestBuildWithPreTest != null ) {
scmBridge.rollback(latestBuildWithPreTest.getPreviousBuild(), launcher, listener);
}
}

build.addAction(action);
action.initialise(launcher, listener);
try {
ensurePublisher(build);
@@ -115,10 +142,11 @@ public PretestedIntegrationBuildWrapper(final AbstractSCMBridge scmBridge) {
build.setResult(Result.FAILURE);
BuildQueue.getInstance().release();
everythingOk = false;
} catch (RollbackFailureException ex) {
build.setResult(Result.FAILURE);
BuildQueue.getInstance().release();
everythingOk = false;
} catch (UnsupportedConfigurationException ex) {
build.setResult(Result.FAILURE);
BuildQueue.getInstance().release();
listener.getLogger().println(ex.getMessage());
return null;
}

BuildWrapper.Environment environment = new PretestEnvironment();
@@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jenkinsci.plugins.pretestedintegration.exceptions;

import java.io.IOException;

/**
*
* @author Mads
*/
public class UnsupportedConfigurationException extends IOException {

public UnsupportedConfigurationException(String message) {
super(message);
}
}
@@ -40,12 +40,19 @@

public class GitBridge extends AbstractSCMBridge {

private String revId;
private String revId;
private String repoName;

@DataBoundConstructor
public GitBridge(IntegrationStrategy integrationStrategy, final String branch, String repoName) {
super(integrationStrategy);
this.branch = branch;
this.repoName = repoName;
}

public GitBridge(IntegrationStrategy integrationStrategy, final String branch) {
super(integrationStrategy);
this.branch = branch;
this.branch = branch;
}

@Override
@@ -74,6 +81,10 @@ private GitSCM findScm(AbstractBuild<?, ?> build) throws InterruptedException {
throw new InterruptedException("Configured scm is not Git");
}
}

private String resolveRepoName() {
return StringUtils.isBlank(repoName) ? "origin" : repoName;
}

private ProcStarter buildCommand(AbstractBuild<?, ?> build, Launcher launcher, TaskListener listener, String... cmds) throws IOException, InterruptedException {
GitSCM scm = findScm(build);
@@ -123,7 +134,8 @@ public int git(AbstractBuild<?, ?> build, Launcher launcher, TaskListener listen
public void ensureBranch(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener, String branch) throws EstablishWorkspaceException {
listener.getLogger().println(String.format("Checking out integration target branch %s and pulling latest changes", getBranch()));
try {
git(build, launcher, listener, "checkout", getBranch());
//We need to explicitly checkout the remote we have configured
git(build, launcher, listener, "checkout", resolveRepoName()+"/"+getBranch());
update(build, launcher, listener);
} catch (IOException ex) {
throw new EstablishWorkspaceException(ex);
@@ -133,7 +145,7 @@ public void ensureBranch(AbstractBuild<?, ?> build, Launcher launcher, BuildList
}

protected void update(AbstractBuild<?, ?> build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
git(build, launcher, listener, "pull", "origin", branch);
git(build, launcher, listener, "pull", resolveRepoName(), branch);
}

/**
@@ -165,7 +177,7 @@ public void commit(AbstractBuild<?, ?> build, Launcher launcher, BuildListener l
int returncode = -99999;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
returncode = git(build, launcher, listener, bos, "push", "origin", getBranch());
returncode = git(build, launcher, listener, bos, "push", resolveRepoName(), getBranch());
} catch (Exception ex) {
logger.log(Level.WARNING, "Failed to commit changes to integration branch", ex);
}
@@ -204,7 +216,7 @@ public void deleteIntegratedBranch(AbstractBuild<?, ?> build, Launcher launcher,

if(build.getResult().isBetterOrEqualTo(getRequiredResult())) {
try {
delRemote = git(build, launcher, listener, out, "push", "origin",":"+removeOrigin(gitDataBranch.getName()));
delRemote = git(build, launcher, listener, out, "push", resolveRepoName(),":"+removeOrigin(gitDataBranch.getName()));
} catch (Exception ex) {
logger.log(Level.WARNING, "Failure to delete branch", ex);
}
@@ -258,6 +270,20 @@ private String removeOrigin(String branchName) {
}
return commit;
}

/**
* @return the remoteName
*/
public String getRepoName() {
return repoName;
}

/**
* @param repoName the remoteName to set
*/
public void setRepoName(String repoName) {
this.repoName = repoName;
}

@Extension
public static final class DescriptorImpl extends SCMBridgeDescriptor<GitBridge> {
@@ -2,7 +2,12 @@
<f:block>
<f:entry title="Integration branch" field="branch">
<f:textbox value="${it.branch}" />
</f:entry>
</f:entry>

<f:entry title="Repository name" field="repoName">
<f:textbox value="${it.repoName}" default="origin"/>
</f:entry>

<j:choose>
<j:when test="${instance.integrationStrategy == null}">
<f:descriptorRadioList descriptors="${descriptor.getIntegrationStrategies()}" title="Pre-tested integration strategy" varName="integrationStrategy" instance="${descriptor.getDefaultStrategy()}"/>

0 comments on commit a3b2dd6

Please sign in to comment.
You can’t perform that action at this time.