Skip to content

Commit 60d705b

Browse files
committed
Make the bot add branch labels/title-prefixes to the pull requests targeting non-main branch
1 parent 56deb36 commit 60d705b

File tree

5 files changed

+859
-0
lines changed

5 files changed

+859
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ pullRequestTasks:
140140
# Tasks specific to the improvement issue type:
141141
improvement:
142142
- improvement task1
143+
branches:
144+
# Make the bot add a label with the name of base ref when a pull requests target a non-main branch.
145+
enabled: true
146+
# Prefix is only added when a prefix format is passed. Must contain a single %s that will be replaced with the base ref
147+
titlePrefix: "[%s]"
148+
# Label is only added when a label format is passed. Must contain a single %s that will be replaced with the base ref
149+
label: "branch-%s"
150+
ignore:
151+
# as other config sections, supports ignore rules
143152
```
144153

145154
### Altering the infrastructure
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package org.hibernate.infra.bot;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
import java.util.Locale;
6+
import java.util.Random;
7+
8+
import org.hibernate.infra.bot.config.DeploymentConfig;
9+
import org.hibernate.infra.bot.config.RepositoryConfig;
10+
11+
import org.jboss.logging.Logger;
12+
13+
import io.quarkiverse.githubapp.ConfigFile;
14+
import io.quarkiverse.githubapp.event.PullRequest;
15+
import jakarta.inject.Inject;
16+
import org.kohsuke.github.GHEventPayload;
17+
import org.kohsuke.github.GHFileNotFoundException;
18+
import org.kohsuke.github.GHIssueState;
19+
import org.kohsuke.github.GHLabel;
20+
import org.kohsuke.github.GHPullRequest;
21+
import org.kohsuke.github.GHRepository;
22+
import org.kohsuke.github.GHUser;
23+
24+
public class EditPullRequestAddBranchTagLabel {
25+
private static final Logger LOG = Logger.getLogger( EditPullRequestAddBranchTagLabel.class );
26+
27+
@Inject
28+
DeploymentConfig deploymentConfig;
29+
30+
void pullRequestChanged(
31+
@PullRequest.Opened @PullRequest.Reopened @PullRequest.Edited @PullRequest.Synchronize
32+
GHEventPayload.PullRequest payload,
33+
@ConfigFile("hibernate-github-bot.yml") RepositoryConfig repositoryConfig
34+
) throws IOException {
35+
addTagOrLabel( payload.getRepository(), repositoryConfig, payload.getPullRequest() );
36+
}
37+
38+
private void addTagOrLabel(
39+
GHRepository repository,
40+
RepositoryConfig repositoryConfig,
41+
GHPullRequest pullRequest
42+
) throws IOException {
43+
if ( repositoryConfig == null || repositoryConfig.branches == null
44+
|| !repositoryConfig.branches.getEnabled().orElse( Boolean.FALSE ) ) {
45+
return;
46+
}
47+
48+
if ( !shouldCheck( repository, pullRequest, repositoryConfig.branches.getIgnore() ) ) {
49+
return;
50+
}
51+
52+
String base = pullRequest.getBase().getRef();
53+
if ( "main".equalsIgnoreCase( base ) ) {
54+
return;
55+
}
56+
57+
if ( repositoryConfig.branches.getTitlePrefix().isPresent() ) {
58+
String prefix = String.format( Locale.ROOT, repositoryConfig.branches.getTitlePrefix().get(), base );
59+
String title = pullRequest.getTitle();
60+
if ( !title.startsWith( prefix ) ) {
61+
if ( !deploymentConfig.isDryRun() ) {
62+
pullRequest.setTitle( prefix + " " + title );
63+
}
64+
else {
65+
LOG.info( "Pull request #" + pullRequest.getNumber() + " - Setting title to: " + title );
66+
}
67+
}
68+
}
69+
70+
if ( repositoryConfig.branches.getLabel().isPresent() ) {
71+
String labelName = String.format( Locale.ROOT, repositoryConfig.branches.getLabel().get(), base );
72+
for ( GHLabel ghLabel : pullRequest.getLabels() ) {
73+
if ( ghLabel.getName().equals( labelName ) ) {
74+
return;
75+
}
76+
}
77+
78+
GHLabel label;
79+
try {
80+
label = repository.getLabel( base );
81+
}
82+
catch (GHFileNotFoundException e) {
83+
label = repository.createLabel(
84+
base,
85+
String.format( Locale.ROOT, "%06x", new Random().nextInt( 0xffffff + 1 ) ),
86+
"Label for pull requests targeting [" + base + "] branch."
87+
);
88+
}
89+
90+
if ( !deploymentConfig.isDryRun() ) {
91+
pullRequest.addLabels( label );
92+
}
93+
else {
94+
LOG.info( "Pull request #" + pullRequest.getNumber() + " - Adding label: " + label.getName() );
95+
}
96+
}
97+
}
98+
99+
private boolean shouldCheck(GHRepository repository, GHPullRequest pullRequest, List<RepositoryConfig.IgnoreConfiguration> ignoredPRConfigurations) throws IOException {
100+
GHUser author = pullRequest.getUser();
101+
String title = pullRequest.getTitle();
102+
for ( RepositoryConfig.IgnoreConfiguration ignore : ignoredPRConfigurations ) {
103+
if ( ignore.getUser().equals( author.getLogin() )
104+
&& ignore.getTitlePattern().matcher( title ).matches() ) {
105+
return false;
106+
}
107+
}
108+
return !GHIssueState.CLOSED.equals( pullRequest.getState() )
109+
&& repository.getId() == pullRequest.getBase().getRepository().getId();
110+
}
111+
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public class RepositoryConfig {
2020

2121
public TaskList pullRequestTasks;
2222

23+
public BranchLabel branches;
24+
2325
public static class JiraConfig {
2426
private Optional<Pattern> issueKeyPattern = Optional.empty();
2527

@@ -229,4 +231,43 @@ public void setIgnore(List<IgnoreConfiguration> ignore) {
229231
this.ignore = ignore;
230232
}
231233
}
234+
235+
public static class BranchLabel {
236+
private Optional<Boolean> enabled = Optional.empty();
237+
private List<IgnoreConfiguration> ignore = Collections.emptyList();
238+
private Optional<String> label = Optional.empty();
239+
private Optional<String> titlePrefix = Optional.empty();
240+
241+
public Optional<Boolean> getEnabled() {
242+
return enabled;
243+
}
244+
245+
public void setEnabled(Boolean enabled) {
246+
this.enabled = Optional.of( enabled );
247+
}
248+
249+
public List<IgnoreConfiguration> getIgnore() {
250+
return ignore;
251+
}
252+
253+
public void setIgnore(List<IgnoreConfiguration> ignore) {
254+
this.ignore = ignore;
255+
}
256+
257+
public Optional<String> getLabel() {
258+
return label;
259+
}
260+
261+
public void setLabel(String label) {
262+
this.label = Optional.of( label );
263+
}
264+
265+
public Optional<String> getTitlePrefix() {
266+
return titlePrefix;
267+
}
268+
269+
public void setTitlePrefix(String titlePrefix) {
270+
this.titlePrefix = Optional.of( titlePrefix );
271+
}
272+
}
232273
}

0 commit comments

Comments
 (0)