Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-43507] Switch to GitHubSCMBuilder
  • Loading branch information
stephenc committed Jun 16, 2017
1 parent 338984c commit 10b52c1
Show file tree
Hide file tree
Showing 49 changed files with 4,126 additions and 797 deletions.
22 changes: 13 additions & 9 deletions pom.xml
Expand Up @@ -23,7 +23,7 @@
<properties>
<jenkins.version>1.625.3</jenkins.version>
<workflow.version>1.14.2</workflow.version>
<scm-api.version>2.2.0-SNAPSHOT</scm-api.version>
<scm-api.version>2.2.0-20170615.114844-13</scm-api.version>
</properties>

<scm>
Expand All @@ -33,6 +33,11 @@
<tag>HEAD</tag>
</scm>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
Expand All @@ -41,14 +46,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>git</artifactId>
<version>3.3.1-SNAPSHOT</version>
<exclusions>
<!-- To avoid ClassNotFoundException during InjectedTest -->
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
<version>3.4.0-20170616.082946-3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down Expand Up @@ -90,6 +88,12 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>branch-api</artifactId>
<version>2.0.11-20170615.161903-2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-aggregator</artifactId>
Expand Down
@@ -1,146 +1,256 @@
/*
* The MIT License
*
* Copyright (c) 2017, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jenkinsci.plugins.github_branch_source;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.scm.SCM;
import hudson.util.ListBoxModel;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.SCMHeadOrigin;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.trait.SCMBuilder;
import jenkins.scm.api.trait.SCMHeadAuthority;
import jenkins.scm.api.trait.SCMHeadAuthorityDescriptor;
import jenkins.scm.api.trait.SCMHeadFilter;
import jenkins.scm.api.trait.SCMSourceContext;
import jenkins.scm.api.trait.SCMSourceRequest;
import jenkins.scm.api.trait.SCMSourceTrait;
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
import jenkins.scm.impl.trait.Discovery;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* A {@link Discovery} trait for GitHub that will discover branches on the repository.
*
* @since 2.2.0
*/
public class BranchDiscoveryTrait extends SCMSourceTrait {
/**
* The strategy encoded as a bit-field.
*/
private int strategyId;

/**
* Constructor for stapler.
*
* @param strategyId the strategy id.
*/
@DataBoundConstructor
public BranchDiscoveryTrait(int strategyId) {
this.strategyId = strategyId;
}

/**
* Constructor for legacy code.
*
* @param buildBranch build branches that are not filed as a PR.
* @param buildBranchWithPr build branches that are also PRs.
*/
public BranchDiscoveryTrait(boolean buildBranch, boolean buildBranchWithPr) {
this.strategyId = (buildBranch ? 1 : 0) + (buildBranchWithPr ? 2 : 0);
}

/**
* Returns the strategy id.
*
* @return the strategy id.
*/
public int getStrategyId() {
return strategyId;
}

/**
* Returns {@code true} if building branches that are not filed as a PR.
*
* @return {@code true} if building branches that are not filed as a PR.
*/
@Restricted(NoExternalUse.class)
public boolean isBuildBranch() {
return (strategyId & 1) != 0;

}

/**
* Returns {@code true} if building branches that are filed as a PR.
*
* @return {@code true} if building branches that are filed as a PR.
*/
@Restricted(NoExternalUse.class)
public boolean isBuildBranchesWithPR() {
return (strategyId & 2) != 0;
}

/**
* {@inheritDoc}
*/
@Override
protected <B extends SCMBuilder<B, S>, S extends SCM> void decorateBuilder(B builder) {
GitHubSCMSourceContext b = GitHubSCMSourceContext.class.cast(builder);
b.wantBranches(true);
b.withAuthority(new BranchSCMHeadAuthority());
protected void decorateContext(SCMSourceContext<?, ?> context) {
GitHubSCMSourceContext ctx = (GitHubSCMSourceContext) context;
ctx.wantBranches(true);
ctx.withAuthority(new BranchSCMHeadAuthority());
switch (strategyId) {
case 1:
b.wantOriginPRs(true);
b.withFilter(new SCMHeadFilter() {
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitHubSCMSourceRequest) {
for (GHPullRequest pullRequest: ((GitHubSCMSourceRequest) request).getPullRequests()) {
if (pullRequest.getHead().getRef().equals(head.getName())) {
// TODO correct is also a PR test
return true;
}
}
}
return false;
}
});
ctx.wantOriginPRs(true);
ctx.withFilter(new ExcludeOriginPRBranchesSCMHeadFilter());
break;
case 2:
b.wantOriginPRs(true);
b.withFilter(new SCMHeadFilter() {
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitHubSCMSourceRequest) {
for (GHPullRequest pullRequest : ((GitHubSCMSourceRequest) request).getPullRequests()) {
if (!pullRequest.getHead().getRef().equals(head.getName())) {
// TODO correct is also a PR test
return true;
}
}
}
return false;
}
});
ctx.wantOriginPRs(true);
ctx.withFilter(new OnlyOriginPRBranchesSCMHeadFilter());
break;
case 3:
default:
// we don't care if it is a PR or not, we're taking them all, no need to ask for PRs and no need
// to filter
break;

}
}

