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
4 changes: 4 additions & 0 deletions src/main/java/org/wildfly/bot/PullRequestRuleProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ void pullRequestRuleCheck(
return;
}

if (githubProcessor.hasDuplicateCommitInBase(pullRequest, pullRequestPayload.getRepository())) {
return;
}

GHRepository repository = pullRequest.getRepository();
SequencedMap<String, List<String>> ccMentionsWithRules = new LinkedHashMap<>();
Set<String> reviewers = new HashSet<>();
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/org/wildfly/bot/util/GithubProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHCommitQueryBuilder;
import org.kohsuke.github.GHCommitState;
import org.kohsuke.github.GHIssueComment;
import org.kohsuke.github.GHLabel;
import org.kohsuke.github.GHPerson;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHPullRequestCommitDetail;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GHUser;
import org.kohsuke.github.GitHub;
Expand Down Expand Up @@ -389,4 +392,33 @@ private String createCCMentionComment(SequencedMap<String, List<String>> ccMenti
)
.toList());
}

public boolean hasDuplicateCommitInBase(GHPullRequest pullRequest, GHRepository repository)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to have the hasDuplicateCommitInBase defined in the GithubProcessor, rather than having a private method in PullRequestRuleProcessor?

Afaik, the method does not use any of the class's states except for LOG.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh, I placed it there, since the PullRequestRuleProcessor already uses method which are specific for this class and are in the GithubProcessor.
However, I can change it if you think it is better. I have no real preference, since I can see that there are some processors that also have helper methods inside its own class, and other which have those helper methods in GithubProcessor

Copy link
Copy Markdown
Collaborator

@mskacelik mskacelik Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking of three possible solutions:

1) Remove the method and use private methods for each processor.

Cons:

  • It would be impossible to test, especially if some private methods perform more complex tasks.
  • It would also bloat the individual Processor classes.

2) Make it a static method.

Pros:

  • Since it's stateless, it would make more sense to have it as a static method.
  • Decomposition.

Cons:

3.) Leave it as it is.

  • ...

Copy link
Copy Markdown
Collaborator Author

@xjusko xjusko Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave it as it is. Or at least change it in another PR if it is needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

throws IOException {
String baseBranch = pullRequest.getBase().getRef();
GHCommitQueryBuilder commitQuery = repository.queryCommits();
if (commitQuery == null) {
return false;
}

Set<String> baseCommitSHAs = commitQuery
.from(baseBranch)
.pageSize(100)
.list()
.toSet()
.stream()
.map(GHCommit::getSHA1)
.collect(Collectors.toSet());

for (GHPullRequestCommitDetail prCommit : pullRequest.listCommits()) {
String prSha = prCommit.getSha();
if (baseCommitSHAs.contains(prSha)) {
LOG.infof("Skipping rules due to incorrect rebase detected: commit %s is already in the base branch %s",
prSha,
baseBranch);
return true;
}
}
return false;
}
}
61 changes: 60 additions & 1 deletion src/test/java/org/wildfly/bot/PRSkipPullRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,30 @@
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHCommitQueryBuilder;
import org.kohsuke.github.GHPullRequestCommitDetail;
import org.kohsuke.github.PagedIterable;
import org.kohsuke.github.PagedIterator;
import org.wildfly.bot.utils.TestConstants;
import org.wildfly.bot.utils.WildflyGitHubBotTesting;
import org.wildfly.bot.utils.mocking.Mockable;
import org.wildfly.bot.utils.mocking.MockedGHPullRequest;
import org.wildfly.bot.utils.testing.PullRequestJson;
import org.wildfly.bot.utils.testing.internal.TestModel;

import java.util.Set;

import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

@QuarkusTest
@GitHubAppTest
Expand Down Expand Up @@ -81,4 +95,49 @@ void testSkippingFormatCheckOnDraft() throws Throwable {
verifyNoMoreInteractions(mocks.pullRequest(pullRequestJson.id()));
});
}
}

@Test
void testSkippingRulesOnIncorrectRebase() throws Throwable {
final String duplicateSHA = "sha1";
final String baseBranch = "main";
pullRequestJson = TestModel.setPullRequestJsonBuilder(pullRequestJsonBuilder -> pullRequestJsonBuilder);
mockedContext = MockedGHPullRequest.builder(pullRequestJson.id());
TestModel.given(
mocks -> {
WildflyGitHubBotTesting.mockRepo(mocks, wildflyConfigFile, pullRequestJson, mockedContext);
GHCommit commit1 = mock(GHCommit.class);
GHCommit commit2 = mock(GHCommit.class);

when(commit1.getSHA1()).thenReturn(duplicateSHA);
when(commit2.getSHA1()).thenReturn("sha2");

// Create a fake PagedIterable for repository commits.
Set<GHCommit> fakeRepoCommitSet = Set.of(commit1, commit2);
PagedIterable<GHCommit> fakeRepoCommits = mock(PagedIterable.class);
GHCommitQueryBuilder mockedQueryBuilder = mock(GHCommitQueryBuilder.class);

when(mocks.repository(TestConstants.TEST_REPO).queryCommits()).thenReturn(mockedQueryBuilder);
when(mockedQueryBuilder.from(eq(baseBranch))).thenReturn(mockedQueryBuilder);
when(mockedQueryBuilder.pageSize(anyInt())).thenReturn(mockedQueryBuilder);
when(mockedQueryBuilder.list()).thenReturn(fakeRepoCommits);
when(fakeRepoCommits.toSet()).thenReturn(fakeRepoCommitSet);

GHPullRequestCommitDetail fakePRCommit = mock(GHPullRequestCommitDetail.class);
PagedIterator<GHPullRequestCommitDetail> mockIterator = mock(PagedIterator.class);
PagedIterable<GHPullRequestCommitDetail> fakePRCommits = mock(PagedIterable.class);

when(fakePRCommit.getSha()).thenReturn(duplicateSHA);
when(mockIterator.hasNext()).thenReturn(true, false);
when(mockIterator.next()).thenReturn(fakePRCommit);
when(mocks.pullRequest(pullRequestJson.id()).listCommits()).thenReturn(fakePRCommits);
when(fakePRCommits._iterator(anyInt())).thenReturn(mockIterator);
})
.pullRequestEvent(pullRequestJson)
.then(mocks -> {
verify(mocks.pullRequest(pullRequestJson.id())).getBase();
verify(mocks.repository(TestConstants.TEST_REPO)).queryCommits();
verify(mocks.pullRequest(pullRequestJson.id()), never()).addLabels(nullable(String[].class));
verify(mocks.pullRequest(pullRequestJson.id()), never()).requestReviewers(any());
});
}
}
1 change: 1 addition & 0 deletions src/test/java/org/wildfly/bot/PRTriggerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ private void checkValidRun(SsePullRequestPayload ssePullRequestPayload, Action a
Mockito.verify(repo, Mockito.atMostOnce()).listLabels();
Mockito.verify(repo, Mockito.atMostOnce()).createLabel(ArgumentMatchers.anyString(),
ArgumentMatchers.anyString());
Mockito.verify(repo, Mockito.atMostOnce()).queryCommits();
Mockito.verifyNoMoreInteractions(repo);
});
}
Expand Down
Loading