Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-47308] Add the ability for branch build strategies to …
…consider the revision
  • Loading branch information
stephenc committed Oct 6, 2017
1 parent 22c8d12 commit 709eefd
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 6 deletions.
18 changes: 18 additions & 0 deletions src/main/java/jenkins/branch/BranchBuildStrategy.java
Expand Up @@ -26,9 +26,13 @@
import hudson.ExtensionPoint;
import hudson.model.AbstractDescribableImpl;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSource;

/**
* An extension point that allows controlling whether a specific {@link SCMHead} should be automatically built when
* discovered.
*
* @since 2.0.0
*/
public abstract class BranchBuildStrategy extends AbstractDescribableImpl<BranchBuildStrategy>
Expand All @@ -44,6 +48,20 @@ public abstract class BranchBuildStrategy extends AbstractDescribableImpl<Branch
*/
public abstract boolean isAutomaticBuild(SCMSource source, SCMHead head);

/**
* Should the specified {@link SCMRevision} of the {@link SCMHead} for the specified {@link SCMSource} be triggered
* when the {@link SCMHead} has been detected as created / modified?
*
* @param source the {@link SCMSource}
* @param head the {@link SCMHead}
* @return {@code true} if and only if the {@link SCMRevision} should be automatically built when the
* {@link SCMHead} has been detected as created / modified.
* @since 2.0.12
*/
public boolean isAutomaticBuild(SCMSource source, SCMHead head, SCMRevision revision) {
return isAutomaticBuild(source, head);
}

