Search in sources :

Example 1 with ConflictMessage

use of com.github.avano.pr.workflow.message.ConflictMessage in project pull-request-workflow by avano.

the class ConflictHandler method checkForConflict.

/**
 * Checks if a PR merge caused conflict in other opened PRs, if so a comment is added to each open PR and it's assigned back to the author to fix.
 *
 * @param msg {@link BusMessage} instance
 */
@Log
@ConsumeEvent(Constants.PR_CHECK_CONFLICT)
public void checkForConflict(BusMessage msg) {
    GHClient client = msg.client();
    ConflictMessage cm = msg.get(ConflictMessage.class);
    if (client.getRepositoryConfiguration().conflictMessage() == null || client.getRepositoryConfiguration().conflictMessage().isEmpty()) {
        LOG.debug("Skipping conflict detection - conflict message not set");
        return;
    }
    for (GHPullRequest openPullRequest : cm.getOpenPullRequests()) {
        try {
            openPullRequest.refresh();
            if ("dirty".equals(openPullRequest.getMergeableState())) {
                LOG.info("PR #{}: Caused conflict in PR #{}", cm.getMergedPrId(), openPullRequest.getNumber());
                client.postComment(openPullRequest, client.getRepositoryConfiguration().conflictMessage().replace("<ID>", cm.getMergedPrId() + ""));
                client.assignToAuthor(openPullRequest);
                List<String> removeLabels = new ArrayList<>();
                removeLabels.addAll(client.getRepositoryConfiguration().approvedLabels());
                removeLabels.addAll(client.getRepositoryConfiguration().reviewRequestedLabels());
                eventBus.publish(Constants.EDIT_LABELS, new BusMessage(client, new LabelsMessage(openPullRequest, client.getRepositoryConfiguration().changesRequestedLabels(), removeLabels)));
            } else {
                LOG.trace("PR #{}: No conflict in PR #{}", cm.getMergedPrId(), openPullRequest.getNumber());
            }
        } catch (IOException e) {
            LOG.error("PR #{}: Unable to process PR", openPullRequest.getNumber(), e);
        }
    }
}
Also used : GHPullRequest(org.kohsuke.github.GHPullRequest) GHClient(com.github.avano.pr.workflow.gh.GHClient) BusMessage(com.github.avano.pr.workflow.message.BusMessage) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage) LabelsMessage(com.github.avano.pr.workflow.message.LabelsMessage) Log(com.github.avano.pr.workflow.handler.interceptor.Log) ConsumeEvent(io.quarkus.vertx.ConsumeEvent)

Example 2 with ConflictMessage

use of com.github.avano.pr.workflow.message.ConflictMessage in project pull-request-workflow by avano.

the class ConflictHandlerTest method shouldAssignOtherPrToAuthorWhenConflictWasCausedTest.

@Test
public void shouldAssignOtherPrToAuthorWhenConflictWasCausedTest() {
    stubFor(WireMock.get(urlEqualTo("/repos/" + TEST_REPO + "/pulls?state=open")).willReturn(ok().withBodyFile("merge/conflict/twoMergeable.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/20")).willReturn(ok().withBodyFile("merge/conflict/20_conflict.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/21")).willReturn(ok().withBodyFile("merge/conflict/21_ok.json")));
    stubFor(WireMock.post(urlPathMatching("/repos/" + TEST_REPO + "/issues/\\d+/comments")).willReturn(aResponse().withStatus(201).withBody("{}")));
    List<GHPullRequest> pullRequestList = new ArrayList<>();
    pullRequestList.add(loadPullRequest(20));
    pullRequestList.add(loadPullRequest(21));
    ConflictMessage msg = new ConflictMessage(123, pullRequestList);
    conflictHandler.checkForConflict(new BusMessage(client, msg));
    List<LoggedRequest> requests = getRequests(WireMock.patchRequestedFor(urlPathMatching("/repos/" + TEST_REPO + "/issues/\\d+")));
    assertThat(requests).hasSize(1);
    assertThat(requests.get(0).getAbsoluteUrl()).endsWith("issues/20");
    JSONArray assignees = new JSONObject(requests.get(0).getBodyAsString()).getJSONArray("assignees");
    assertThat(assignees).containsExactly("creator");
}
Also used : GHPullRequest(org.kohsuke.github.GHPullRequest) LoggedRequest(com.github.tomakehurst.wiremock.verification.LoggedRequest) JSONObject(org.json.JSONObject) BusMessage(com.github.avano.pr.workflow.message.BusMessage) ArrayList(java.util.ArrayList) JSONArray(org.json.JSONArray) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test)

