支持构建成功自动合并PR

This commit is contained in:
yashin 2018-07-03 18:44:10 +08:00
parent 81c80cefb7
commit 310b8996e5
9 changed files with 8 additions and 184 deletions

View File

@ -8,6 +8,6 @@ import com.gitee.jenkins.gitee.api.model.*;
interface GiteeApiProxy {
void createMergeRequestNote(String owner, String repo, Integer mergeRequestId, String body);
void headCurrentUser();
void acceptMergeRequest(Integer projectId, Integer mergeRequestId, String mergeCommitMessage, boolean shouldRemoveSourceBranch);
void acceptMergeRequest(String owner, String repo, Integer mergeRequestId);
User getCurrentUser();
}

View File

@ -16,11 +16,10 @@ interface GiteeV5ApiProxy extends GiteeApiProxy {
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/projects/{projectId}/merge_requests/{mergeRequestId}/merge")
void acceptMergeRequest(@PathParam("projectId") Integer projectId,
@PathParam("mergeRequestId") Integer mergeRequestId,
@FormParam("merge_commit_message") String mergeCommitMessage,
@FormParam("should_remove_source_branch") boolean shouldRemoveSourceBranch);
@Path("/repos/{ownerPath}/{repoPath}/pulls/{prNumber}/merge")
void acceptMergeRequest(@PathParam("ownerPath") String ownerPath,
@PathParam("repoPath") String repoPath,
@PathParam("prNumber") Integer prNumber);
@POST
@Produces(MediaType.APPLICATION_JSON)

View File

@ -22,11 +22,10 @@ final class ResteasyGiteeClient implements GiteeClient {
return hostUrl;
}
// Gitee v5 don't support commit message and remove source branch
@Override
public void acceptMergeRequest(MergeRequest mr, String mergeCommitMessage, boolean shouldRemoveSourceBranch) {
api.acceptMergeRequest(mr.getProjectId(), mergeRequestIdProvider.apply(mr), mergeCommitMessage, shouldRemoveSourceBranch);
api.acceptMergeRequest(mr.getRepoOwner(), mr.getRepoPath(), mergeRequestIdProvider.apply(mr));
}
@Override
@ -34,7 +33,6 @@ final class ResteasyGiteeClient implements GiteeClient {
api.createMergeRequestNote(mr.getRepoOwner(), mr.getRepoPath(), mergeRequestIdProvider.apply(mr), body);
}
@Override
public User getCurrentUser() {
return api.getCurrentUser();

View File

@ -1,65 +0,0 @@
package com.gitee.jenkins.publisher;
import com.gitee.jenkins.gitee.api.GiteeClient;
import com.gitee.jenkins.gitee.api.model.MergeRequest;
import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import org.kohsuke.stapler.DataBoundConstructor;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.WebApplicationException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Robin Müller
*/
public class GiteeVotePublisher extends MergeRequestNotifier {
private static final Logger LOGGER = Logger.getLogger(GiteeVotePublisher.class.getName());
@DataBoundConstructor
public GiteeVotePublisher() { }
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
@Override
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
return true;
}
@Override
public String getDisplayName() {
return Messages.GiteeVotePublisher_DisplayName();
}
}
@Override
protected void perform(Run<?, ?> build, TaskListener listener, GiteeClient client, MergeRequest mergeRequest) {
try {
client.createMergeRequestNote(mergeRequest, getResultIcon(build.getResult()));
} catch (WebApplicationException | ProcessingException e) {
listener.getLogger().printf("Failed to add vote on Merge Request for project '%s': %s%n", mergeRequest.getProjectId(), e.getMessage());
LOGGER.log(Level.SEVERE, String.format("Failed to add vote on Merge Request for project '%s'", mergeRequest.getProjectId()), e);
}
}
private String getResultIcon(Result result) {
if (result == Result.SUCCESS) {
return ":+1:";
} else {
return ":-1:";
}
}
}

View File