/**
* {@inheritDoc}
*/
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/jenkins/branch/MultiBranchProject.java
Expand Up @@ -2015,7 +2015,7 @@ public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) throws
revision
);
needSave = true;
if (isAutomaticBuild(source, head)) {
if (isAutomaticBuild(source, head, revision)) {
scheduleBuild(
_factory,
project,
Expand All @@ -2034,7 +2034,7 @@ public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) throws
listener.getLogger()
.format("Changes detected: %s (%s → %s)%n", rawName, lastBuild, revision);
needSave = true;
if (isAutomaticBuild(source, head)) {
if (isAutomaticBuild(source, head, revision)) {
scheduleBuild(
_factory,
project,
Expand All @@ -2058,7 +2058,7 @@ public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) throws
if (pollingResult.hasChanges()) {
listener.getLogger().format("Changes detected: %s%n", rawName);
needSave = true;
if (isAutomaticBuild(source, head)) {
if (isAutomaticBuild(source, head, revision)) {
scheduleBuild(
_factory,
project,
Expand Down Expand Up @@ -2122,7 +2122,7 @@ public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) throws
_factory.decorate(project);
// ok it is now up to the observer to ensure it does the actual save.
observer.created(project);
if (isAutomaticBuild(source, head)) {
if (isAutomaticBuild(source, head, revision)) {
scheduleBuild(
_factory,
project,
Expand All @@ -2145,9 +2145,10 @@ public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) throws
* Tests if the specified {@link SCMHead} should be automatically built when discovered / modified.
* @param source the source.
* @param head the head.
* @param revision the revision.
* @return {@code true} if the head should be automatically built when discovered / modified.
*/
private boolean isAutomaticBuild(SCMSource source, SCMHead head) {
private boolean isAutomaticBuild(SCMSource source, SCMHead head, SCMRevision revision) {
BranchSource branchSource = null;
for (BranchSource s: sources) {
if (s.getSource().getId().equals(source.getId())) {
Expand All @@ -2165,7 +2166,7 @@ private boolean isAutomaticBuild(SCMSource source, SCMHead head) {
return !(head instanceof TagSCMHead);
} else {
for (BranchBuildStrategy s: buildStrategies) {
if (s.isAutomaticBuild(source, head)) {
if (s.isAutomaticBuild(source, head, revision)) {
return true;
}
}
Expand Down
76 changes: 76 additions & 0 deletions src/test/java/integration/EventsTest.java
Expand Up @@ -46,7 +46,9 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -62,6 +64,7 @@
import jenkins.scm.api.SCMEvents;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadEvent;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.SCMSourceEvent;
import jenkins.scm.api.mixin.ChangeRequestCheckoutStrategy;
Expand All @@ -72,8 +75,10 @@
import jenkins.scm.impl.mock.MockSCMDiscoverBranches;
import jenkins.scm.impl.mock.MockSCMDiscoverChangeRequests;
import jenkins.scm.impl.mock.MockSCMDiscoverTags;
import jenkins.scm.impl.mock.MockSCMHead;
import jenkins.scm.impl.mock.MockSCMHeadEvent;
import jenkins.scm.impl.mock.MockSCMNavigator;
import jenkins.scm.impl.mock.MockSCMRevision;
import jenkins.scm.impl.mock.MockSCMSource;
import jenkins.scm.impl.mock.MockSCMSourceEvent;
import jenkins.scm.impl.trait.WildcardSCMSourceFilterTrait;
Expand Down Expand Up @@ -937,6 +942,77 @@ public void given_multibranchWithSources_when_createEventWhileIndexing_then_only
}
}

public static class BuildRevisionStrategyImpl extends BranchBuildStrategy {
private final Set<String> approved;

public BuildRevisionStrategyImpl(String... approved) {
this.approved = new HashSet<>(Arrays.asList(approved));
}

@Override
public boolean isAutomaticBuild(SCMSource source, SCMHead head) {
return true;
}

@Override
public boolean isAutomaticBuild(SCMSource source, SCMHead head, SCMRevision revision) {
return revision instanceof MockSCMRevision
&& approved.contains(((MockSCMRevision) revision).getHash())
&& super.isAutomaticBuild(source, head, revision);
}

@TestExtension(
"given_multibranchWithRevisionSpecificStrategy_when_indexing_then_everythingIsFoundButMagicRevisionOnlyBuilt")
public static class DescriptorImpl extends BranchBuildStrategyDescriptor {

}
}

@Test
@Issue("JENKINS-47308")
public void
given_multibranchWithRevisionSpecificStrategy_when_indexing_then_everythingIsFoundButMagicRevisionOnlyBuilt()
throws Exception {
try (MockSCMController c = MockSCMController.create()) {
c.createRepository("foo");
c.createTag("foo", "master", "master-1.0");
c.cloneBranch("foo", "master","stable");
c.addFile("foo", "master", "new revision", "dummy.txt", "anything".getBytes("UTF-8"));
c.cloneBranch("foo", "master", "development");
Integer crNum = c.openChangeRequest("foo", "master");
BasicMultiBranchProject prj = r.jenkins.createProject(BasicMultiBranchProject.class, "foo");
prj.setCriteria(null);
BranchSource source = new BranchSource(new MockSCMSource(c, "foo", new MockSCMDiscoverBranches(),
new MockSCMDiscoverTags(), new MockSCMDiscoverChangeRequests()));
source.setBuildStrategies(Arrays.<BranchBuildStrategy>asList(new BuildRevisionStrategyImpl(c.getRevision("foo", "master"))));
prj.getSourcesList().add(source);
prj.scheduleBuild2(0).getFuture().get();
r.waitUntilNoActivity();
assertThat("We now have projects",
prj.getItems(), not(Matchers.<FreeStyleProject>empty()));
FreeStyleProject master = prj.getItem("master");
assertThat("We have master branch", master, notNullValue());
FreeStyleProject stable = prj.getItem("stable");
assertThat("We have stable branch", stable, notNullValue());
FreeStyleProject development = prj.getItem("development");
assertThat("We have development branch", development, notNullValue());
FreeStyleProject tag = prj.getItem("master-1.0");
assertThat("We have master-1.0 tag", tag, notNullValue());
FreeStyleProject cr = prj.getItem("CR-" + crNum);
assertThat("We now have the change request", cr, notNullValue());
assertThat("We have only the expected items",
prj.getItems(), containsInAnyOrder(cr, master, stable, development, tag));
r.waitUntilNoActivity();
assertThat("The master branch was built", master.getLastBuild(), notNullValue());
assertThat("The master branch was built", master.getLastBuild().getNumber(), is(1));
assertThat("The development branch was built", development.getLastBuild(), notNullValue());
assertThat("The development branch was built", development.getLastBuild().getNumber(), is(1));
assertThat("The stable branch was not built", stable.getLastBuild(), nullValue());
assertThat("The tag was not built", tag.getLastBuild(), nullValue());
assertThat("The change request was not built", cr.getLastBuild(), nullValue());
}
}

/**
* Waits until Hudson finishes building everything, including those in the queue, or fail the test
* if the specified timeout milliseconds is
Expand Down

0 comments on commit 709eefd

Please sign in to comment.