Example 3 with ConflictMessage

use of com.github.avano.pr.workflow.message.ConflictMessage in project pull-request-workflow by avano.

the class ConflictHandlerTest method shouldNotPostCommentWhenEverythingWasOkTest.

@Test
public void shouldNotPostCommentWhenEverythingWasOkTest() {
    stubFor(WireMock.get(urlEqualTo("/repos/" + TEST_REPO + "/pulls?state=open")).willReturn(ok().withBodyFile("merge/conflict/twoMergeable.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/20")).willReturn(ok().withBodyFile("merge/conflict/20_ok.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/21")).willReturn(ok().withBodyFile("merge/conflict/21_ok.json")));
    stubFor(WireMock.post(urlPathMatching("/repos/" + TEST_REPO + "/issues/\\d+/comments")).willReturn(aResponse().withStatus(201).withBody("{}")));
    List<GHPullRequest> pullRequestList = new ArrayList<>();
    pullRequestList.add(loadPullRequest(20));
    pullRequestList.add(loadPullRequest(21));
    ConflictMessage msg = new ConflictMessage(123, pullRequestList);
    conflictHandler.checkForConflict(new BusMessage(client, msg));
    List<LoggedRequest> requests = getRequests(WireMock.postRequestedFor(urlPathMatching("/repos/" + TEST_REPO + "/issues/\\d+/comments")));
    assertThat(requests).isEmpty();
}
Also used : GHPullRequest(org.kohsuke.github.GHPullRequest) LoggedRequest(com.github.tomakehurst.wiremock.verification.LoggedRequest) BusMessage(com.github.avano.pr.workflow.message.BusMessage) ArrayList(java.util.ArrayList) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test)

Example 4 with ConflictMessage

use of com.github.avano.pr.workflow.message.ConflictMessage in project pull-request-workflow by avano.

the class ConflictHandlerTest method shouldPostCommentWhenCausedConflictTest.

@Test
public void shouldPostCommentWhenCausedConflictTest() {
    stubFor(WireMock.get(urlEqualTo("/repos/" + TEST_REPO + "/pulls?state=open")).willReturn(ok().withBodyFile("merge/conflict/twoMergeable.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/20")).willReturn(ok().withBodyFile("merge/conflict/20_conflict.json")));
    stubFor(WireMock.get(urlPathMatching("/repos/" + TEST_REPO + "/pulls/21")).willReturn(ok().withBodyFile("merge/conflict/21_ok.json")));
    stubFor(WireMock.post(urlEqualTo("/repos/" + TEST_REPO + "/issues/20/comments")).willReturn(aResponse().withStatus(201).withBody("{}")));
    List<GHPullRequest> pullRequestList = new ArrayList<>();
    pullRequestList.add(loadPullRequest(20));
    pullRequestList.add(loadPullRequest(21));
    ConflictMessage msg = new ConflictMessage(123, pullRequestList);
    conflictHandler.checkForConflict(new BusMessage(client, msg));
    List<LoggedRequest> requests = getRequests(WireMock.postRequestedFor(urlPathMatching("/repos/" + TEST_REPO + "/issues/\\d+/comments")));
    assertThat(requests).hasSize(1);
    assertThat(requests.get(0).getAbsoluteUrl()).endsWith("issues/20/comments");
    assertThat(new JSONObject(requests.get(0).getBodyAsString()).getString("body")).isEqualTo(client.getRepositoryConfiguration().conflictMessage().replace("<ID>", 123 + ""));
}
Also used : GHPullRequest(org.kohsuke.github.GHPullRequest) LoggedRequest(com.github.tomakehurst.wiremock.verification.LoggedRequest) JSONObject(org.json.JSONObject) BusMessage(com.github.avano.pr.workflow.message.BusMessage) ArrayList(java.util.ArrayList) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test)

Example 5 with ConflictMessage

use of com.github.avano.pr.workflow.message.ConflictMessage in project pull-request-workflow by avano.

the class MergeHandler method mergePullRequest.

/**
 * Set the reviewers as assignees and merge the pull request.
 *
 * @param msg {@link BusMessage} instance
 */
