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());
  }
  /**
   * 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));
  }
예제 #3
0
 public void testNoAxis() throws Exception {
   ToxBuilder builder = new ToxBuilder("tox.ini", false, null);
   MatrixProject project = createMatrixProject();
   AxisList axes = new AxisList(new TextAxis("TOTO", "TUTU"));
   project.setAxes(axes);
   project.getBuildersList().add(builder);
   MatrixBuild build = project.scheduleBuild2(0).get();
   List<MatrixRun> runs = build.getRuns();
   assertEquals(1, runs.size());
   MatrixRun run = runs.get(0);
   String log = FileUtils.readFileToString(run.getLogFile());
   assertTrue(
       "should not have found a tox axis:\n" + log,
       log.contains(Messages.ToxBuilder_ToxAxis_Required()));
 }
예제 #4
0
 public void testNoInterpreter() throws Exception {
   ToxBuilder builder = new ToxBuilder("tox.ini", false, null);
   MatrixProject project = createMatrixProject();
   AxisList axes = new AxisList(new ToxAxis(new String[] {"py27"}));
   project.setAxes(axes);
   project.getBuildersList().add(builder);
   MatrixBuild build = project.scheduleBuild2(0).get();
   List<MatrixRun> runs = build.getRuns();
   assertEquals(1, runs.size());
   MatrixRun run = runs.get(0);
   String log = FileUtils.readFileToString(run.getLogFile());
   assertTrue(
       "should not have found an interpreter:\n" + log,
       log.contains(Messages.BuilderUtil_NoInterpreterFound()));
 }
예제 #5
0
 public void testToxAxisSuccessful() throws Exception {
   configureCPython2();
   ToxBuilder builder = new ToxBuilder("tox.ini", false, null);
   MatrixProject project = createMatrixProject();
   AxisList axes = new AxisList(new ToxAxis(new String[] {"py27"}));
   project.setScm(new ToxSCM("tox.ini", "[testenv]\ncommand = echo"));
   project.setAxes(axes);
   project.getBuildersList().add(builder);
   MatrixBuild build = project.scheduleBuild2(0).get();
   List<MatrixRun> runs = build.getRuns();
   assertEquals(1, runs.size());
   MatrixRun run = runs.get(0);
   String log = FileUtils.readFileToString(run.getLogFile());
   assertTrue("tox should have been successful:\n" + log, log.contains("congratulations :)"));
   assertTrue("build should have been successful:\n" + log, log.contains("SUCCESS"));
 }
  @Test
  public void shortenMatrix() throws Exception {
    Node slave = j.createOnlineSlave();
    setMaxPathLength(slave, 1); // Not enough for anything

    MatrixProject mp = j.createMatrixProject();
    mp.setAssignedNode(slave);
    mp.setAxes(new AxisList(new LabelExpAxis("axis", slave.getNodeName())));

    MatrixBuild build = j.buildAndAssertSuccess(mp);
    assertThat(build.getBuiltOn(), equalTo(slave));
    MatrixRun run = build.getExactRuns().get(0);
    assertThat(run.getBuiltOn(), equalTo(slave));

    System.out.println(build.getWorkspace());
    System.out.println(run.getWorkspace());
  }
예제 #7
0
 public void testToxenvPatternBlank() throws Exception {
   configureCPython2();
   ToxBuilder builder = new ToxBuilder("tox.ini", false, "$FOOBAR");
   MatrixProject project = createMatrixProject();
   AxisList axes = new AxisList(new TextAxis("FOOBAR2", "badluck"));
   project.setScm(new ToxSCM("tox.ini", "[testenv]\ncommand = echo"));
   project.setAxes(axes);
   project.getBuildersList().add(builder);
   MatrixBuild build = project.scheduleBuild2(0).get();
   List<MatrixRun> runs = build.getRuns();
   assertEquals(1, runs.size());
   MatrixRun run = runs.get(0);
   String log = FileUtils.readFileToString(run.getLogFile());
   System.out.println(log);
   assertTrue(
       "should not be able to run with a blank TOXENV pattern:\n" + log,
       log.contains(Messages.ToxBuilder_ToxenvPattern_Invalid("$FOOBAR")));
 }
  /**
   * Schedules the given configuration.
   *
   * <p>Copied from the {@link
   * DefaultMatrixExecutionStrategyImpl#scheduleConfigurationBuild(hudson.matrix.MatrixBuild.MatrixBuildExecution,
   * hudson.matrix.MatrixConfiguration)}
   *
   * @param execution Contains information about the general build, including the listener used to
   *     log queue blockage.
   * @param configuration The configuration to schedule.
   * @param upstreamCause The cause of the build. Will either be an {@link
   *     hudson.model.Cause.UpstreamCause} or {@link
   *     com.attask.jenkins.healingmatrixproject.SelfHealingCause}.
   */
  private void scheduleConfigurationBuild(
      MatrixBuild.MatrixBuildExecution execution,
      MatrixConfiguration configuration,
      Cause.UpstreamCause upstreamCause)
      throws InterruptedException {
    MatrixBuild build = (MatrixBuild) execution.getBuild();
    execution
        .getListener()
        .getLogger()
        .println(Messages.MatrixBuild_Triggering(ModelHyperlinkNote.encodeTo(configuration)));

    // filter the parent actions for those that can be passed to the individual jobs.
    List<MatrixChildAction> childActions = Util.filter(build.getActions(), MatrixChildAction.class);

    BuildListener listener = execution.getListener();
    while (!configuration.scheduleBuild(childActions, upstreamCause)) {
      String msg = "Unable to schedule build " + configuration.getFullDisplayName() + ". Retrying.";
      listener.error(msg);
      Thread.sleep(500);
    }
  }
