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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ The following behaviours apply to both `Multibranch Pipeline Jobs` and `Folder O

* `Only Branches that are not also filed as MRs` - If you are discovering origin merge requests, it may not make sense to discover the same changes both as a merge request and as a branch.
* `Only Branches that are filed as MRs` - This option exists to preserve legacy behaviour when upgrading from older versions of the plugin. NOTE: If you have an actual use case for this option please file a merge request against this text.
* `Only explicitly listed branches` - Only branches matching the "Branches to always include" regex are built as branches. Useful when builing only long-lived branches (e.g. `main`) and MRs (discovered separately).
* `All Branches` - Ignores whether the branch is also filed as a merge request and instead discovers all branches on the origin project.

* `Discover merge requests from origin` - To discover merge requests made from origin branches.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,195 +143,222 @@
ctx.wantOriginMRs(true);
ctx.withFilter(new OnlyOriginMRBranchesSCMHeadFilter(getBranchesAlwaysIncludedRegexPattern()));
break;
case 4:
ctx.withFilter(new OnlyExplicitlyListedBranchesSCMHeadFilter(getBranchesAlwaysIncludedRegexPattern()));
break;
case 3:
default:
// we don't care if it is a MR or not, we're taking them all, no need to ask for MRs and no need
// to filter
break;
}
}

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

/**
* Our descriptor.
*/
@Symbol("gitLabBranchDiscovery")
@Extension
@Discovery
public static class DescriptorImpl extends SCMSourceTraitDescriptor {

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

/**
* {@inheritDoc}
*/
@Override
public Class<? extends SCMSourceContext> getContextClass() {
return GitLabSCMSourceContext.class;
}

/**
* {@inheritDoc}
*/
@Override
public Class<? extends SCMSource> getSourceClass() {
return GitLabSCMSource.class;
}

/**
* Populates the strategy options.
*
* @return the stategy options.
*/
@NonNull
@Restricted(NoExternalUse.class)
@SuppressWarnings("unused") // stapler
public ListBoxModel doFillStrategyIdItems() {
ListBoxModel result = new ListBoxModel();
result.add(Messages.BranchDiscoveryTrait_excludeMRs(), "1");
result.add(Messages.BranchDiscoveryTrait_onlyMRs(), "2");
result.add(Messages.BranchDiscoveryTrait_onlyExplicitlyListed(), "4");
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
@Symbol("gitLabBranchHeadAuthority")
public static class DescriptorImpl extends SCMHeadAuthorityDescriptor {

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

/**
* {@inheritDoc}
*/
@NonNull
@Override
public String getDisplayName() {
return Messages.BranchDiscoveryTrait_authorityDisplayName();
}
}
}

/**
* Filter that excludes branches that are also filed as a merge request.
* Base class for branch filters that support an always-included regex.
* Handles the common filter then delegates to {@link #isExcludedBranch} for strategy-specific logic.
*/
public static class ExcludeOriginMRBranchesSCMHeadFilter extends SCMHeadFilter {
public abstract static class BranchDiscoverySCMHeadFilter extends SCMHeadFilter {

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

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

/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitLabSCMSourceRequest) {
if (branchesAlwaysIncludedRegexPattern != null
&& branchesAlwaysIncludedRegexPattern
.matcher(head.getName())
.matches()) {
return false;
}
public final boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (!(head instanceof BranchSCMHead)) {
return false;
}
if (branchesAlwaysIncludedRegexPattern != null
&& branchesAlwaysIncludedRegexPattern
.matcher(head.getName())
.matches()) {
return false;
}
return isExcludedBranch(request, (BranchSCMHead) head);
}

/**
* Strategy-specific exclusion logic, called only for branch heads not covered by
* the always-included regex.
*
* @param request the current SCM source request.
* @param head the branch head being evaluated.
* @return {@code true} if the branch should be excluded from discovery.
*/
protected abstract boolean isExcludedBranch(@NonNull SCMSourceRequest request, @NonNull BranchSCMHead head);
}

/**
* Filter that excludes branches that are also filed as a merge request.
*/
public static class ExcludeOriginMRBranchesSCMHeadFilter extends BranchDiscoverySCMHeadFilter {

public ExcludeOriginMRBranchesSCMHeadFilter(Pattern branchesAlwaysIncludedRegexPattern) {
super(branchesAlwaysIncludedRegexPattern);
}

@Override
protected boolean isExcludedBranch(@NonNull SCMSourceRequest request, @NonNull BranchSCMHead head) {
if (request instanceof GitLabSCMSourceRequest) {
for (MergeRequest m : ((GitLabSCMSourceRequest) request).getMergeRequests()) {
// only match if the merge request is an origin merge request
if (m.getSourceProjectId().equals(m.getTargetProjectId())
&& m.getSourceBranch().equalsIgnoreCase(head.getName())) {
return true;
}
}
}
return false;
}
}

/**
* Filter that excludes branches that are not also filed as a merge request.
*/
public static class OnlyOriginMRBranchesSCMHeadFilter extends SCMHeadFilter {

/**
* The compiled {@link Pattern} of the branchesAlwaysIncludedRegex.
*/
private final Pattern branchesAlwaysIncludedRegexPattern;
public static class OnlyOriginMRBranchesSCMHeadFilter extends BranchDiscoverySCMHeadFilter {

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

/**
* {@inheritDoc}
*/
@Override
public boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head) {
if (head instanceof BranchSCMHead && request instanceof GitLabSCMSourceRequest) {
if (branchesAlwaysIncludedRegexPattern != null
&& branchesAlwaysIncludedRegexPattern
.matcher(head.getName())
.matches()) {
return false;
}

protected boolean isExcludedBranch(@NonNull SCMSourceRequest request, @NonNull BranchSCMHead head) {
if (request instanceof GitLabSCMSourceRequest) {
for (MergeRequest m : ((GitLabSCMSourceRequest) request).getMergeRequests()) {
if (m.getSourceProjectId().equals(m.getTargetProjectId())
&& !m.getSourceBranch().equalsIgnoreCase(head.getName())) {
return true;
}
}
}
return false;
}
}

/**
* Filter that excludes all branches except those matching the always-included regex.
*/
public static class OnlyExplicitlyListedBranchesSCMHeadFilter extends BranchDiscoverySCMHeadFilter {

public OnlyExplicitlyListedBranchesSCMHeadFilter(Pattern branchesAlwaysIncludedRegexPattern) {
super(branchesAlwaysIncludedRegexPattern);
}

@Override
protected boolean isExcludedBranch(@NonNull SCMSourceRequest request, @NonNull BranchSCMHead head) {
return true;

Check warning on line 361 in src/main/java/io/jenkins/plugins/gitlabbranchsource/BranchDiscoveryTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 147-361 are not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@
on the
origin project.
</dd>
<dt>Only explicitly listed branches</dt>
<dd>
Only branches matching the "Branches to always include" regex are built as branches.
</dd>
</dl>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ BranchDiscoveryTrait.authorityDisplayName=Trust origin branches
BranchDiscoveryTrait.displayName=Discover branches
BranchDiscoveryTrait.excludeMRs=Only branches that are not also filed as MRs
BranchDiscoveryTrait.onlyMRs=Only branches that are also filed as MRs
BranchDiscoveryTrait.onlyExplicitlyListed=Only explicitly listed branches
ExcludeArchivedRepositoriesTrait.displayName=Exclude archived repositories
BuildStatusNameCustomPartTrait.displayName=Customize GitLab build status name
ForkMergeRequestDiscoveryTrait.displayName=Discover merge requests from forks
Expand Down