Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,17 @@
import com.cloudbees.jenkins.plugins.bitbucket.Messages;
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketPullRequest;
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRepository;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.Util;
import hudson.model.Item;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import java.io.IOException;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import jenkins.model.Jenkins;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadCategory;
import jenkins.scm.api.SCMHeadOrigin;
Expand All @@ -48,7 +55,11 @@
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;

/**
* A {@link Discovery} trait for bitbucket that will discover branches on the repository.
Expand All @@ -67,6 +78,17 @@
*/
private final int strategyId;

/**
* Regex of branches that should always be included regardless of whether a merge request exists or not.
*/
private String branchesAlwaysIncludedRegex;

/**
* The compiled {@link Pattern} of the branchesAlwaysIncludedRegex.
*/
@CheckForNull
private transient Pattern branchesAlwaysIncludedRegexPattern;

/**
* Constructor for stapler.
*
Expand Down Expand Up @@ -96,6 +118,36 @@
return strategyId;
}

/**
* Returns the branchesAlwaysIncludedRegex.
*
* @return the branchesAlwaysIncludedRegex.
*/
public String getBranchesAlwaysIncludedRegex() {
return branchesAlwaysIncludedRegex;
}

/**
* Sets the branchesAlwaysIncludedRegex.
*/
@DataBoundSetter
public void setBranchesAlwaysIncludedRegex(@CheckForNull String branchesAlwaysIncludedRegex) {
this.branchesAlwaysIncludedRegex = Util.fixEmptyAndTrim(branchesAlwaysIncludedRegex);
}

/**
* Returns the compiled {@link Pattern} of the branchesAlwaysIncludedRegex.
*
* @return the branchesAlwaysIncludedRegexPattern.
*/
public Pattern getBranchesAlwaysIncludedRegexPattern() {
if (branchesAlwaysIncludedRegex != null && branchesAlwaysIncludedRegexPattern == null) {

Check warning on line 144 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 144 is only partially covered, one branch is missing
branchesAlwaysIncludedRegexPattern = Pattern.compile(branchesAlwaysIncludedRegex);
}

return branchesAlwaysIncludedRegexPattern;
}

/**
* Returns {@code true} if building branches that are not filed as a PR.
*
Expand Down Expand Up @@ -127,11 +179,11 @@
switch (strategyId) {
case 1:
ctx.wantOriginPRs(true);
ctx.withFilter(new ExcludeOriginPRBranchesSCMHeadFilter());
ctx.withFilter(new ExcludeOriginPRBranchesSCMHeadFilter(getBranchesAlwaysIncludedRegexPattern()));
break;
case 2:
ctx.wantOriginPRs(true);
ctx.withFilter(new OnlyOriginPRBranchesSCMHeadFilter());
ctx.withFilter(new OnlyOriginPRBranchesSCMHeadFilter(getBranchesAlwaysIncludedRegexPattern()));
break;
case 3:
default:
Expand Down Expand Up @@ -179,6 +231,27 @@
result.add(Messages.BranchDiscoveryTrait_allBranches(), "3");
return result;
}

@NonNull
@Restricted(NoExternalUse.class)
@RequirePOST
public FormValidation doCheckBranchesAlwaysIncludedRegex(@CheckForNull @AncestorInPath Item context, @QueryParameter String value) {
if(context == null) {
Jenkins.get().checkPermission(Jenkins.MANAGE);
} else {
context.checkPermission(Item.CONFIGURE);
}

if (value == null || value.isBlank()) {
return FormValidation.ok();
}
try {
Pattern.compile(value);
return FormValidation.ok();
} catch (PatternSyntaxException ex) {
return FormValidation.error(ex.getMessage());
}
}
}

/**
Expand Down Expand Up @@ -220,12 +293,41 @@
* Filter that excludes branches that are also filed as a pull request.
*/
public static class ExcludeOriginPRBranchesSCMHeadFilter extends SCMHeadFilter {

/**
* The compiled {@link Pattern} of the branchesAlwaysIncludedRegex.
*/
private final Pattern branchesAlwaysIncludedRegexPattern;

public ExcludeOriginPRBranchesSCMHeadFilter() {
branchesAlwaysIncludedRegexPattern = null;
}

Check warning on line 304 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 302-304 are not covered by tests

/**
* Constructor
*
* @param branchesAlwaysIncludedRegexPattern the branchesAlwaysIncludedRegexPattern.
*/
public ExcludeOriginPRBranchesSCMHeadFilter(Pattern branchesAlwaysIncludedRegexPattern) {
this.branchesAlwaysIncludedRegexPattern = branchesAlwaysIncludedRegexPattern;
}

/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof BitbucketSCMSourceRequest) {
if (branchesAlwaysIncludedRegexPattern != null

Check warning on line 321 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 321 is only partially covered, one branch is missing
&& branchesAlwaysIncludedRegexPattern
.matcher(head.getName())
.matches()) {

Check warning on line 324 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 324 is only partially covered, one branch is missing
request.listener()
.getLogger()
.println("Include branch " + head.getName()
+ " because branch name matches always included pattern");
return false;
}
BitbucketSCMSourceRequest req = (BitbucketSCMSourceRequest) request;
String fullName = req.getRepoOwner() + "/" + req.getRepository();
try {
Expand All @@ -251,12 +353,42 @@
* Filter that excludes branches that are not also filed as a pull request.
*/
public static class OnlyOriginPRBranchesSCMHeadFilter extends SCMHeadFilter {

/**
* The compiled {@link Pattern} of the branchesAlwaysIncludedRegex.
*/
private final Pattern branchesAlwaysIncludedRegexPattern;

public OnlyOriginPRBranchesSCMHeadFilter() {
branchesAlwaysIncludedRegexPattern = null;
}

Check warning on line 364 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 362-364 are not covered by tests

/**
* Constructor
*
* @param branchesAlwaysIncludedRegexPattern the branchesAlwaysIncludedRegexPattern.
*/
public OnlyOriginPRBranchesSCMHeadFilter(Pattern branchesAlwaysIncludedRegexPattern) {
this.branchesAlwaysIncludedRegexPattern = branchesAlwaysIncludedRegexPattern;
}

/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof BitbucketSCMSourceRequest) {
if (branchesAlwaysIncludedRegexPattern != null

Check warning on line 381 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 381 is only partially covered, one branch is missing
&& branchesAlwaysIncludedRegexPattern
.matcher(head.getName())
.matches()) {

Check warning on line 384 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 384 is only partially covered, one branch is missing
request.listener()
.getLogger()
.println("Include branch " + head.getName()
+ " because branch name matches always included pattern");
return false;
}

BitbucketSCMSourceRequest req = (BitbucketSCMSourceRequest) request;
String fullName = req.getRepoOwner() + "/" + req.getRepository();
try {
Expand All @@ -267,8 +399,11 @@
return false;
}
}
request.listener().getLogger().println("Discard branch " + head.getName()
+ " because current strategy excludes branches that are not also filed as a pull request");
request.listener()
.getLogger()
.println(
"Discard branch " + head.getName()

Check warning on line 405 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/trait/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 402-405 are not covered by tests
+ " because current strategy excludes branches that are not also filed as a pull request");
return true;
} catch (IOException | InterruptedException e) {
// should never happens because data in the requests has been already initialised
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
<f:entry title="${%Strategy}" field="strategyId">
<f:select default="1"/>
</f:entry>
<f:entry title="${%Branches to always include}" field="branchesAlwaysIncludedRegex">
<f:textbox/>
</f:entry>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Regular expression of branches that should always be included regardless of whether a pull request exists or not for those branches.
</div>
Loading
Loading