private void mergePullRequest(BusMessage msg) {
    GHClient client = msg.client();
    GHPullRequest pr = msg.get(GHPullRequest.class);
    try {
        if (!Constants.DEPENDABOT_NAME.equals(client.getAuthor(pr).getLogin())) {
            // Assign the PR to all users who provided a review, so that it will be visible who was involved
            Set<GHUser> reviewers = client.getReviews(pr).keySet();
            reviewers.remove(pr.getUser());
            LOG.info("PR #{}: Setting assignees to: {}", pr.getNumber(), reviewers.stream().map(GHPerson::getLogin).collect(Collectors.joining(", ")));
            client.setAssignees(pr, reviewers);
        }
        // Save open PRs so that we can check later if merging this PR caused a conflict in some other PR
        List<GHPullRequest> mergeableOpenPullRequests = client.listOpenPullRequests().stream().filter(pullRequest -> {
            try {
                // Filter out this PR and all that are not mergeable
                return pr.getNumber() != pullRequest.getNumber() && pullRequest.getMergeable() != null && pullRequest.getMergeable();
            } catch (IOException e) {
                LOG.error("PR #{}: Unable to determine mergeable state", pullRequest.getNumber());
            }
            return false;
        }).collect(Collectors.toList());
        LOG.info("PR #{}: Merging", pr.getNumber());
        pr.merge(client.getRepositoryConfiguration().mergeMessage(), null, client.getRepositoryConfiguration().mergeMethod());
        LOG.info("PR #{}: Merged", pr.getNumber());
        if (!mergeableOpenPullRequests.isEmpty()) {
            eventBus.publish(Constants.PR_CHECK_CONFLICT, new BusMessage(client, new ConflictMessage(pr.getNumber(), mergeableOpenPullRequests)));
        }
    } catch (IOException e) {
        LOG.error("PR #{}: Unable to process merge", pr.getNumber(), e);
    }
}
Also used : BaseHandler(com.github.avano.pr.workflow.handler.base.BaseHandler) GHPullRequest(org.kohsuke.github.GHPullRequest) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage) GHPullRequestReviewState(org.kohsuke.github.GHPullRequestReviewState) Collection(java.util.Collection) Set(java.util.Set) IOException(java.io.IOException) ConsumeEvent(io.quarkus.vertx.ConsumeEvent) Collectors(java.util.stream.Collectors) ApprovalStrategy(com.github.avano.pr.workflow.config.ApprovalStrategy) GHPerson(org.kohsuke.github.GHPerson) Constants(com.github.avano.pr.workflow.config.Constants) List(java.util.List) GHUser(org.kohsuke.github.GHUser) GHClient(com.github.avano.pr.workflow.gh.GHClient) Map(java.util.Map) BusMessage(com.github.avano.pr.workflow.message.BusMessage) GHLabel(org.kohsuke.github.GHLabel) Log(com.github.avano.pr.workflow.handler.interceptor.Log) GHPullRequest(org.kohsuke.github.GHPullRequest) GHClient(com.github.avano.pr.workflow.gh.GHClient) BusMessage(com.github.avano.pr.workflow.message.BusMessage) GHPerson(org.kohsuke.github.GHPerson) GHUser(org.kohsuke.github.GHUser) IOException(java.io.IOException) ConflictMessage(com.github.avano.pr.workflow.message.ConflictMessage)

Aggregations

BusMessage (com.github.avano.pr.workflow.message.BusMessage)5 ConflictMessage (com.github.avano.pr.workflow.message.ConflictMessage)5 GHPullRequest (org.kohsuke.github.GHPullRequest)5 ArrayList (java.util.ArrayList)4 LoggedRequest (com.github.tomakehurst.wiremock.verification.LoggedRequest)3 QuarkusTest (io.quarkus.test.junit.QuarkusTest)3 Test (org.junit.jupiter.api.Test)3 GHClient (com.github.avano.pr.workflow.gh.GHClient)2 Log (com.github.avano.pr.workflow.handler.interceptor.Log)2 ConsumeEvent (io.quarkus.vertx.ConsumeEvent)2 IOException (java.io.IOException)2 JSONObject (org.json.JSONObject)2 ApprovalStrategy (com.github.avano.pr.workflow.config.ApprovalStrategy)1 Constants (com.github.avano.pr.workflow.config.Constants)1 BaseHandler (com.github.avano.pr.workflow.handler.base.BaseHandler)1 LabelsMessage (com.github.avano.pr.workflow.message.LabelsMessage)1 Collection (java.util.Collection)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1