Skip to content

Commit 78cf816

Browse files
mbelladeyrodiere
authored andcommitted
Add new configuration that limits the issue auto-link feature
1 parent 4128ad2 commit 78cf816

File tree

5 files changed

+77
-8
lines changed

5 files changed

+77
-8
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ with the following content:
4141
---
4242
jira:
4343
projectKey: "HSEARCH" # Change to whatever your project key is
44-
insertLinksInPullRequests: true # This is optional and enables automatically adding issue links to PR descriptions
44+
insertLinksInPullRequests: true # This is optional and enables automatically adding links to Jira issues found in a PR's commits to its description
45+
linkIssuesLimit: 3 # This is optional and allows disabling automatic issue links when more than the specified number of keys are found in a PR's commits (defaults to 3)
4546
# To skip JIRA-related checks (pull request title/body includes JIRA issue keys/links etc.),
4647
# a list of ignore rules can be configured:
4748
ignore:

src/main/java/org/hibernate/infra/bot/CheckPullRequestContributionRules.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,14 @@ private List<Check> createChecks(RepositoryConfig repositoryConfig) {
138138
checks.add( new TitleCheck() );
139139

140140
if ( repositoryConfig != null && repositoryConfig.jira != null ) {
141-
final boolean checkMentions = repositoryConfig.jira.getInsertLinksInPullRequests().isEmpty()
142-
|| repositoryConfig.jira.getInsertLinksInPullRequests().get().equals( Boolean.FALSE );
141+
final Integer issueLinksLimit = repositoryConfig.jira.getInsertLinksInPullRequests().isPresent()
142+
&& repositoryConfig.jira.getInsertLinksInPullRequests().get().equals( Boolean.TRUE )
143+
? repositoryConfig.jira.getIssueLinksLimit()
144+
: null;
143145
repositoryConfig.jira.getIssueKeyPattern()
144146
.ifPresent( issueKeyPattern -> checks.add(
145147
new JiraIssuesCheck(
146-
issueKeyPattern, checkMentions, repositoryConfig.jira.getIgnore(),
148+
issueKeyPattern, issueLinksLimit, repositoryConfig.jira.getIgnore(),
147149
repositoryConfig.jira.getIgnoreFiles()
148150
) ) );
149151
}
@@ -172,17 +174,17 @@ static class JiraIssuesCheck extends Check {
172174

173175
private final Pattern issueKeyPattern;
174176

175-
private final boolean checkMentions;
177+
private final Integer issueLinksLimit;
176178

177179
private final List<RepositoryConfig.IgnoreConfiguration> ignoredPRConfigurations;
178180
private final GlobMatcher ignoredFilesMatcher;
179181

180-
JiraIssuesCheck(Pattern issueKeyPattern, boolean checkMentions,
182+
JiraIssuesCheck(Pattern issueKeyPattern, Integer issueLinksLimit,
181183
List<RepositoryConfig.IgnoreConfiguration> ignoredPRConfigurations,
182184
List<String> ignoreFilePatterns) {
183185
super( "Contribution — JIRA issues" );
184186
this.issueKeyPattern = issueKeyPattern;
185-
this.checkMentions = checkMentions;
187+
this.issueLinksLimit = issueLinksLimit;
186188
this.ignoredPRConfigurations = ignoredPRConfigurations;
187189
this.ignoredFilesMatcher = new GlobMatcher( ignoreFilePatterns );
188190
}
@@ -222,7 +224,7 @@ public void perform(CheckRunContext context, CheckRunOutput output) throws IOExc
222224
commitRule.failed( "Offending commits: " + commitsWithMessageNotStartingWithIssueKey );
223225
}
224226

225-
if ( checkMentions ) {
227+
if ( issueLinksLimit == null || issueKeys.size() > issueLinksLimit ) {
226228
// We only need to check mentions if automatic body editing is disabled
227229
CheckRunRule pullRequestRule = output.rule(
228230
"The PR title or body should list the keys of all JIRA issues mentioned in the commits" );

src/main/java/org/hibernate/infra/bot/EditPullRequestBodyAddIssueLinks.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ private void editPullRequestBodyAddIssueLinks(
7979
LOG.debug( "Found no issue keys in commits, terminating." );
8080
return;
8181
}
82+
else if ( issueKeys.size() > repositoryConfig.jira.getIssueLinksLimit() ) {
83+
LOG.debug( "Found more issues than the configured limit, terminating." );
84+
return;
85+
}
8286

8387
final String originalBody = Objects.toString( pullRequest.getBody(), "" );
8488

src/main/java/org/hibernate/infra/bot/config/RepositoryConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public static class JiraConfig {
1515
private Optional<Pattern> issueKeyPattern = Optional.empty();
1616

1717
private Optional<Boolean> insertLinksInPullRequests = Optional.empty();
18+
private Integer issueLinksLimit = 3;
1819

1920
private List<IgnoreConfiguration> ignore = Collections.emptyList();
2021

@@ -36,6 +37,14 @@ public Optional<Boolean> getInsertLinksInPullRequests() {
3637
return insertLinksInPullRequests;
3738
}
3839

40+
public Integer getIssueLinksLimit() {
41+
return issueLinksLimit;
42+
}
43+
44+
public void setIssueLinksLimit(Integer issueLinksLimit) {
45+
this.issueLinksLimit = issueLinksLimit;
46+
}
47+
3948
public List<IgnoreConfiguration> getIgnore() {
4049
return ignore;
4150
}

src/test/java/org/hibernate/infra/bot/tests/EditPullRequestBodyAddIssueLinksTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515

1616
import static io.quarkiverse.githubapp.testing.GitHubAppTesting.given;
1717
import static org.assertj.core.api.Assertions.assertThat;
18+
import static org.mockito.Mockito.never;
1819
import static org.mockito.Mockito.times;
1920
import static org.mockito.Mockito.verify;
21+
import static org.mockito.Mockito.verifyNoMoreInteractions;
2022
import static org.mockito.Mockito.when;
2123

2224
@QuarkusTest
@@ -232,4 +234,55 @@ void bodyContainsAllIssues() throws IOException {
232234
} );
233235
}
234236

237+
238+
@Test
239+
void tooManyIssues() throws IOException {
240+
long repoId = 344815557L;
241+
long prId = 585627026L;
242+
given()
243+
.github( mocks -> {
244+
mocks.configFile("hibernate-github-bot.yml")
245+
.fromString( """
246+
jira:
247+
projectKey: "HSEARCH"
248+
insertLinksInPullRequests: true
249+
issueLinksLimit: 3
250+
""" );
251+
252+
GHRepository repoMock = mocks.repository( "yrodiere/hibernate-github-bot-playground" );
253+
when( repoMock.getId() ).thenReturn( repoId );
254+
255+
PullRequestMockHelper.start( mocks, prId, repoMock )
256+
.commit( "HSEARCH-1111 Commit 1" )
257+
.commit( "HSEARCH-1112 Commit 2" )
258+
.commit( "HSEARCH-1113 HSEARCH-1114 HSEARCH-1115 Commit 3" )
259+
.commit( "HSEARCH-1116 Commit 4" )
260+
.comment( "Some comment" )
261+
.comment( "Some other comment" );
262+
263+
mockCheckRuns( repoMock, "6e9f11a1e2946b207c6eb245ec942f2b5a3ea156" );
264+
} )
265+
.when()
266+
.payloadFromClasspath( "/pullrequest-opened-hsearch-1111.json" )
267+
.event( GHEvent.PULL_REQUEST )
268+
.then()
269+
.github( mocks -> {
270+
GHPullRequest prMock = mocks.pullRequest( prId );
271+
ArgumentCaptor<String> bodyCaptor = ArgumentCaptor.forClass( String.class );
272+
verify( prMock, never() ).setBody( bodyCaptor.capture() );
273+
ArgumentCaptor<String> commentCaptor = ArgumentCaptor.forClass( String.class );
274+
verify( prMock ).comment( commentCaptor.capture() );
275+
assertThat( commentCaptor.getValue() )
276+
.isEqualTo( """
277+
Thanks for your pull request!
278+
279+
This pull request does not follow the contribution rules. Could you have a look?
280+
281+
❌ The PR title or body should list the keys of all JIRA issues mentioned in the commits
282+
    ↳ Issue keys mentioned in commits but missing from the PR title or body: [HSEARCH-1112, HSEARCH-1113, HSEARCH-1114, HSEARCH-1115, HSEARCH-1116]
283+
284+
› This message was automatically generated.""" );
285+
verifyNoMoreInteractions( mocks.ghObjects() );
286+
} );
287+
}
235288
}

0 commit comments

Comments
 (0)