@ -10,7 +10,6 @@ import com.gitee.jenkins.gitee.hook.model.PipelineHook;
import com.gitee.jenkins.gitee.hook.model.PushHook;
import com.gitee.jenkins.publisher.GiteeAcceptMergeRequestPublisher;
import com.gitee.jenkins.publisher.GiteeMessagePublisher;
import com.gitee.jenkins.publisher.GiteeVotePublisher;
import com.gitee.jenkins.trigger.filter.BranchFilter;
import com.gitee.jenkins.trigger.filter.BranchFilterFactory;
import com.gitee.jenkins.trigger.filter.BranchFilterType;
@ -181,9 +180,6 @@ public class GiteePushTrigger extends Trigger<Job<?, ?>> {
if (trigger.addNoteOnMergeRequest) {
project.getPublishersList().add(new GiteeMessagePublisher());
}
if (trigger.addVoteOnMergeRequest) {
project.getPublishersList().add(new GiteeVotePublisher());
}
if (trigger.acceptMergeRequestOnSuccess) {
project.getPublishersList().add(new GiteeAcceptMergeRequestPublisher());
}

View File

@ -73,7 +73,7 @@ class MergeRequestHookTriggerHandlerImpl extends AbstractWebHookTriggerHandler<M
}
}
else {
LOGGER.log(Level.INFO, "request is not allow, hook ----- #" + hook.toString());
LOGGER.log(Level.INFO, "request is not allow, hook state=" + hook.getState() + ", action = " + hook.getAction());
}
} catch (Exception e) {
LOGGER.log(Level.INFO, "request is not allow, hook ----- #" + hook.toString());

View File

@ -1,5 +1,4 @@
GiteeCommitStatusPublisher.DisplayName=Publish build status to Gitee
name.required=Build name required.
GiteeMessagePublisher.DisplayName=Add note with build status on Gitee pull requests
GiteeVotePublisher.DisplayName=Add vote for build status on Gitee pull requests
GiteeAcceptMergeRequestPublisher.DisplayName=Accept Gitee pull request on success

View File

@ -1,5 +1,4 @@
GiteeCommitStatusPublisher.DisplayName=\u53D1\u5E03\u6784\u5EFA\u72B6\u6001\u5230 Gitee
name.required=\u8BF7\u8F93\u5165\u6784\u5EFA\u540D\u79F0\u3002
GiteeMessagePublisher.DisplayName=\u5C06\u6784\u5EFA\u72B6\u6001\u8BC4\u8BBA\u5230 Gitee Pull Request \u4E2D
GiteeVotePublisher.DisplayName=\u5C06\u6784\u5EFA\u7ED3\u679C\u6295\u7968\u5230 Gitee Pull request \u4E2D
GiteeAcceptMergeRequestPublisher.DisplayName=\u5F53\u6784\u5EFA\u6210\u529F\u81EA\u52A8\u5408\u5E76 Gitee \u7684 Pull Request

View File

@ -1,102 +0,0 @@
package com.gitee.jenkins.publisher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.model.StreamBuildListener;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.mockserver.client.server.MockServerClient;
import org.mockserver.junit.MockServerRule;
import org.mockserver.model.HttpRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import static com.gitee.jenkins.publisher.TestUtility.*;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
/**
* @author Nikolay Ustinov
*/
public class GiteeVotePublisherTest {
@ClassRule
public static MockServerRule mockServer = new MockServerRule(new Object());
@ClassRule
public static JenkinsRule jenkins = new JenkinsRule();
private MockServerClient mockServerClient;
private BuildListener listener;
@BeforeClass
public static void setupClass() throws IOException {
setupGiteeConnections(jenkins, mockServer);
}
@Before
public void setup() {
listener = new StreamBuildListener(jenkins.createTaskListener().getLogger(), Charset.defaultCharset());
mockServerClient = new MockServerClient("localhost", mockServer.getPort());
}
@After
public void cleanup() {
mockServerClient.reset();
}
@Test
public void matrixAggregatable() throws InterruptedException, IOException {
verifyMatrixAggregatable(GiteeVotePublisher.class, listener);
}
@Test
public void success_v3() throws IOException, InterruptedException {
performAndVerify(mockSimpleBuild(GITEE_CONNECTION_V3, Result.SUCCESS), "v3", MERGE_REQUEST_ID, ":+1:");
}
@Test
public void success_v4() throws IOException, InterruptedException {
performAndVerify(mockSimpleBuild(GITEE_CONNECTION_V4, Result.SUCCESS), "v4", MERGE_REQUEST_IID, ":+1:");
}
@Test
public void failed_v3() throws IOException, InterruptedException {
performAndVerify(mockSimpleBuild(GITEE_CONNECTION_V3, Result.FAILURE), "v3", MERGE_REQUEST_ID, ":-1:");
}
@Test
public void failed_v4() throws IOException, InterruptedException {
performAndVerify(mockSimpleBuild(GITEE_CONNECTION_V4, Result.FAILURE), "v4", MERGE_REQUEST_IID, ":-1:");
}
private void performAndVerify(AbstractBuild build, String apiLevel, int mergeRequestId, String defaultNote) throws InterruptedException, IOException {
GiteeVotePublisher publisher = preparePublisher(new GiteeVotePublisher(), build);
publisher.perform(build, null, listener);
mockServerClient.verify(prepareSendMessageWithSuccessResponse(build, apiLevel, mergeRequestId, defaultNote));
}
private HttpRequest prepareSendMessageWithSuccessResponse(AbstractBuild build, String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
HttpRequest updateCommitStatus = prepareSendMessageStatus(apiLevel, mergeRequestId, formatNote(build, body));
mockServerClient.when(updateCommitStatus).respond(response().withStatusCode(200));
return updateCommitStatus;
}
private HttpRequest prepareSendMessageStatus(final String apiLevel, int mergeRequestId, String body) throws UnsupportedEncodingException {
return request()
.withPath("/gitee/api/" + apiLevel + "/projects/" + PROJECT_ID + "/merge_requests/" + mergeRequestId + "/notes")
.withMethod("POST")
.withHeader("PRIVATE-TOKEN", "secret")
.withBody("body=" + URLEncoder.encode(body, "UTF-8"));
}
}