Skip to content

Commit

Permalink
[JENKINS-31128] Added failing test that indicates a design challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
MadsNielsen authored and Thierry Lacour committed Oct 30, 2015
1 parent 80d066a commit 3f74109
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 1 deletion.
@@ -0,0 +1,131 @@
/*
* 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.integration.scm.git;

import hudson.matrix.Axis;
import hudson.matrix.AxisList;
import hudson.matrix.MatrixProject;
import hudson.model.AbstractProject;
import hudson.model.FreeStyleProject;
import hudson.model.Job;
import hudson.plugins.git.BranchSpec;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.SubmoduleConfig;
import hudson.plugins.git.UserRemoteConfig;
import hudson.plugins.git.extensions.GitSCMExtension;
import hudson.plugins.git.extensions.impl.CleanCheckout;
import hudson.plugins.git.extensions.impl.PruneStaleBranch;
import hudson.slaves.DumbSlave;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.jenkinsci.plugins.pretestedintegration.PretestedIntegrationBuildWrapper;
import org.jenkinsci.plugins.pretestedintegration.PretestedIntegrationPostCheckout;
import org.jenkinsci.plugins.pretestedintegration.scm.git.AccumulatedCommitStrategy;
import org.jenkinsci.plugins.pretestedintegration.scm.git.GitBridge;
import org.jenkinsci.plugins.pretestedintegration.scm.git.SquashCommitStrategy;
import org.jvnet.hudson.test.JenkinsRule;

/**
*
* @author Mads
*/
public class GitProjectBuilder {

public enum STRATEGY_TYPE {

SQUASH, ACCUMULATED
};

private JenkinsRule rule;
private String integrationBranchName = "master";
private String repoName = "origin";
private Class<? extends Job> jobType;
private STRATEGY_TYPE type;
private List<UserRemoteConfig> gitRepos;
private boolean useSlave;

public GitProjectBuilder setRule(JenkinsRule rule) {
this.rule = rule;
return this;
}

public GitProjectBuilder setIntegrationBranchName(String integrationBranchName) {
this.integrationBranchName = integrationBranchName;
return this;
}

public GitProjectBuilder setJobType(Class<? extends Job> jobType) {
this.jobType = jobType;
return this;
}

public GitProjectBuilder setStrategy(STRATEGY_TYPE type) {
this.type = type;
return this;
}

public GitProjectBuilder setGitRepos(List<UserRemoteConfig> gitRepos) {
this.gitRepos = gitRepos;
return this;
}

public GitProjectBuilder setUseSlaves(boolean useSlave) {
this.useSlave = useSlave;
return this;
}

public GitProjectBuilder setRepoName(String repoName) {
this.repoName = repoName;
return this;
}

public AbstractProject<?,?> generateJenkinsJob() throws IOException, Exception {

assert jobType.equals(FreeStyleProject.class) || jobType.equals(MatrixProject.class) : "We must use either matrix or free style job types";

AbstractProject<?,?> project = null;

GitBridge gitBridge;
if (type == STRATEGY_TYPE.SQUASH) {
gitBridge = new GitBridge(new SquashCommitStrategy(), integrationBranchName, repoName);
} else {
gitBridge = new GitBridge(new AccumulatedCommitStrategy(), integrationBranchName, repoName);
}

if (jobType.equals(FreeStyleProject.class)) {
project = rule.createFreeStyleProject();
((FreeStyleProject)project).getBuildWrappersList().add(new PretestedIntegrationBuildWrapper(gitBridge));
project.getPublishersList().add(new PretestedIntegrationPostCheckout());
} else if(jobType.equals(MatrixProject.class)) {
project = rule.createMatrixProject();
((MatrixProject)project).getBuildWrappersList().add(new PretestedIntegrationBuildWrapper(gitBridge));
project.getPublishersList().add(new PretestedIntegrationPostCheckout());
((MatrixProject)project).setAxes(new AxisList(new Axis("X", Arrays.asList("X1","X2"))));
}

if (useSlave) {
DumbSlave onlineSlave = rule.createOnlineSlave();
project.setAssignedNode(onlineSlave);
}

List<GitSCMExtension> gitSCMExtensions = new ArrayList<>();
gitSCMExtensions.add(new PruneStaleBranch());
gitSCMExtensions.add(new CleanCheckout());

GitSCM gitSCM = new GitSCM(gitRepos,
Collections.singletonList(new BranchSpec("*/ready/**")),
false, Collections.<SubmoduleConfig>emptyList(),
null, null, gitSCMExtensions);

project.setScm(gitSCM);

return project;
}

}
@@ -0,0 +1,150 @@
/*
* 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.integration.scm.git;

import hudson.matrix.MatrixProject;
import hudson.matrix.MatrixRun;
import hudson.model.AbstractProject;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Run;
import hudson.plugins.git.UserRemoteConfig;
import hudson.util.RunList;
import java.io.File;
import java.util.Collections;
import static junit.framework.TestCase.assertEquals;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.CreateBranchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

/**
*
* @author Mads
*/
public class MatrixProjectCompatabilityTestIT {
@Rule
public JenkinsRule jenkinsRule = new JenkinsRule();

private static final String FEATURE_BRANCH_NAME = "ready/feature_1";
private Repository repository;

@After
public void tearDown() throws Exception {
TestUtilsFactory.destroyRepo(repository);
}

/**
* Git Plugin
*
* Test that show that a ready/feature_1 branch get integrated into master
* using a Matrix job type.
*
* Pretested integration:
* - 'Integration branch' : master (default)
* - 'Repository name' : origin (default)
* - 'Strategy' : Squash Commit
*
* GitSCM:
* - 'Name' : (empty)
*
* Workflow
* - Create a repository containing a 'ready' branch.
* - The build is triggered.
*
* Results
* - We expect that the plugin triggers, and that the commits on ready branch
* is merged into our integration branch master and build result becomes SUCCESS.
*
* @throws Exception
*/
@Test
public void oneBuildBasicSmokeTest() throws Exception {
repository = TestUtilsFactory.createValidRepository("test-repo");

File workDir = new File("test-repo");

Git.cloneRepository().setURI("file:///" + repository.getDirectory().getAbsolutePath()).setDirectory(workDir)
.setBare(false)
.setCloneAllBranches(true)
.setNoCheckout(false)
.call().close();

Git git = Git.open(workDir);

System.out.println("Opening git repository in: " + workDir.getAbsolutePath());

String readmeFromIntegration = FileUtils.readFileToString(new File("test-repo/readme"));

git.checkout().setName(FEATURE_BRANCH_NAME).setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK).setCreateBranch(true).call();
final int COMMIT_COUNT_ON_FEATURE_BEFORE_EXECUTION = TestUtilsFactory.countCommits(git);
git.checkout().setName("master").setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK).call();