/**
* {@inheritDoc}
*/
@Override
public boolean includeCategory(@NonNull SCMHeadCategory category) {
return category.isUncategorized();
}

/**
* Our descriptor.
*/
@Extension
@Discovery
public static class DescriptorImpl extends SCMSourceTraitDescriptor {

/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return "Discover branches";
return Messages.BranchDiscoveryTrait_displayName();
}

/**
* {@inheritDoc}
*/
@Override
public boolean isApplicableToContext(@NonNull Class<? extends SCMSourceContext> contextClass) {
return GitHubSCMSourceRequest.class.isAssignableFrom(contextClass);
return GitHubSCMSourceContext.class.isAssignableFrom(contextClass);
}

/**
* Populates the strategy options.
*
* @return the stategy options.
*/
@NonNull
@Restricted(NoExternalUse.class)
@SuppressWarnings("unused") // stapler
public ListBoxModel doFillStrategyIdItems() {
ListBoxModel result = new ListBoxModel();
result.add("Only branches that are not also filed as PRs", "1");
result.add("Only branches that are also filed as PRs", "2");
result.add("All branches", "3");
result.add(Messages.BranchDiscoveryTrait_excludePRs(), "1");
result.add(Messages.BranchDiscoveryTrait_onlyPRs(), "2");
result.add(Messages.BranchDiscoveryTrait_allBranches(), "3");
return result;
}
}

/**
* Trusts branches from the origin repository.
*/
public static class BranchSCMHeadAuthority extends SCMHeadAuthority<SCMSourceRequest, BranchSCMHead, SCMRevision> {
/**
* {@inheritDoc}
*/
@Override
protected boolean checkTrusted(@NonNull SCMSourceRequest request, @NonNull BranchSCMHead head) {
return true;
}

/**
* Out descriptor.
*/
@Extension
public static class DescriptorImpl extends SCMHeadAuthorityDescriptor {
/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return null;
return Messages.BranchDiscoveryTrait_authorityDisplayName();
}

/**
* {@inheritDoc}
*/
@Override
public boolean isApplicableToOrigin(@NonNull Class<? extends SCMHeadOrigin> originClass) {
return SCMHeadOrigin.Default.class.isAssignableFrom(originClass);
}
}
}

/**
* Filter that excludes branches that are also filed as a pull request.
*/
public static class ExcludeOriginPRBranchesSCMHeadFilter extends SCMHeadFilter {
/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitHubSCMSourceRequest) {
for (GHPullRequest pullRequest : ((GitHubSCMSourceRequest) request).getPullRequests()) {
if (pullRequest.getHead().getRef().equals(head.getName())) {
// TODO correct is also a PR test
return true;
}
}
}
return false;
}
}

/**
* Filter that excludes branches that are not also filed as a pull request.
*/
public static class OnlyOriginPRBranchesSCMHeadFilter extends SCMHeadFilter {
/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitHubSCMSourceRequest) {
for (GHPullRequest pullRequest : ((GitHubSCMSourceRequest) request).getPullRequests()) {
if (!pullRequest.getHead().getRef().equals(head.getName())) {
// TODO correct is also a PR test
return true;
}
}
}
return false;
}
}
}

0 comments on commit 10b52c1

Please sign in to comment.