/** * Tests if a {@link MatrixBuild} gets loaded and converted correctly from a version 1.2.0 save. * * @throws InterruptedException if it is not allowed to sleep in the beginning. */ @LocalData public void testMatrix120() throws InterruptedException { MatrixProject project = (MatrixProject) jenkins.getItem("mymatrix"); MatrixBuild build = project.getBuildByNumber(1); OldDataConverter.getInstance().waitForInitialCompletion(); FailureCauseMatrixBuildAction matrixBuildAction = build.getAction(FailureCauseMatrixBuildAction.class); assertNotNull(matrixBuildAction); List<MatrixRun> runs = Whitebox.getInternalState(matrixBuildAction, "runs"); assertNotNull(runs); List<String> runIds = null; runIds = Whitebox.getInternalState(matrixBuildAction, "runIds"); assertEquals(runs.size(), runIds.size()); assertNotNull(runs.get(3).getProject()); assertEquals(runs.get(3).getProject().getCombination().toString(), runIds.get(3)); assertNotNull(Whitebox.getInternalState(matrixBuildAction, "build")); MatrixBuild build2 = project.getBuildByNumber(2); List<MatrixRun> aggregatedRuns2 = FailureCauseMatrixAggregator.getRuns(build2); FailureCauseMatrixBuildAction matrixBuildAction2 = build2.getAction(FailureCauseMatrixBuildAction.class); assertNotNull(matrixBuildAction2); List<MatrixRun> runs2 = Whitebox.getInternalState(matrixBuildAction2, "runs"); assertSame(aggregatedRuns2.get(5), runs2.get(5)); }
public boolean doBuildConfiguration(MatrixBuild b, MatrixConfiguration c) { MatrixSubsetAction a = b.getAction(MatrixSubsetAction.class); if (a == null) return true; // run the filter and restrict the subset to run return c.getCombination().evalScriptExpression(b.getParent().getAxes(), a.getFilter()); }
@Override public boolean checkout( final AbstractBuild build, Launcher launcher, final FilePath workspace, final BuildListener listener, File changelogFile) throws IOException, InterruptedException { listener .getLogger() .println( "Checkout:" + workspace.getName() + " / " + workspace.getRemote() + " - " + workspace.getChannel()); listener.getLogger().println("Using strategy: " + choosingStrategy); final String projectName = build.getProject().getName(); final int buildNumber = build.getNumber(); final String gitExe = getDescriptor().getGitExe(); final String buildnumber = "hudson-" + projectName + "-" + buildNumber; final BuildData buildData = getBuildData(build.getPreviousBuild(), true); if (buildData != null && buildData.lastBuild != null) { listener.getLogger().println("Last Built Revision: " + buildData.lastBuild.revision); } final EnvVars environment = build.getEnvironment(listener); final String singleBranch = getSingleBranch(build); Revision tempParentLastBuiltRev = null; if (build instanceof MatrixRun) { MatrixBuild parentBuild = ((MatrixRun) build).getParentBuild(); if (parentBuild != null) { BuildData parentBuildData = parentBuild.getAction(BuildData.class); if (parentBuildData != null) { tempParentLastBuiltRev = parentBuildData.getLastBuiltRevision(); } } } final Revision parentLastBuiltRev = tempParentLastBuiltRev; final Revision revToBuild = workspace.act( new FileCallable<Revision>() { private static final long serialVersionUID = 1L; public Revision invoke(File localWorkspace, VirtualChannel channel) throws IOException { FilePath ws = new FilePath(localWorkspace); listener .getLogger() .println( "Checkout:" + ws.getName() + " / " + ws.getRemote() + " - " + ws.getChannel()); IGitAPI git = new GitAPI(gitExe, ws, listener, environment); if (git.hasGitRepo()) { // It's an update listener.getLogger().println("Fetching changes from the remote Git repository"); for (RemoteConfig remoteRepository : getRepositories()) { fetchFrom(git, localWorkspace, listener, remoteRepository); } } else { listener.getLogger().println("Cloning the remote Git repository"); // Go through the repositories, trying to clone from one // boolean successfullyCloned = false; for (RemoteConfig rc : remoteRepositories) { try { git.clone(rc); successfullyCloned = true; break; } catch (GitException ex) { listener.error( "Error cloning remote repo '%s' : %s", rc.getName(), ex.getMessage()); if (ex.getCause() != null) { listener.error("Cause: %s", ex.getCause().getMessage()); } // Failed. Try the next one listener.getLogger().println("Trying next repository"); } } if (!successfullyCloned) { listener.error("Could not clone from a repository"); throw new GitException("Could not clone"); } // Also do a fetch for (RemoteConfig remoteRepository : getRepositories()) { fetchFrom(git, localWorkspace, listener, remoteRepository); } if (git.hasGitModules()) { git.submoduleInit(); git.submoduleUpdate(); } } if (parentLastBuiltRev != null) return parentLastBuiltRev; IBuildChooser buildChooser = createBuildChooser(git, listener, buildData); Collection<Revision> candidates = buildChooser.getCandidateRevisions(false, singleBranch); if (candidates.size() == 0) return null; return candidates.iterator().next(); } }); if (revToBuild == null) { // getBuildCandidates should make the last item the last build, so a re-build // will build the last built thing. listener.error("Nothing to do"); return false; } listener.getLogger().println("Commencing build of " + revToBuild); environment.put(GIT_COMMIT, revToBuild.getSha1String()); Object[] returnData; // Changelog, BuildData if (mergeOptions.doMerge()) { if (!revToBuild.containsBranchName(mergeOptions.getRemoteBranchName())) { returnData = workspace.act( new FileCallable<Object[]>() { private static final long serialVersionUID = 1L; public Object[] invoke(File localWorkspace, VirtualChannel channel) throws IOException { IGitAPI git = new GitAPI(gitExe, new FilePath(localWorkspace), listener, environment); IBuildChooser buildChooser = createBuildChooser(git, listener, buildData); // Do we need to merge this revision onto MergeTarget // Only merge if there's a branch to merge that isn't // us.. listener .getLogger() .println( "Merging " + revToBuild + " onto " + mergeOptions.getMergeTarget()); // checkout origin/blah ObjectId target = git.revParse(mergeOptions.getRemoteBranchName()); git.checkout(target.name()); try { git.merge(revToBuild.getSha1().name()); } catch (Exception ex) { listener .getLogger() .println( "Branch not suitable for integration as it does not merge cleanly"); // We still need to tag something to prevent // repetitive builds from happening - tag the // candidate // branch. git.checkout(revToBuild.getSha1().name()); git.tag(buildnumber, "Hudson Build #" + buildNumber); buildChooser.revisionBuilt(revToBuild, buildNumber, Result.FAILURE); return new Object[] {null, buildChooser.getData()}; } if (git.hasGitModules()) { git.submoduleUpdate(); } // Tag the successful merge git.tag(buildnumber, "Hudson Build #" + buildNumber); StringBuilder changeLog = new StringBuilder(); if (revToBuild.getBranches().size() > 0) listener .getLogger() .println("Warning : There are multiple branch changesets here"); try { for (Branch b : revToBuild.getBranches()) { Build lastRevWas = buildData == null ? null : buildData.getLastBuildOfBranch(b.getName()); if (lastRevWas != null) { changeLog.append( putChangelogDiffsIntoFile( git, b.name, lastRevWas.getSHA1().name(), revToBuild.getSha1().name())); } } } catch (GitException ge) { changeLog.append("Unable to retrieve changeset"); } Build buildData = buildChooser.revisionBuilt(revToBuild, buildNumber, null); GitUtils gu = new GitUtils(listener, git); buildData.mergeRevision = gu.getRevisionForSHA1(target); // Fetch the diffs into the changelog file return new Object[] {changeLog.toString(), buildChooser.getData()}; } }); BuildData returningBuildData = (BuildData) returnData[1]; build.addAction(returningBuildData); return changeLogResult((String) returnData[0], changelogFile); } } // No merge returnData = workspace.act( new FileCallable<Object[]>() { private static final long serialVersionUID = 1L; public Object[] invoke(File localWorkspace, VirtualChannel channel) throws IOException { IGitAPI git = new GitAPI(gitExe, new FilePath(localWorkspace), listener, environment); IBuildChooser buildChooser = createBuildChooser(git, listener, buildData); // Straight compile-the-branch listener.getLogger().println("Checking out " + revToBuild); git.checkout(revToBuild.getSha1().name()); // if( compileSubmoduleCompares ) if (doGenerateSubmoduleConfigurations) { SubmoduleCombinator combinator = new SubmoduleCombinator(git, listener, localWorkspace, submoduleCfg); combinator.createSubmoduleCombinations(); } if (git.hasGitModules()) { git.submoduleInit(); git.submoduleSync(); // Git submodule update will only 'fetch' from where it // regards as 'origin'. However, // it is possible that we are building from a // RemoteRepository with changes // that are not in 'origin' AND it may be a new module that // we've only just discovered. // So - try updating from all RRs, then use the submodule // Update to do the checkout for (RemoteConfig remoteRepository : getRepositories()) { fetchFrom(git, localWorkspace, listener, remoteRepository); } // Update to the correct checkout git.submoduleUpdate(); } // Tag the successful merge git.tag(buildnumber, "Hudson Build #" + buildNumber); StringBuilder changeLog = new StringBuilder(); int histories = 0; try { for (Branch b : revToBuild.getBranches()) { Build lastRevWas = buildData == null ? null : buildData.getLastBuildOfBranch(b.getName()); if (lastRevWas != null) { listener.getLogger().println("Recording changes in branch " + b.getName()); changeLog.append( putChangelogDiffsIntoFile( git, b.name, lastRevWas.getSHA1().name(), revToBuild.getSha1().name())); histories++; } else { listener.getLogger().println("No change to record in branch " + b.getName()); } } } catch (GitException ge) { changeLog.append("Unable to retrieve changeset"); } if (histories > 1) listener .getLogger() .println("Warning : There are multiple branch changesets here"); buildChooser.revisionBuilt(revToBuild, buildNumber, null); if (getClean()) { listener.getLogger().println("Cleaning workspace"); git.clean(); } // Fetch the diffs into the changelog file return new Object[] {changeLog.toString(), buildChooser.getData()}; } }); build.addAction((Action) returnData[1]); return changeLogResult((String) returnData[0], changelogFile); }