예제 #9
0
 public void testToxAxisAndToxenvPattern() throws Exception {
   configureCPython2();
   ToxBuilder builder = new ToxBuilder("tox.ini", false, "$INTERPRETER$VERSION");
   MatrixProject project = createMatrixProject();
   AxisList axes =
       new AxisList(
           new ToxAxis(new String[] {"py27"}),
           new TextAxis("INTERPRETER", "py"),
           new TextAxis("VERSION", "27"));
   project.setScm(new ToxSCM("tox.ini", "[testenv]\ncommand = echo"));
   project.setAxes(axes);
   project.getBuildersList().add(builder);
   MatrixBuild build = project.scheduleBuild2(0).get();
   List<MatrixRun> runs = build.getRuns();
   assertEquals(1, runs.size());
   MatrixRun run = runs.get(0);
   String log = FileUtils.readFileToString(run.getLogFile());
   System.out.println(log);
   assertTrue(
       "should not be able to run with both Tox axis and TOXENV pattern:\n" + log,
       log.contains(Messages.ToxBuilder_ToxAxis_And_ToxenvPattern()));
 }
 /** Test artifact copy between matrix jobs, for artifact from matching axis */
 public void testMatrixToMatrix() throws Exception {
   MatrixProject other = createMatrixArtifactProject(), p = createMatrixProject();
   p.setAxes(new AxisList(new Axis("FOO", "one", "two"))); // should match other job
   p.getBuildersList()
       .add(
           new CopyArtifact(
               other.getName() + "/FOO=$FOO",
               new StatusBuildSelector(true),
               "",
               "",
               false,
               false));
   assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
   MatrixBuild b = p.scheduleBuild2(0, new UserCause()).get();
   assertBuildStatusSuccess(b);
   MatrixRun r = b.getRun(new Combination(Collections.singletonMap("FOO", "one")));
   assertFile(true, "one.txt", r);
   assertFile(false, "two.txt", r);
   r = b.getRun(new Combination(Collections.singletonMap("FOO", "two")));
   assertFile(false, "one.txt", r);
   assertFile(true, "two.txt", r);
 }
예제 #11
0
  @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);
  }
예제 #12
0
 @Override
 public AbstractBuild<?, ?> resolveChild(Child child) {
   MatrixBuild b = (MatrixBuild) owner;
   return b.getRun(Combination.fromString(child.name));
 }