/** Tests that axes are available as build variables in the Maven builds. */ public void testBuildAxisInMaven() throws Exception { MatrixProject p = createMatrixProject(); p.getBuildersList().add(new Maven("-Dprop=${db} validate", null)); // we need a dummy build script that echos back our property p.setScm(new SingleFileSCM("pom.xml", getClass().getResource("echo-property.pom"))); MatrixBuild build = p.scheduleBuild2(0).get(); List<MatrixRun> runs = build.getRuns(); assertEquals(4, runs.size()); for (MatrixRun run : runs) { assertBuildStatus(Result.SUCCESS, run); String expectedDb = run.getParent().getCombination().get("db"); System.out.println(run.getLog()); assertLogContains("assertion " + expectedDb + "=" + expectedDb, run); // also make sure that the variables are expanded at the command line level. assertFalse(run.getLog().contains("-Dprop=${db}")); } }
/** Tests that axes are available as build variables in the Ant builds. */ public void testBuildAxisInAnt() throws Exception { MatrixProject p = createMatrixProject(); Ant.AntInstallation ant = configureDefaultAnt(); p.getBuildersList().add(new Ant("-Dprop=${db} test", ant.getName(), null, null, null)); // we need a dummy build script that echos back our property p.setScm( new SingleFileSCM( "build.xml", "<project default='test'><target name='test'><echo>assertion ${prop}=${db}</echo></target></project>")); MatrixBuild build = p.scheduleBuild2(0, new Cause.UserCause()).get(); List<MatrixRun> runs = build.getRuns(); assertEquals(4, runs.size()); for (MatrixRun run : runs) { assertBuildStatus(Result.SUCCESS, run); String expectedDb = run.getParent().getCombination().get("db"); assertLogContains("assertion " + expectedDb + "=" + expectedDb, run); } }
/** * Waits for the given configurations to finish, retrying any that qualify to be rerun. * * @param execution Provided by the plugin. * @param patterns List of regular expression patterns used to scan the log to determine if a * build should be rerun. * @param retries Mutable map that tracks the number of times a specific configuration has been * retried. * @param configurations The configurations that have already been scheduled to run that should be * waited for to finish. * @return The worst result of all the runs. If a build was rerun, only the result of the rerun is * considered. * @throws InterruptedException * @throws IOException */ private Result waitForMatrixRuns( MatrixBuild.MatrixBuildExecution execution, List<Pattern> patterns, Map<MatrixConfiguration, Integer> retries, LinkedList<MatrixConfiguration> configurations) throws InterruptedException, IOException { BuildListener listener = execution.getListener(); PrintStream logger = listener.getLogger(); Map<String, String> whyBlockedMap = new HashMap< String, String>(); // keep track of why builds are blocked so we can print unique messages when // they change. Result finalResult = Result.SUCCESS; int iteration = 0; boolean continueRetrying = true; while (!configurations.isEmpty()) { ++iteration; MatrixConfiguration configuration = configurations.removeFirst(); if (isBuilding(execution, configuration, whyBlockedMap)) { if (iteration >= configurations.size()) { // Every time we loop through all the configurations, sleep for a bit. // This is to prevent polling too often while everything is still building. iteration = 0; Thread.sleep(1000); } configurations.add(configuration); continue; } Run parentBuild = execution.getBuild(); MatrixRun matrixRun = configuration.getBuildByNumber(parentBuild.getNumber()); Result runResult = matrixRun.getResult(); if (continueRetrying && runResult.isWorseOrEqualTo(getWorseThanOrEqualTo()) && runResult.isBetterOrEqualTo(getBetterThanOrEqualTo())) { if (matchesPattern(matrixRun, patterns)) { int retriedCount = retries.get(configuration); if (retriedCount < getMaxRetries()) { ++retriedCount; retries.put(configuration, retriedCount); // rerun String logMessage = String.format( "%s was %s. Matched pattern to rerun. Rerunning (%d).", matrixRun, runResult, retriedCount); listener.error(logMessage); HealedAction action = parentBuild.getAction(HealedAction.class); if (action == null) { //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (parentBuild.getActions()) { action = parentBuild.getAction(HealedAction.class); if (action == null) { action = new HealedAction(matrixRun.getCharset()); parentBuild.addAction(action); } } } action.addAutoHealedJob(matrixRun); MatrixConfiguration parent = matrixRun.getParent(); if (parent != null) { // I'm paranoid about NPEs parent.removeRun(matrixRun); matrixRun.delete(); } else { LOGGER.severe( "couldn't remove old run, parent was null. This is a Jenkins core bug."); } scheduleConfigurationBuild( execution, configuration, new SelfHealingCause(parentBuild, retriedCount)); configurations.add(configuration); continue; } else { String logMessage = String.format( "%s was %s. Matched pattern to rerun, but the max number of retries (%d) has been met.", matrixRun, runResult, getMaxRetries()); listener.error(logMessage); if (getStopRetryingAfterOneFails()) { listener.error("Not retrying any more builds."); continueRetrying = false; } } } else { String logMessage = String.format( "%s was %s. It did not match the pattern to rerun. Accepting result.", matrixRun, runResult); logger.println(logMessage); } } notifyEndRun(matrixRun, execution.getAggregators(), execution.getListener()); finalResult = finalResult.combine(runResult); } return finalResult; }