GitProjectBuilder builder = new GitProjectBuilder()
.setGitRepos(Collections.singletonList(new UserRemoteConfig("file://" + repository.getDirectory().getAbsolutePath(), null, null, null)))
.setUseSlaves(true).setRule(jenkinsRule)
.setStrategy(GitProjectBuilder.STRATEGY_TYPE.ACCUMULATED);
builder.setJobType(MatrixProject.class);

MatrixProject project = (MatrixProject)builder.generateJenkinsJob();
TestUtilsFactory.triggerProject(project);

jenkinsRule.waitUntilNoActivityUpTo(60000);

assertEquals("2 runs for this particular matrix build", 2, project.getLastBuild().getRuns().size());

String readmeFileContents = FileUtils.readFileToString(new File("test-repo/readme"));
assertEquals(readmeFromIntegration, readmeFileContents);

git.pull().call();

final int COMMIT_COUNT_ON_MASTER_AFTER_EXECUTION = TestUtilsFactory.countCommits(git);

git.close();

//We assert that 2 commits from branch gets merged + 1 combined merge commit since we do --no-ff
assertEquals(COMMIT_COUNT_ON_FEATURE_BEFORE_EXECUTION + 3, COMMIT_COUNT_ON_MASTER_AFTER_EXECUTION);
}

/**
*
* TODO: How do we solve this one.
*
* We need to test and make our plugin not spawn 2 failed runs if the parent job fails with a merge conflict
* @throws Exception
*/
@Test
@Ignore
public void oneBuildBasicMergeFailure() throws Exception {
repository = TestUtilsFactory.createRepositoryWithMergeConflict("test-repo");

File workDir = new File("test-repo");

Git.cloneRepository().setURI("file:///" + repository.getDirectory().getAbsolutePath()).setDirectory(workDir)
.setBare(false)
.setCloneAllBranches(true)
.setNoCheckout(false)
.call().close();

GitProjectBuilder builder = new GitProjectBuilder()
.setGitRepos(Collections.singletonList(new UserRemoteConfig("file://" + repository.getDirectory().getAbsolutePath(), null, null, null)))
.setUseSlaves(true).setRule(jenkinsRule)
.setStrategy(GitProjectBuilder.STRATEGY_TYPE.ACCUMULATED);
builder.setJobType(MatrixProject.class);

MatrixProject project = (MatrixProject)builder.generateJenkinsJob();
TestUtilsFactory.triggerProject(project);

jenkinsRule.waitUntilNoActivityUpTo(60000);

assertEquals("Since merge failed...we should get no child jobs to spawn", 0, project.getLastBuild().getRuns().size());
}
}
@@ -1,5 +1,6 @@
package org.jenkinsci.plugins.pretestedintegration.integration.scm.git;

import hudson.model.AbstractProject;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.plugins.git.BranchSpec;
Expand Down Expand Up @@ -264,7 +265,7 @@ public static FreeStyleProject configurePretestedIntegrationPlugin(JenkinsRule r
return configurePretestedIntegrationPlugin(rule, type, Collections.singletonList(new UserRemoteConfig("file://" + repo.getDirectory().getAbsolutePath(), null, null, null)), null, runOnSlave);
}

public static void triggerProject(FreeStyleProject project) throws Exception {
public static void triggerProject(AbstractProject<?,?> project) throws Exception {
project.getTriggers().clear();
SCMTrigger scmTrigger = new SCMTrigger("@daily", true);
project.addTrigger(scmTrigger);
Expand Down

0 comments on commit 3f74109

Please sign in to comment.