diff --git a/pom.xml b/pom.xml index a0580bab25b0792e40de01bde1f2f8d961c52515..692de08d164ae62db8c88169314b2a36ee1fad6b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,20 @@ org.jenkins-ci.plugins plugin - 2.3 + 4.18 + - 1.609.3 - 1.115 - ${jenkins.version} - false + 8 + 2.277.4 + 2.5 + 3.10 + 2.4.0 + 1.18.16 + 3.11 + 2.12.1 + 4.9.0 gitee @@ -27,6 +33,13 @@ + + scm:git:ssh://github.com:jenkinsci/gitee-plugin.git + scm:git:git@github.com:jenkinsci/gitee-plugin.git + https://github.com/jenkinsci/gitee-plugin + HEAD + + Yashin @@ -48,220 +61,147 @@ - - scm:git:ssh://github.com:jenkinsci/gitee-plugin.git - scm:git:git@github.com:jenkinsci/gitee-plugin.git - https://github.com/jenkinsci/gitee-plugin - HEAD - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - jgit-repository - Eclipse JGit Repository - http://download.eclipse.org/jgit/maven - - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - - clean install - ${project.basedir}/target - ${project.build.directory}/classes - ${project.artifactId}-${project.version} - ${project.build.directory}/test-classes - ${project.basedir}/src/main/java - ${project.basedir}/src/main/scripts - ${project.basedir}/src/test/java - - - ${project.basedir}/src/main/resources - - - - - ${project.basedir}/src/test/resources - - - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.4 - - false - - - - - + + + + io.jenkins.tools.bom + bom-2.277.x + 26 + import + pom + + + - - - org.jenkins-ci.plugins - git - 2.4.1 - org.jenkins-ci.plugins - git-client - 1.19.0 - - - org.jenkins-ci.plugins.workflow - workflow-step-api - 1.15 + structs org.jenkins-ci.plugins.workflow workflow-job - 1.15 org.jenkins-ci.plugins credentials - 2.1.0 org.jenkins-ci.plugins plain-credentials - 1.1 - true org.jenkins-ci symbol-annotation - 1.5 - org.eclipse.jgit - org.eclipse.jgit - 3.5.2.201411120430-r + org.jenkins-ci.plugins + matrix-project - org.jenkins-ci.plugins - matrix-project - 1.10 + org.jenkins-ci.plugins + git org.jenkins-ci.plugins - display-url-api - 1.1.1 + git-client - - - org.jboss.spec.javax.ws.rs - jboss-jaxrs-api_2.0_spec - 1.0.0.Final - - - org.jboss.resteasy - resteasy-client - 3.0.16.Final - - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider - 2.9.9 - - - com.fasterxml.jackson.core - jackson-databind - 2.9.9.3 + org.jenkins-ci.plugins.workflow + workflow-cps + test - org.apache.httpcomponents - httpclient - 4.3.1 + org.jenkins-ci.plugins.workflow + workflow-basic-steps + test - - - com.google.guava - guava - 18.0 + org.jenkins-ci.plugins.workflow + workflow-durable-task-step + test - net.karneim - pojobuilder - 3.4.0 - provided + org.jenkins-ci.plugins.workflow + workflow-aggregator + ${workflow-aggregator.version} + test + + + jackson-datatype-json-org + com.fasterxml.jackson.datatype + + - - - junit - junit - 4.12 + org.jenkins-ci.main + maven-plugin + ${jenkins-maven.version} test - org.hamcrest - hamcrest-all - 1.3 + org.jenkins-ci.plugins + envinject + ${jenkins-envinject.version} test + + - org.mockito - mockito-all - 1.9.5 - test + org.projectlombok + lombok + ${lombok.version} + provided + + - org.powermock - powermock-api-mockito - 1.6.1 - test + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + - org.powermock - powermock-module-junit4 - 1.6.1 - test + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + - org.mock-server - mockserver-netty - 3.10.2 - test + com.squareup.okhttp3 + okhttp + ${okhttp.version} - org.bouncycastle - bcmail-jdk15on - - - org.bouncycastle - bcprov-jdk15on - - - org.bouncycastle - bcpkix-jdk15on - - - javax.servlet - javax.servlet-api + org.jetbrains.kotlin + kotlin-stdlib-common - - org.postgresql - postgresql - 9.4.1208 - test - + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + jgit-repository + Eclipse JGit Repository + http://download.eclipse.org/jgit/maven + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + diff --git a/src/main/java/com/gitee/jenkins/GiteeWebHook.java b/src/main/java/com/gitee/jenkins/GiteeWebHook.java new file mode 100644 index 0000000000000000000000000000000000000000..a2ba3dc0a71f0306898226b8bda55bfdfb033373 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/GiteeWebHook.java @@ -0,0 +1,88 @@ +package com.gitee.jenkins; + +import com.gitee.jenkins.entity.WebHook; +import com.gitee.jenkins.entity.WebHookAction; +import com.gitee.jenkins.event.GiteeEventResolver; +import com.gitee.jenkins.handler.GiteeWebHookHandler; +import hudson.Extension; +import hudson.model.UnprotectedRootAction; +import hudson.security.csrf.CrumbExclusion; +import org.kohsuke.stapler.HttpResponses; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.interceptor.RequirePOST; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Receives gitee hook + */ +@Extension +public class GiteeWebHook implements UnprotectedRootAction { + + private static final Logger LOGGER = Logger.getLogger(GiteeWebHook.class.getName()); + + public static final String WEBHOOK_URL = "gitee-project"; + + @Override + public String getIconFileName() { + return null; + } + + @Override + public String getDisplayName() { + return null; + } + + @Override + public String getUrlName() { + return WEBHOOK_URL; + } + + /** + * Receives the webhook call + * + * @param projectName 项目名 + * @param request + * @param response + */ + @RequirePOST + public void getDynamic(String projectName, StaplerRequest request, StaplerResponse response) { + LOGGER.log(Level.INFO, "WebHook called with url: {0}", request.getRequestURIWithQueryString()); + WebHookAction webHookAction = GiteeEventResolver.resolve(projectName, request); + GiteeWebHookHandler.handler(webHookAction); + response(webHookAction.getWebHook()); + } + + public static void response(WebHook webHook) { + throw new HttpResponses.HttpResponseException() { + @Override + public void generateResponse(StaplerRequest staplerRequest, StaplerResponse staplerResponse, Object o) throws IOException, ServletException { + staplerResponse.setContentType("text/plain;charset=UTF-8"); + staplerResponse.getWriter().println(webHook.getWebHookDescription() + " has been accepted."); + } + }; + } + + @Extension + public static class GiteeWebHookCrumbExclusion extends CrumbExclusion { + + @Override + public boolean process(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + String pathInfo = request.getPathInfo(); + if (pathInfo != null && pathInfo.startsWith("/" + WEBHOOK_URL + "/")) { + chain.doFilter(request, response); + return true; + } + return false; + } + + } + +} diff --git a/src/main/java/com/gitee/jenkins/api/GiteeApi.java b/src/main/java/com/gitee/jenkins/api/GiteeApi.java new file mode 100644 index 0000000000000000000000000000000000000000..88101e0fe422a42489c407221cfa2825780c040f --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/GiteeApi.java @@ -0,0 +1,34 @@ +package com.gitee.jenkins.api; + +import com.gitee.jenkins.entity.User; +import com.gitee.jenkins.excetion.GiteeClientRequestException; + +public interface GiteeApi { + + /** + * 合并 PR 请求 + * + * @param owner 使用者 + * @param repo 仓库 + * @param number PR 序号 + */ + void mergerPullRequest(String owner, String repo, Integer number) throws GiteeClientRequestException; + + /** + * 创建 PR 评论 + * + * @param owner 所有者 + * @param repo 仓库 + * @param number PR 序号 + * @param body 评论内容 + */ + void submitPullRequestComments(String owner, String repo, Integer number, String body) throws GiteeClientRequestException; + + /** + * 获取当前用户(返回用户数据) + * + * @return + */ + User getUser() throws GiteeClientRequestException; + +} diff --git a/src/main/java/com/gitee/jenkins/api/client/GiteeClient.java b/src/main/java/com/gitee/jenkins/api/client/GiteeClient.java new file mode 100644 index 0000000000000000000000000000000000000000..4e5e4fccdd72d6961ba88f49d026a7dc53794ddc --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/client/GiteeClient.java @@ -0,0 +1,37 @@ +package com.gitee.jenkins.api.client; + +import com.gitee.jenkins.api.GiteeApi; +import lombok.AllArgsConstructor; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@AllArgsConstructor +@Restricted(NoExternalUse.class) +public abstract class GiteeClient implements GiteeApi { + + /** + * gitee服务器地址 + */ + String hostname; + + /** + * access token + */ + String accessToken; + + /** + * 是否忽略证书错误 + */ + boolean ignoreCertificateErrors; + + /** + * 链接超时时间 + */ + int connectionTimeout; + + /** + * 读取超时时间 + */ + int readTimeout; + +} diff --git a/src/main/java/com/gitee/jenkins/api/client/GiteeV5Client.java b/src/main/java/com/gitee/jenkins/api/client/GiteeV5Client.java new file mode 100644 index 0000000000000000000000000000000000000000..bcdd1e424c00a5d6e58b3f87f48bc6c3ac5a9d1f --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/client/GiteeV5Client.java @@ -0,0 +1,54 @@ +package com.gitee.jenkins.api.client; + +import com.gitee.jenkins.entity.User; +import com.gitee.jenkins.excetion.GiteeClientRequestException; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +import java.util.HashMap; +import java.util.Map; + +@Restricted(NoExternalUse.class) +public class GiteeV5Client extends HttpGiteeClient { + + private static final String ACCESS_TOKEN_PARAM_NAME = "access_token"; + + /** + * /api/v5/repos/{owner}/{repo}/pulls/{number}/merge + */ + private static final String MERGE_PULL_REQUEST_URL = "/api/v5/repos/%s/%s/pulls/%s/merge"; + /** + * /api/v5/repos/{owner}/{repo}/pulls/{number}/comments + */ + private static final String SUBMIT_PULL_REQUEST_COMMENTS_URL = "/api/v5/repos/%s/%s/pulls/%s/comments"; + private static final String GET_USER_URL = "/api/v5/user"; + + public GiteeV5Client(String url, String accessToken, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) { + super(url, accessToken, ignoreCertificateErrors, connectionTimeout, readTimeout); + } + + @Override + public void mergerPullRequest(String owner, String repo, Integer number) throws GiteeClientRequestException { + Map requestParamsMap = getRequestParamsMap(); + putJson(hostname + String.format(MERGE_PULL_REQUEST_URL, owner, repo, number), requestParamsMap); + } + + @Override + public void submitPullRequestComments(String owner, String repo, Integer number, String body) throws GiteeClientRequestException { + Map requestParamsMap = getRequestParamsMap(); + requestParamsMap.put("body", body); + postJson(hostname + String.format(SUBMIT_PULL_REQUEST_COMMENTS_URL, owner, repo, number), requestParamsMap); + } + + @Override + public User getUser() throws GiteeClientRequestException { + return getForEntity(hostname + GET_USER_URL, getRequestParamsMap(), User.class); + } + + private Map getRequestParamsMap() { + Map map = new HashMap<>(4); + map.put(ACCESS_TOKEN_PARAM_NAME, accessToken); + return map; + } + +} diff --git a/src/main/java/com/gitee/jenkins/api/client/HttpGiteeClient.java b/src/main/java/com/gitee/jenkins/api/client/HttpGiteeClient.java new file mode 100644 index 0000000000000000000000000000000000000000..d7e2fd65a137535a207386d10e686fc7b3282b3f --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/client/HttpGiteeClient.java @@ -0,0 +1,221 @@ +package com.gitee.jenkins.api.client; + +import com.gitee.jenkins.excetion.GiteeClientRequestException; +import com.gitee.jenkins.util.JsonUtil; +import okhttp3.*; +import okhttp3.Request.Builder; +import org.jetbrains.annotations.NotNull; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Restricted(NoExternalUse.class) +public abstract class HttpGiteeClient extends GiteeClient { + + private static final Logger LOGGER = Logger.getLogger(HttpGiteeClient.class.getName()); + + public static final MediaType APPLICATION_JSON_UTF8 = MediaType.get("application/json; charset=utf-8"); + + private static final String CONNECTION_TIMEOUT_HEADER = "connection_timeout"; + private static final String READ_TIMEOUT_HEADER = "read_timeout"; + + /** + * 正常http客户端 + */ + private static final OkHttpClient SAFE_HTTP_CLIENT; + + /** + * 忽略证书安全的http客户端 + */ + private static final OkHttpClient UNSAFE_HTTP_CLIENT; + + static { + DynamicTimeoutsInterceptor dynamicTimeoutsInterceptor = new DynamicTimeoutsInterceptor(); + // 创建正常http客户端 + SAFE_HTTP_CLIENT = new OkHttpClient.Builder() + .addInterceptor(dynamicTimeoutsInterceptor) + .build(); + // 创建忽略证书安全得http客户端 + UNSAFE_HTTP_CLIENT = configureToIgnoreCertificate(new OkHttpClient.Builder()) + .addInterceptor(dynamicTimeoutsInterceptor) + .build(); + } + + protected HttpGiteeClient(String hostname, + String accessToken, + boolean ignoreCertificateErrors, + int connectionTimeout, + int readTimeout) { + super(hostname, accessToken, ignoreCertificateErrors, connectionTimeout, readTimeout); + } + + /** + * get请求,解析结果 + * + * @param url url + * @param params 参数 + * @param clazz 结果解析类型 + * @param 结果类泛型 + * @return 请求解析结果 + * @throws Exception 请求失败 + */ + T getForEntity(String url, Map params, Class clazz) throws GiteeClientRequestException { + try (Response response = reqGet(url, params)) { + return JsonUtil.string2Obj(response.body().string(), clazz); + } catch (IOException e) { + throw new GiteeClientRequestException(e); + } + } + + /** + * post json请求,不解析结果 + * + * @param url url + * @param params 参数 + * @throws Exception 请求失败 + */ + void postJson(String url, Map params) throws GiteeClientRequestException { + try (Response response = reqPostJson(url, params)) { + } + } + + /** + * put json请求,不解析结果 + * + * @param url url + * @param params 参数 + * @throws Exception 请求失败 + */ + void putJson(String url, Map params) throws GiteeClientRequestException { + try (Response response = reqPutJson(url, params)) { + } + } + + private Response reqGet(String url, Map params) throws GiteeClientRequestException { + Request request = getRequestBuilder(url, params).build(); + return getResponse(url, request); + } + + private Response reqPostJson(String url, Map params) throws GiteeClientRequestException { + Request request = getRequestBuilder(url) + .post(RequestBody.create(JsonUtil.obj2String(params), APPLICATION_JSON_UTF8)) + .build(); + return getResponse(url, request); + } + + private Response reqPutJson(String url, Map params) throws GiteeClientRequestException { + Request request = getRequestBuilder(url) + .put(RequestBody.create(JsonUtil.obj2String(params), APPLICATION_JSON_UTF8)) + .build(); + return getResponse(url, request); + } + + private Builder getRequestBuilder(String url) { + return getRequestBuilder(url, null); + } + + private Builder getRequestBuilder(String url, Map params) { + HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(url).newBuilder(); + if (Objects.nonNull(params)) { + for (Map.Entry entry : params.entrySet()) { + httpUrlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); + } + } + + return new Builder() + .url(httpUrlBuilder.build()) + .header(CONNECTION_TIMEOUT_HEADER, String.valueOf(connectionTimeout)) + .header(READ_TIMEOUT_HEADER, String.valueOf(readTimeout)); + } + + private Response getResponse(String url, Request request) throws GiteeClientRequestException { + try { + Response response = getHttpClient().newCall(request).execute(); + if (!response.isSuccessful()) { + throw new GiteeClientRequestException(String.format("request %s error: %s", url, response.body().string())); + } + return response; + } catch (IOException e) { + throw new GiteeClientRequestException(e); + } + } + + private OkHttpClient getHttpClient() { + return ignoreCertificateErrors ? UNSAFE_HTTP_CLIENT : SAFE_HTTP_CLIENT; + } + + /** + * 忽略https错误 + * + * @param builder + * @return + */ + private static OkHttpClient.Builder configureToIgnoreCertificate(OkHttpClient.Builder builder) { + try { + // Create a trust manager that does not validate certificate chains + final TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + }; + + // Install the all-trusting trust manager + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + // Create an ssl socket factory with our all-trusting manager + final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + + builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]) + .hostnameVerifier((hostname, session) -> true); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Exception while configuring IgnoreSslCertificate" + e, e); + } + return builder; + } + + /** + * 动态配置超时时间拦截器 + */ + private static class DynamicTimeoutsInterceptor implements Interceptor { + + @NotNull + @Override + public Response intercept(@NotNull Chain chain) throws IOException { + Request request = chain.request(); + int connectionTimeout = Integer.parseInt(request.header(CONNECTION_TIMEOUT_HEADER)); + int readTimeout = Integer.parseInt(request.header(READ_TIMEOUT_HEADER)); + request = request.newBuilder() + .removeHeader(CONNECTION_TIMEOUT_HEADER) + .removeHeader(READ_TIMEOUT_HEADER) + .build(); + + return chain.withConnectTimeout(connectionTimeout, TimeUnit.SECONDS) + .withReadTimeout(readTimeout, TimeUnit.SECONDS) + .proceed(request); + } + + } + +} diff --git a/src/main/java/com/gitee/jenkins/api/client/factory/GiteeClientFactory.java b/src/main/java/com/gitee/jenkins/api/client/factory/GiteeClientFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a430ece57f7f2d877324f0daa8b15aa02fea0d30 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/client/factory/GiteeClientFactory.java @@ -0,0 +1,25 @@ +package com.gitee.jenkins.api.client.factory; + +import com.gitee.jenkins.api.client.GiteeClient; +import com.gitee.jenkins.enums.GiteeClientType; +import hudson.ExtensionList; +import hudson.ExtensionPoint; + +public interface GiteeClientFactory extends ExtensionPoint { + + GiteeClient getGiteeClient(String hostname, + String accessToken, + boolean ignoreCertificateErrors, + int connectionTimeout, + int readTimeout); + + GiteeClientType getGiteeClientType(); + + static GiteeClientFactory getGiteeClientFactory(GiteeClientType giteeClientType) { + return ExtensionList.lookup(GiteeClientFactory.class).stream() + .filter(giteeClientFactory -> giteeClientFactory.getGiteeClientType() == giteeClientType) + .findFirst() + .orElse(ExtensionList.lookup(GiteeClientFactory.class).get(GiteeV5ClientFactory.class)); + } + +} diff --git a/src/main/java/com/gitee/jenkins/api/client/factory/GiteeV5ClientFactory.java b/src/main/java/com/gitee/jenkins/api/client/factory/GiteeV5ClientFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..3b1ee4a0f855a5d0599bcfb3142765d45c3207f3 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/api/client/factory/GiteeV5ClientFactory.java @@ -0,0 +1,24 @@ +package com.gitee.jenkins.api.client.factory; + +import com.gitee.jenkins.api.client.GiteeClient; +import com.gitee.jenkins.api.client.GiteeV5Client; +import com.gitee.jenkins.enums.GiteeClientType; +import hudson.Extension; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Extension +@Restricted(NoExternalUse.class) +public class GiteeV5ClientFactory implements GiteeClientFactory { + + @Override + public GiteeClient getGiteeClient(String hostname, String accessToken, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) { + return new GiteeV5Client(hostname, accessToken, ignoreCertificateErrors, connectionTimeout, readTimeout); + } + + @Override + public GiteeClientType getGiteeClientType() { + return GiteeClientType.V5; + } + +} diff --git a/src/main/java/com/gitee/jenkins/cause/CauseData.java b/src/main/java/com/gitee/jenkins/cause/CauseData.java deleted file mode 100644 index 7931db59c3177aee53707096de1ccb5e63f39231..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/cause/CauseData.java +++ /dev/null @@ -1,603 +0,0 @@ -package com.gitee.jenkins.cause; - -import com.gitee.jenkins.gitee.api.model.PullRequest; -import hudson.markup.EscapedMarkupFormatter; -import jenkins.model.Jenkins; -import net.karneim.pojobuilder.GeneratePojoBuilder; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; - -import java.util.*; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * @author Robin Müller - */ -public final class CauseData { - private final ActionType actionType; - private final Integer sourceProjectId; - private final Integer targetProjectId; - private final String branch; - private final String pathWithNamespace; - private final String sourceBranch; - private final String userName; - private final String userEmail; - private final String sourceRepoHomepage; - private final String sourceRepoName; - private final String sourceNamespace; - private final String sourceRepoUrl; - private final String sourceRepoSshUrl; - private final String sourceRepoHttpUrl; - private final String pullRequestTitle; - private final String pullRequestDescription; - private final Integer pullRequestId; - private final Integer pullRequestIid; - private final String pullRequestState; - private final String mergedByUser; - private final String pullRequestAssignee; - private final Integer pullRequestTargetProjectId; - private final String targetBranch; - private final String targetRepoName; - private final String targetNamespace; - private final String targetRepoSshUrl; - private final String targetRepoHttpUrl; - private final String triggeredByUser; - private final String before; - private final String after; - private final String lastCommit; - private final String targetProjectUrl; - private final String triggerPhrase; - private final String ref; - private final String beforeSha; - private final String isTag; - private final String sha; - private final String status; - private final String stages; - private final String createdAt; - private final String finishedAt; - private final String buildDuration; - private final String jsonBody; - private final String noteBody; - private final boolean created; - private final boolean deleted; - - @GeneratePojoBuilder(withFactoryMethod = "*") - CauseData(ActionType actionType, Integer sourceProjectId, Integer targetProjectId, String branch, String sourceBranch, String userName, - String userEmail, String sourceRepoHomepage, String sourceRepoName, String sourceNamespace, String sourceRepoUrl, - String sourceRepoSshUrl, String sourceRepoHttpUrl, String pullRequestTitle, String pullRequestDescription, Integer pullRequestId, - Integer pullRequestIid, Integer pullRequestTargetProjectId, String targetBranch, String targetRepoName, String targetNamespace, - String targetRepoSshUrl, String targetRepoHttpUrl, String triggeredByUser, String before, String after, String lastCommit, - String targetProjectUrl, String triggerPhrase, String pullRequestState, String mergedByUser, String pullRequestAssignee, - String ref, String isTag, String sha, String beforeSha, String status, String stages, String createdAt, String finishedAt, - String buildDuration, String pathWithNamespace, boolean created, boolean deleted, String jsonBody, String noteBody) { - this.actionType = checkNotNull(actionType, "actionType must not be null."); - this.sourceProjectId = checkNotNull(sourceProjectId, "sourceProjectId must not be null."); - this.targetProjectId = checkNotNull(targetProjectId, "targetProjectId must not be null."); - this.branch = checkNotNull(branch, "branch must not be null."); - this.sourceBranch = checkNotNull(sourceBranch, "sourceBranch must not be null."); - this.userName = checkNotNull(userName, "userName must not be null."); - this.userEmail = userEmail == null ? "" : userEmail; - this.sourceRepoHomepage = sourceRepoHomepage == null ? "" : sourceRepoHomepage; - this.sourceRepoName = checkNotNull(sourceRepoName, "sourceRepoName must not be null."); - this.sourceNamespace = checkNotNull(sourceNamespace, "sourceNamespace must not be null."); - this.sourceRepoUrl = sourceRepoUrl == null ? sourceRepoSshUrl : sourceRepoUrl; - this.sourceRepoSshUrl = checkNotNull(sourceRepoSshUrl, "sourceRepoSshUrl must not be null."); - this.sourceRepoHttpUrl = checkNotNull(sourceRepoHttpUrl, "sourceRepoHttpUrl must not be null."); - this.pullRequestTitle = checkNotNull(pullRequestTitle, "pullRequestTitle must not be null."); - this.pullRequestDescription = pullRequestDescription == null ? "" : pullRequestDescription; - this.pullRequestId = pullRequestId; - this.pullRequestIid = pullRequestIid; - this.pullRequestState = pullRequestState == null ? "" : pullRequestState; - this.mergedByUser = mergedByUser == null ? "" : mergedByUser; - this.pullRequestAssignee = pullRequestAssignee == null ? "" : pullRequestAssignee; - this.pullRequestTargetProjectId = pullRequestTargetProjectId; - this.targetBranch = checkNotNull(targetBranch, "targetBranch must not be null."); - this.targetRepoName = checkNotNull(targetRepoName, "targetRepoName must not be null."); - this.targetNamespace = checkNotNull(targetNamespace, "targetNamespace must not be null."); - this.targetRepoSshUrl = checkNotNull(targetRepoSshUrl, "targetRepoSshUrl must not be null."); - this.targetRepoHttpUrl = checkNotNull(targetRepoHttpUrl, "targetRepoHttpUrl must not be null."); - this.triggeredByUser = checkNotNull(triggeredByUser, "triggeredByUser must not be null."); - this.before = before == null ? "" : before; - this.after = after == null ? "" : after; -// this.lastCommit = checkNotNull(lastCommit, "lastCommit must not be null"); - // 直接checkout到分支,而非commit sha,暂时不需要确保lastCommit 非空 - this.lastCommit = lastCommit; - this.targetProjectUrl = targetProjectUrl; - this.triggerPhrase = triggerPhrase; - this.ref = ref; - this.isTag = isTag; - this.sha = sha; - this.beforeSha = beforeSha; - this.status = status; - this.stages = stages; - this.createdAt = createdAt; - this.finishedAt = finishedAt; - this.buildDuration = buildDuration; - this.pathWithNamespace = pathWithNamespace; - this.created = created; - this.deleted = deleted; - this.jsonBody = jsonBody; - this.noteBody = noteBody; - } - - public Map getBuildVariables() { - MapWrapper variables = new MapWrapper<>(new HashMap()); - variables.put("giteeBranch", branch); - variables.put("giteeSourceBranch", sourceBranch); - variables.put("giteeActionType", actionType.name()); - variables.put("giteeUserName", userName); - variables.put("giteeUserEmail", userEmail); - variables.put("giteeSourceRepoHomepage", sourceRepoHomepage); - variables.put("giteeSourceRepoName", sourceRepoName); - variables.put("giteeSourceNamespace", sourceNamespace); - variables.put("giteeSourceRepoURL", sourceRepoUrl); - variables.put("giteeSourceRepoSshUrl", sourceRepoSshUrl); - variables.put("giteeSourceRepoHttpUrl", sourceRepoHttpUrl); - variables.put("giteePullRequestTitle", pullRequestTitle); - variables.put("giteePullRequestDescription", pullRequestDescription); - variables.put("giteePullRequestId", pullRequestId == null ? "" : pullRequestId.toString()); - variables.put("giteePullRequestIid", pullRequestIid == null ? "" : pullRequestIid.toString()); - variables.put("giteePullRequestTargetProjectId", pullRequestTargetProjectId == null ? "" : pullRequestTargetProjectId.toString()); - variables.put("giteePullRequestLastCommit", lastCommit); - variables.put("giteePushCreated", created ? "true" : "false"); - variables.put("giteePushDeleted", deleted ? "true" : "false"); - variables.putIfNotNull("giteePullRequestState", pullRequestState); - variables.putIfNotNull("giteeMergedByUser", mergedByUser); - variables.putIfNotNull("giteePullRequestAssignee", pullRequestAssignee); - variables.put("giteeTargetBranch", targetBranch); - variables.put("giteeTargetRepoName", targetRepoName); - variables.put("giteeTargetNamespace", targetNamespace); - variables.put("giteeTargetRepoSshUrl", targetRepoSshUrl); - variables.put("giteeTargetRepoHttpUrl", targetRepoHttpUrl); - variables.put("giteeBefore", before); - variables.put("giteeAfter", after); - variables.put("giteeBeforeCommitSha", before); - variables.put("giteeAfterCommitSha", after); - variables.put("giteeRef", ref); - variables.put("ref", ref); - variables.put("beforeSha", beforeSha); - variables.put("isTag", isTag); - variables.put("sha", sha); - variables.put("status", status); - variables.put("stages", stages); - variables.put("createdAt", createdAt); - variables.put("finishedAt", finishedAt); - variables.put("duration", buildDuration); - variables.put("jsonBody", jsonBody); - variables.put("noteBody", noteBody); - variables.putIfNotNull("giteeTriggerPhrase", triggerPhrase); - return variables; - } - - public Integer getSourceProjectId() { - return sourceProjectId; - } - - public Integer getTargetProjectId() { - return targetProjectId; - } - - public String getBranch() { - return branch; - } - - public String getSourceBranch() { - return sourceBranch; - } - - public ActionType getActionType() { - return actionType; - } - - public String getUserName() { - return userName; - } - - public String getUserEmail() { - return userEmail; - } - - public String getSourceRepoHomepage() { - return sourceRepoHomepage; - } - - public String getSourceRepoName() { - return sourceRepoName; - } - - public String getSourceNamespace() { - return sourceNamespace; - } - - public String getSourceRepoUrl() { - return sourceRepoUrl; - } - - public String getSourceRepoSshUrl() { - return sourceRepoSshUrl; - } - - public String getSourceRepoHttpUrl() { - return sourceRepoHttpUrl; - } - - public String getPullRequestTitle() { - return pullRequestTitle; - } - - public String getPullRequestDescription() { - return pullRequestDescription; - } - - public String getPathWithNamespace() { return pathWithNamespace; } - - public Integer getPullRequestId() { - return pullRequestId; - } - - public Integer getPullRequestIid() { - return pullRequestIid; - } - - public Integer getPullRequestTargetProjectId() { - return pullRequestTargetProjectId; - } - - public String getTargetBranch() { - return targetBranch; - } - - public String getTargetRepoName() { - return targetRepoName; - } - - public String getTargetNamespace() { - return targetNamespace; - } - - public String getTargetRepoSshUrl() { - return targetRepoSshUrl; - } - - public String getTargetRepoHttpUrl() { - return targetRepoHttpUrl; - } - - public String getTriggeredByUser() { - return triggeredByUser; - } - - public String getBefore() { - return before; - } - - public String getAfter() { - return after; - } - - public String getLastCommit() { - return lastCommit; - } - - public String getTargetProjectUrl() { - return targetProjectUrl; - } - - public String getRef() { return ref; } - - public String getIsTag() { return isTag; } - - public String getSha() { return sha; } - - public String getBeforeSha() {return beforeSha; } - - public String getStatus() { return status; } - - public String getStages() { return stages; } - - public String getCreatedAt() { return createdAt; } - - public String getFinishedAt() { return finishedAt; } - - public String getBuildDuration() { return buildDuration; } - - public String getJsonBody() { return jsonBody; } - - public String getNoteBody() { return noteBody; } - - - String getShortDescription() { - return actionType.getShortDescription(this); - } - - public String getPullRequestState() { - return pullRequestState; - } - - public String getMergedByUser() { - return mergedByUser; - } - - public String getPullRequestAssignee() { - return pullRequestAssignee; - } - - - public boolean getCreated() { - return created; - } - - public boolean getDeleted() { - return deleted; - } - - public PullRequest getPullRequest() { - if (pullRequestId == null) { - return null; - } - - return new PullRequest(pullRequestId, pullRequestIid, sourceBranch, targetBranch, pullRequestTitle, - sourceProjectId, targetProjectId, pullRequestDescription, pullRequestState, pathWithNamespace); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CauseData causeData = (CauseData) o; - return new EqualsBuilder() - .append(actionType, causeData.actionType) - .append(sourceProjectId, causeData.sourceProjectId) - .append(targetProjectId, causeData.targetProjectId) - .append(branch, causeData.branch) - .append(sourceBranch, causeData.sourceBranch) - .append(userName, causeData.userName) - .append(userEmail, causeData.userEmail) - .append(sourceRepoHomepage, causeData.sourceRepoHomepage) - .append(sourceRepoName, causeData.sourceRepoName) - .append(sourceNamespace, causeData.sourceNamespace) - .append(sourceRepoUrl, causeData.sourceRepoUrl) - .append(sourceRepoSshUrl, causeData.sourceRepoSshUrl) - .append(sourceRepoHttpUrl, causeData.sourceRepoHttpUrl) - .append(pullRequestTitle, causeData.pullRequestTitle) - .append(pullRequestDescription, causeData.pullRequestDescription) - .append(pullRequestId, causeData.pullRequestId) - .append(pullRequestIid, causeData.pullRequestIid) - .append(pullRequestState, causeData.pullRequestState) - .append(mergedByUser, causeData.mergedByUser) - .append(pullRequestAssignee, causeData.pullRequestAssignee) - .append(pullRequestTargetProjectId, causeData.pullRequestTargetProjectId) - .append(targetBranch, causeData.targetBranch) - .append(targetRepoName, causeData.targetRepoName) - .append(targetNamespace, causeData.targetNamespace) - .append(targetRepoSshUrl, causeData.targetRepoSshUrl) - .append(targetRepoHttpUrl, causeData.targetRepoHttpUrl) - .append(triggeredByUser, causeData.triggeredByUser) - .append(before, causeData.before) - .append(after, causeData.after) - .append(lastCommit, causeData.lastCommit) - .append(targetProjectUrl, causeData.targetProjectUrl) - .append(ref, causeData.getRef()) - .append(isTag, causeData.getIsTag()) - .append(sha, causeData.getSha()) - .append(beforeSha, causeData.getBeforeSha()) - .append(status, causeData.getStatus()) - .append(stages, causeData.getStages()) - .append(createdAt, causeData.getCreatedAt()) - .append(finishedAt, causeData.getFinishedAt()) - .append(buildDuration, causeData.getBuildDuration()) - .append(pathWithNamespace, causeData.getPathWithNamespace()) - .append(created, causeData.getCreated()) - .append(deleted, causeData.getDeleted()) - .append(jsonBody, causeData.getJsonBody()) - .append(noteBody, causeData.getNoteBody()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(actionType) - .append(sourceProjectId) - .append(targetProjectId) - .append(branch) - .append(sourceBranch) - .append(userName) - .append(userEmail) - .append(sourceRepoHomepage) - .append(sourceRepoName) - .append(sourceNamespace) - .append(sourceRepoUrl) - .append(sourceRepoSshUrl) - .append(sourceRepoHttpUrl) - .append(pullRequestTitle) - .append(pullRequestDescription) - .append(pullRequestId) - .append(pullRequestIid) - .append(pullRequestState) - .append(mergedByUser) - .append(pullRequestAssignee) - .append(pullRequestTargetProjectId) - .append(targetBranch) - .append(targetRepoName) - .append(targetNamespace) - .append(targetRepoSshUrl) - .append(targetRepoHttpUrl) - .append(triggeredByUser) - .append(before) - .append(after) - .append(lastCommit) - .append(targetProjectUrl) - .append(ref) - .append(isTag) - .append(sha) - .append(beforeSha) - .append(status) - .append(stages) - .append(createdAt) - .append(finishedAt) - .append(buildDuration) - .append(pathWithNamespace) - .append(created) - .append(deleted) - .append(jsonBody) - .append(noteBody) - .toHashCode(); - } - - @Override - public String toString() { - return new ToStringBuilder(this) - .append("actionType", actionType) - .append("sourceProjectId", sourceProjectId) - .append("targetProjectId", targetProjectId) - .append("branch", branch) - .append("sourceBranch", sourceBranch) - .append("userName", userName) - .append("userEmail", userEmail) - .append("sourceRepoHomepage", sourceRepoHomepage) - .append("sourceRepoName", sourceRepoName) - .append("sourceNamespace", sourceNamespace) - .append("sourceRepoUrl", sourceRepoUrl) - .append("sourceRepoSshUrl", sourceRepoSshUrl) - .append("sourceRepoHttpUrl", sourceRepoHttpUrl) - .append("pullRequestTitle", pullRequestTitle) - .append("pullRequestDescription", pullRequestDescription) - .append("pullRequestId", pullRequestId) - .append("pullRequestIid", pullRequestIid) - .append("pullRequestState", pullRequestState) - .append("mergedByUser", mergedByUser) - .append("pullRequestAssignee", pullRequestAssignee) - .append("pullRequestTargetProjectId", pullRequestTargetProjectId) - .append("targetBranch", targetBranch) - .append("targetRepoName", targetRepoName) - .append("targetNamespace", targetNamespace) - .append("targetRepoSshUrl", targetRepoSshUrl) - .append("targetRepoHttpUrl", targetRepoHttpUrl) - .append("triggeredByUser", triggeredByUser) - .append("before", before) - .append("after", after) - .append("lastCommit", lastCommit) - .append("targetProjectUrl", targetProjectUrl) - .append("ref", ref) - .append("isTag", isTag) - .append("sha", sha) - .append("beforeSha", beforeSha) - .append("status", status) - .append("stages", stages) - .append("createdAt", createdAt) - .append("finishedAt", finishedAt) - .append("duration", buildDuration) - .append("pathWithNamespace", pathWithNamespace) - .append("created", created) - .append("deleted", deleted) - .append("jsonBody", jsonBody) - .append("noteBody", noteBody) - .toString(); - } - - public enum ActionType { - PUSH { - @Override - String getShortDescription(CauseData data) { - return getShortDescriptionPush(data); - } - }, TAG_PUSH { - @Override - String getShortDescription(CauseData data) { - return getShortDescriptionPush(data); - } - }, MERGE { - @Override - String getShortDescription(CauseData data) { - String forkNamespace = StringUtils.equals(data.getSourceNamespace(), data.getTargetBranch()) ? "" : data.getSourceNamespace() + "/"; - if (Jenkins.getActiveInstance().getMarkupFormatter() instanceof EscapedMarkupFormatter || data.getTargetProjectUrl() == null) { - return Messages.GiteeWebHookCause_ShortDescription_PullRequestHook_plain(String.valueOf(data.getPullRequestIid()), - forkNamespace + data.getSourceBranch(), - data.getTargetBranch()); - } else { - return Messages.GiteeWebHookCause_ShortDescription_PullRequestHook_html(String.valueOf(data.getPullRequestIid()), - forkNamespace + data.getSourceBranch(), - data.getTargetBranch(), - data.getTargetProjectUrl()); - } - } - }, NOTE { - @Override - String getShortDescription(CauseData data) { - String triggeredBy = data.getTriggeredByUser(); - String forkNamespace = StringUtils.equals(data.getSourceNamespace(), data.getTargetBranch()) ? "" : data.getSourceNamespace() + "/"; - if (Jenkins.getActiveInstance().getMarkupFormatter() instanceof EscapedMarkupFormatter || data.getTargetProjectUrl() == null) { - return Messages.GiteeWebHookCause_ShortDescription_NoteHook_plain(triggeredBy, - String.valueOf(data.getPullRequestIid()), - forkNamespace + data.getSourceBranch(), - data.getTargetBranch()); - } else { - return Messages.GiteeWebHookCause_ShortDescription_NoteHook_html(triggeredBy, - String.valueOf(data.getPullRequestIid()), - forkNamespace + data.getSourceBranch(), - data.getTargetBranch(), - data.getTargetProjectUrl()); - } - } - }, COMMIT_COMMENT { - @Override - String getShortDescription(CauseData data) { - return Messages.GiteeWebHookCause_ShortDescription_Commit_comment(data.getTriggeredByUser()); - } - }, PIPELINE { - @Override - String getShortDescription(CauseData data) { - String getStatus = data.getStatus(); - if (getStatus == null) { - return Messages.GiteeWebHookCause_ShortDescription_PipelineHook_noStatus(); - } else { - return Messages.GiteeWebHookCause_ShortDescription_PipelineHook(getStatus); - } - } - }; - - private static String getShortDescriptionPush(CauseData data) { - String pushedBy = data.getTriggeredByUser(); - if (pushedBy == null) { - return Messages.GiteeWebHookCause_ShortDescription_PushHook_noUser(); - } else { - return Messages.GiteeWebHookCause_ShortDescription_PushHook(pushedBy); - } - } - - abstract String getShortDescription(CauseData data); - } - - private static class MapWrapper extends AbstractMap { - - private final Map map; - - MapWrapper(Map map) { - this.map = map; - } - - @Override - public V put(K key, V value) { - return map.put(key, value); - } - - @Override - public Set> entrySet() { - return map.entrySet(); - } - - void putIfNotNull(K key, V value) { - if (value != null) { - map.put(key, value); - } - } - } -} diff --git a/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCause.java b/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCause.java index 0bb8a9c6544f5fe10e4b1e8fd3966374e6109100..d05cc8752372763a9646f50acd261b68e37cf0ab 100644 --- a/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCause.java +++ b/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCause.java @@ -1,23 +1,20 @@ package com.gitee.jenkins.cause; +import com.google.common.base.Preconditions; import hudson.triggers.SCMTrigger; +import lombok.EqualsAndHashCode; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * @author Robin Müller - * @author Yashin - */ +@EqualsAndHashCode public class GiteeWebHookCause extends SCMTrigger.SCMTriggerCause { - private final CauseData data; + private final GiteeWebHookCauseData data; - public GiteeWebHookCause(CauseData data) { + public GiteeWebHookCause(GiteeWebHookCauseData giteeWebHookCauseData) { super(""); - this.data = checkNotNull(data, "data must not be null"); + this.data = Preconditions.checkNotNull(giteeWebHookCauseData, "data must not be null"); } - public CauseData getData() { + public GiteeWebHookCauseData getData() { return data; } @@ -25,4 +22,5 @@ public class GiteeWebHookCause extends SCMTrigger.SCMTriggerCause { public String getShortDescription() { return data.getShortDescription(); } + } diff --git a/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCauseData.java b/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCauseData.java new file mode 100644 index 0000000000000000000000000000000000000000..c197a7eed75f9c609c2b88b42c0b70d82636cbb1 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/cause/GiteeWebHookCauseData.java @@ -0,0 +1,210 @@ +package com.gitee.jenkins.cause; + +import com.gitee.jenkins.enums.WebHookType; +import com.google.common.base.Preconditions; +import lombok.Builder; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Data +public class GiteeWebHookCauseData { + + private WebHookType webHookType; + + private String userName; + + private String userEmail; + + private Integer sourceProjectId; + + private Integer targetProjectId; + + private String pathWithNamespace; + + private String branch; + + private String sourceBranch; + + private String sourceRepoHomepage; + + private String sourceRepoName; + + private String sourceNamespace; + + private String sourceRepoUrl; + + private String sourceRepoSshUrl; + + private String sourceRepoHttpUrl; + + private String targetBranch; + + private String targetRepoName; + + private String targetNamespace; + + private String targetProjectUrl; + + private String targetRepoSshUrl; + + private String targetRepoHttpUrl; + + private String pullRequestTitle; + + private String pullRequestDescription; + + private Integer pullRequestId; + + private Integer pullRequestIid; + + private String pullRequestState; + + private String mergedByUser; + + private String pullRequestAssignee; + + private Integer pullRequestTargetProjectId; + + private String before; + + private String after; + + private String lastCommit; + + private final String ref; + + private final String beforeSha; + + private final String sha; + + private final String isTag; + + private boolean created; + + private boolean deleted; + + private String status; + + private String stages; + + private String createdAt; + + private String finishedAt; + + private String buildDuration; + + private String jsonBody; + + private String noteBody; + + private String triggerPhrase; + + private String triggeredByUser; + + @Builder + private GiteeWebHookCauseData(WebHookType webHookType, String userName, String userEmail, Integer sourceProjectId, Integer targetProjectId, String pathWithNamespace, String branch, String sourceBranch, String sourceRepoHomepage, String sourceRepoName, String sourceNamespace, String sourceRepoUrl, String sourceRepoSshUrl, String sourceRepoHttpUrl, String targetBranch, String targetRepoName, String targetNamespace, String targetProjectUrl, String targetRepoSshUrl, String targetRepoHttpUrl, String pullRequestTitle, String pullRequestDescription, Integer pullRequestId, Integer pullRequestIid, String pullRequestState, String mergedByUser, String pullRequestAssignee, Integer pullRequestTargetProjectId, String before, String after, String lastCommit, String ref, String beforeSha, String sha, String isTag, boolean created, boolean deleted, String status, String stages, String createdAt, String finishedAt, String buildDuration, String jsonBody, String noteBody, String triggerPhrase, String triggeredByUser) { + this.webHookType = Preconditions.checkNotNull(webHookType, "actionType must not be null."); + this.userName = Preconditions.checkNotNull(userName, "userName must not be null."); + this.userEmail = Optional.ofNullable(userEmail).orElse(""); + this.sourceProjectId = Preconditions.checkNotNull(sourceProjectId, "sourceProjectId must not be null."); + this.targetProjectId = Preconditions.checkNotNull(targetProjectId, "targetProjectId must not be null."); + this.pathWithNamespace = pathWithNamespace; + this.branch = Preconditions.checkNotNull(branch, "branch must not be null."); + this.sourceBranch = Preconditions.checkNotNull(sourceBranch, "sourceBranch must not be null."); + this.sourceRepoHomepage = Optional.ofNullable(sourceRepoHomepage).orElse(""); + this.sourceRepoName = Preconditions.checkNotNull(sourceRepoName, "sourceRepoName must not be null."); + this.sourceNamespace = Preconditions.checkNotNull(sourceNamespace, "sourceNamespace must not be null."); + this.sourceRepoUrl = Optional.ofNullable(sourceRepoUrl).orElse(sourceRepoSshUrl); + this.sourceRepoSshUrl = Preconditions.checkNotNull(sourceRepoSshUrl, "sourceRepoSshUrl must not be null."); + this.sourceRepoHttpUrl = Preconditions.checkNotNull(sourceRepoHttpUrl, "sourceRepoHttpUrl must not be null."); + this.targetBranch = Preconditions.checkNotNull(targetBranch, "targetBranch must not be null."); + this.targetRepoName = Preconditions.checkNotNull(targetRepoName, "targetRepoName must not be null."); + this.targetNamespace = Preconditions.checkNotNull(targetNamespace, "targetNamespace must not be null."); + this.targetProjectUrl = targetProjectUrl; + this.targetRepoSshUrl = Preconditions.checkNotNull(targetRepoSshUrl, "targetRepoSshUrl must not be null."); + this.targetRepoHttpUrl = Preconditions.checkNotNull(targetRepoHttpUrl, "targetRepoHttpUrl must not be null."); + this.pullRequestTitle = Preconditions.checkNotNull(pullRequestTitle, "pullRequestTitle must not be null."); + this.pullRequestDescription = Optional.ofNullable(pullRequestDescription).orElse(""); + this.pullRequestId = pullRequestId; + this.pullRequestIid = pullRequestIid; + this.pullRequestState = Optional.ofNullable(pullRequestState).orElse(""); + this.mergedByUser = Optional.ofNullable(mergedByUser).orElse(""); + this.pullRequestAssignee = Optional.ofNullable(pullRequestAssignee).orElse(""); + this.pullRequestTargetProjectId = pullRequestTargetProjectId; + this.before = Optional.ofNullable(before).orElse(""); + this.after = Optional.ofNullable(after).orElse(""); + this.lastCommit = lastCommit; + this.ref = ref; + this.beforeSha = beforeSha; + this.sha = sha; + this.isTag = isTag; + this.created = created; + this.deleted = deleted; + this.status = status; + this.stages = stages; + this.createdAt = createdAt; + this.finishedAt = finishedAt; + this.buildDuration = buildDuration; + this.jsonBody = jsonBody; + this.noteBody = noteBody; + this.triggerPhrase = triggerPhrase; + this.triggeredByUser = Preconditions.checkNotNull(triggeredByUser, "triggeredByUser must not be null."); + } + + public Map getBuildEnvironmentVariables() { + Map map = new HashMap<>(64); + map.put("giteeActionType", webHookType.name()); + map.put("giteeUserName", userName); + map.put("giteeUserEmail", userEmail); + map.put("giteeBranch", branch); + map.put("giteeSourceBranch", sourceBranch); + map.put("giteeSourceRepoHomepage", sourceRepoHomepage); + map.put("giteeSourceRepoName", sourceRepoName); + map.put("giteeSourceNamespace", sourceNamespace); + map.put("giteeSourceRepoURL", sourceRepoUrl); + map.put("giteeSourceRepoSshUrl", sourceRepoSshUrl); + map.put("giteeSourceRepoHttpUrl", sourceRepoHttpUrl); + map.put("giteeTargetBranch", targetBranch); + map.put("giteeTargetRepoName", targetRepoName); + map.put("giteeTargetNamespace", targetNamespace); + map.put("giteeTargetRepoSshUrl", targetRepoSshUrl); + map.put("giteeTargetRepoHttpUrl", targetRepoHttpUrl); + map.put("giteePullRequestTitle", pullRequestTitle); + map.put("giteePullRequestDescription", pullRequestDescription); + map.put("giteePullRequestId", Optional.ofNullable(pullRequestId).map(String::valueOf).orElse("")); + map.put("giteePullRequestIid", Optional.ofNullable(pullRequestIid).map(String::valueOf).orElse("")); + map.put("giteePullRequestTargetProjectId", Optional.ofNullable(pullRequestTargetProjectId).map(String::valueOf).orElse("")); + map.compute("giteePullRequestState", (k, v) -> pullRequestState); + map.compute("giteeMergedByUser", (k, v) -> mergedByUser); + map.compute("giteePullRequestAssignee", (k, v) -> pullRequestAssignee); + map.put("giteeBefore", before); + map.put("giteeAfter", after); + map.put("giteeBeforeCommitSha", before); + map.put("giteeAfterCommitSha", after); + map.put("giteePullRequestLastCommit", lastCommit); + map.put("giteeRef", ref); + map.put("ref", ref); + map.put("beforeSha", beforeSha); + map.put("sha", sha); + map.put("isTag", isTag); + map.put("giteePushCreated", String.valueOf(created)); + map.put("giteePushDeleted", String.valueOf(deleted)); + map.put("status", status); + map.put("stages", stages); + map.put("createdAt", createdAt); + map.put("finishedAt", finishedAt); + map.put("duration", buildDuration); + map.put("jsonBody", jsonBody); + map.put("noteBody", noteBody); + map.compute("giteeTriggerPhrase", (k, v) -> triggerPhrase); + return map; + } + + public String getShortDescription() { + return webHookType.getShortDescription(this); + } + +} diff --git a/src/main/java/com/gitee/jenkins/config/ApiTokenConfig.java b/src/main/java/com/gitee/jenkins/config/ApiTokenConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..62a58f44f5bf2c89dee000a32d3333ec729a5e09 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/ApiTokenConfig.java @@ -0,0 +1,15 @@ +package com.gitee.jenkins.config; + +import com.cloudbees.plugins.credentials.common.StandardCredentials; +import hudson.util.Secret; + +public interface ApiTokenConfig extends StandardCredentials { + + /** + * 获取 Api Token + * + * @return Api Token + */ + Secret getApiToken(); + +} diff --git a/src/main/java/com/gitee/jenkins/config/GiteeApiTokenConfig.java b/src/main/java/com/gitee/jenkins/config/GiteeApiTokenConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..40071274104420bf687e143d4d60065b0482c3fe --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/GiteeApiTokenConfig.java @@ -0,0 +1,55 @@ +package com.gitee.jenkins.config; + +import com.cloudbees.plugins.credentials.CredentialsNameProvider; +import com.cloudbees.plugins.credentials.CredentialsScope; +import com.cloudbees.plugins.credentials.NameWith; +import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials; +import hudson.Extension; +import hudson.Util; +import hudson.util.Secret; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.util.Optional; + +@NameWith(GiteeApiTokenConfig.NameProvider.class) +public final class GiteeApiTokenConfig extends BaseStandardCredentials implements ApiTokenConfig { + + /** + * gitee api token + */ + private Secret apiToken; + + /** + * 获取 gitee api token + * + * @return apiToken + */ + @Override + public Secret getApiToken() { + return apiToken; + } + + @DataBoundConstructor + public GiteeApiTokenConfig(CredentialsScope scope, String id, String description, Secret apiToken) { + super(scope, id, description); + this.apiToken = apiToken; + } + + protected static class NameProvider extends CredentialsNameProvider { + @Override + public String getName(ApiTokenConfig c) { + String description = Util.fixEmptyAndTrim(c.getDescription()); + return Messages.GiteeApiToken_name() + + Optional.ofNullable(description).map(s -> String.join("(", description, ")")).orElse(""); + } + } + + @Extension + public static class DescriptorImpl extends BaseStandardCredentialsDescriptor { + @Override + public String getDisplayName() { + return Messages.GiteeApiToken_name(); + } + } + +} diff --git a/src/main/java/com/gitee/jenkins/config/GiteeConnectionConfig.java b/src/main/java/com/gitee/jenkins/config/GiteeConnectionConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..572cb36ae8a783eab33f09f0935b6cff75f347c0 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/GiteeConnectionConfig.java @@ -0,0 +1,281 @@ +package com.gitee.jenkins.config; + +import com.cloudbees.plugins.credentials.*; +import com.cloudbees.plugins.credentials.common.StandardCredentials; +import com.cloudbees.plugins.credentials.common.StandardListBoxModel; +import com.cloudbees.plugins.credentials.domains.Domain; +import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder; +import com.gitee.jenkins.api.client.GiteeClient; +import com.gitee.jenkins.api.client.factory.GiteeClientFactory; +import com.gitee.jenkins.enums.GiteeClientType; +import com.gitee.jenkins.excetion.GiteeClientRequestException; +import hudson.Extension; +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Descriptor; +import hudson.model.Item; +import hudson.security.ACL; +import hudson.util.FormValidation; +import hudson.util.ListBoxModel; +import hudson.util.Secret; +import jenkins.model.Jenkins; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.jenkinsci.plugins.plaincredentials.StringCredentials; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; + +import java.io.IOException; +import java.util.*; + +/** + * Gitee链接配置 + */ +@Getter +@Setter +public class GiteeConnectionConfig extends AbstractDescribableImpl { + + private static final GiteeClientType GITEE_CLIENT_TYPE = GiteeClientType.V5; + + /** + * 链接名 + */ + private String name; + + /** + * Gitee域名URL + */ + private String url; + + /** + * 证书令牌id + */ + private String apiTokenId; + + /** + * 证书令牌 + * + * @deprecated 已废弃设置,现在不直接配置 apiToken,而是配置链接 + */ + @Deprecated + private transient String apiToken; + + /** + * 忽略 SSL 证书错误 + */ + private final boolean ignoreCertificateErrors; + + /** + * 建立链接超时时间 单位:秒 + */ + private Integer connectionTimeout; + + /** + * 读取超时时间 单位:秒 + */ + private Integer readTimeout; + + private transient GiteeClientFactory giteeClientFactory; + + private transient GiteeClient giteeClient; + + @DataBoundConstructor + public GiteeConnectionConfig(String name, String url, String apiTokenId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) { + this.name = name; + this.url = url; + this.apiTokenId = apiTokenId; + this.ignoreCertificateErrors = ignoreCertificateErrors; + this.connectionTimeout = connectionTimeout; + this.readTimeout = readTimeout; + this.giteeClientFactory = GiteeClientFactory.getGiteeClientFactory(GITEE_CLIENT_TYPE); + } + + @Restricted(NoExternalUse.class) + public GiteeConnectionConfig(String url, String apiTokenId, boolean ignoreCertificateErrors) { + this("", url, apiTokenId, ignoreCertificateErrors, 0, 0); + } + + public GiteeClient getGiteeClient() { + if (giteeClient == null) { + giteeClient = giteeClientFactory.getGiteeClient(url, getApiToken(apiTokenId), ignoreCertificateErrors, connectionTimeout, readTimeout); + } + return giteeClient; + } + + @Restricted(NoExternalUse.class) + private String getApiToken(String apiTokenId) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + + StandardCredentials credentials = CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials(StandardCredentials.class, (Item) null, ACL.SYSTEM, Collections.emptyList()), + CredentialsMatchers.withId(apiTokenId) + ); + + if (credentials != null) { + if (credentials instanceof GiteeApiTokenConfig) { + return ((GiteeApiTokenConfig) credentials).getApiToken().getPlainText(); + } + if (credentials instanceof StringCredentials) { + return ((StringCredentials) credentials).getSecret().getPlainText(); + } + } + + throw new IllegalStateException("No credentials found for credentialsId: " + apiTokenId); + } + + protected GiteeConnectionConfig readResolve() { + if (connectionTimeout == null || readTimeout == null) { + return new GiteeConnectionConfig(name, url, apiTokenId, ignoreCertificateErrors, 10, 10); + } + giteeClientFactory = GiteeClientFactory.getGiteeClientFactory(GITEE_CLIENT_TYPE); + return this; + } + + /** + * 兼容直接输入token的场景 + */ + @Initializer(after = InitMilestone.PLUGINS_STARTED) + public static void compatibleProcessing() throws IOException { + GiteeGlobalConfig giteeGlobalConfig = (GiteeGlobalConfig) Jenkins.get().getDescriptor(GiteeGlobalConfig.class); + if (giteeGlobalConfig == null) { + return; + } + for (GiteeConnectionConfig giteeConnectionConfig : giteeGlobalConfig.getGiteeConnectionConfigs()) { + if (Objects.isNull(giteeConnectionConfig.apiTokenId) && Objects.nonNull(giteeConnectionConfig.apiToken)) { + for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.get())) { + if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) { + List domains = credentialsStore.getDomains(); + giteeConnectionConfig.apiTokenId = UUID.randomUUID().toString(); + credentialsStore.addCredentials( + domains.get(0), + new GiteeApiTokenConfig(CredentialsScope.SYSTEM, giteeConnectionConfig.apiTokenId, "Gitee API Token", Secret.fromString(giteeConnectionConfig.apiToken)) + ); + } + } + } + } + giteeGlobalConfig.save(); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + /** + * 测试链接 + * + * @param url + * @param apiTokenId + * @param ignoreCertificateErrors + * @return + */ + public FormValidation doTestConnection(@QueryParameter String url, + @QueryParameter String apiTokenId, + @QueryParameter boolean ignoreCertificateErrors) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + + try { + new GiteeConnectionConfig(url, apiTokenId, ignoreCertificateErrors) + .getGiteeClient() + .getUser(); + return FormValidation.ok(Messages.connection_success()); + } catch (GiteeClientRequestException e) { + return FormValidation.error(Messages.connection_error(e.getMessage())); + } + + } + + /** + * 名称校验 + * + * @param value + * @return + */ + public FormValidation doCheckName(@QueryParameter String id, @QueryParameter String value) { + if (StringUtils.isBlank(value)) { + return FormValidation.error(Messages.name_required()); + } + boolean nameExist = Optional.ofNullable((GiteeGlobalConfig) Jenkins.get().getDescriptor(GiteeGlobalConfig.class)) + .map(giteeGlobalConfig -> giteeGlobalConfig.containsGiteeConnectionName(id, value)) + .orElse(false); + if (nameExist) { + return FormValidation.error(Messages.name_exists(value)); + } + return FormValidation.ok(); + } + + /** + * url校验 + * + * @param value + * @return + */ + public FormValidation doCheckUrl(@QueryParameter String value) { + if (StringUtils.isBlank(value)) { + return FormValidation.error(Messages.url_required()); + } + return FormValidation.ok(); + } + + /** + * api token id校验 + * + * @param value + * @return + */ + public FormValidation doCheckApiTokenId(@QueryParameter String value) { + if (StringUtils.isBlank(value)) { + return FormValidation.error(Messages.apiToken_required()); + } + return FormValidation.ok(); + } + + /** + * 链接超时时间校验 + * + * @param value + * @return + */ + public FormValidation doCheckConnectionTimeout(@QueryParameter Integer value) { + if (Objects.isNull(value)) { + return FormValidation.error(Messages.connectionTimeout_required()); + } + return FormValidation.ok(); + } + + /** + * 读取超时时间校验 + * + * @param value + * @return + */ + public FormValidation doCheckReadTimeout(@QueryParameter Integer value) { + if (value == null) { + return FormValidation.error(Messages.readTimeout_required()); + } + return FormValidation.ok(); + } + + public ListBoxModel doFillApiTokenIdItems(@QueryParameter String url, @QueryParameter String apiTokenId) { + if (Jenkins.get().hasPermission(Item.CONFIGURE)) { + new StandardListBoxModel() + .includeEmptyValue() + .includeCurrentValue(apiTokenId); + return new StandardListBoxModel() + .includeEmptyValue() + .includeMatchingAs( + ACL.SYSTEM, + Jenkins.get(), + StandardCredentials.class, + URIRequirementBuilder.fromUri(url).build(), + new GiteeCredentialMatcher() + ).includeCurrentValue(apiTokenId); + } + return new StandardListBoxModel(); + } + + } + +} diff --git a/src/main/java/com/gitee/jenkins/config/GiteeCredentialMatcher.java b/src/main/java/com/gitee/jenkins/config/GiteeCredentialMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..1c549b561ed949cca8a0fdaa43e7ac00abc72778 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/GiteeCredentialMatcher.java @@ -0,0 +1,18 @@ +package com.gitee.jenkins.config; + +import com.cloudbees.plugins.credentials.Credentials; +import com.cloudbees.plugins.credentials.CredentialsMatcher; +import org.jenkinsci.plugins.plaincredentials.StringCredentials; + +public class GiteeCredentialMatcher implements CredentialsMatcher { + + @Override + public boolean matches(Credentials credentials) { + try { + return credentials instanceof GiteeApiTokenConfig || credentials instanceof StringCredentials; + } catch (Exception e) { + return false; + } + } + +} diff --git a/src/main/java/com/gitee/jenkins/config/GiteeGlobalConfig.java b/src/main/java/com/gitee/jenkins/config/GiteeGlobalConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..0d75ca22a8c2a363c90cb3a3177d1fe83b4840e4 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/GiteeGlobalConfig.java @@ -0,0 +1,91 @@ +package com.gitee.jenkins.config; + +import com.gitee.jenkins.api.client.GiteeClient; +import hudson.Extension; +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import jenkins.model.GlobalConfiguration; +import jenkins.model.Jenkins; +import lombok.Getter; +import lombok.Setter; +import net.sf.json.JSONObject; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; +import org.kohsuke.stapler.StaplerRequest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * Gitee全局配置 + */ +@Getter +@Setter +@Extension +public class GiteeGlobalConfig extends GlobalConfiguration { + + private static final Logger LOGGER = Logger.getLogger(GiteeGlobalConfig.class.getName()); + + private List giteeConnectionConfigs; + private transient Map giteeConnectionConfigMap; + + @DataBoundConstructor + public GiteeGlobalConfig() { + giteeConnectionConfigs = new ArrayList<>(); + // 加载持久化配置 + load(); + refreshGiteeConnectionConfigMap(); + } + + @Override + public boolean configure(StaplerRequest req, JSONObject json) throws FormException { + giteeConnectionConfigs = req.bindJSONToList(GiteeConnectionConfig.class, json.get("connections")); + refreshGiteeConnectionConfigMap(); + save(); + return super.configure(req, json); + } + + /** + * 重建Gitee链接配置映射 + */ + private void refreshGiteeConnectionConfigMap() { + giteeConnectionConfigMap = giteeConnectionConfigs.stream().collect(Collectors.toMap(GiteeConnectionConfig::getName, Function.identity())); + } + + @DataBoundSetter + public void setGiteeConnectionConfigs(List giteeConnectionConfigs) { + this.giteeConnectionConfigs = giteeConnectionConfigs; + refreshGiteeConnectionConfigMap(); + save(); + } + + public GiteeClient getGiteeClient(String giteeConnectionName) { + return Optional.ofNullable(giteeConnectionConfigMap.get(giteeConnectionName)) + .map(GiteeConnectionConfig::getGiteeClient) + .orElse(null); + } + + public boolean containsGiteeConnectionName(String id, String giteeConnectionName) { + return Optional.ofNullable(giteeConnectionConfigMap) + .map(map -> map.get(giteeConnectionName)) + .map(giteeConnectionConfig -> !giteeConnectionConfig.toString().equals(id)) + .orElse(false); + } + + /** + * 提供一个空输入 + */ + @Initializer(after = InitMilestone.SYSTEM_CONFIG_ADAPTED) + public static void init() { + GiteeGlobalConfig giteeGlobalConfig = (GiteeGlobalConfig) Jenkins.get().getDescriptor(GiteeGlobalConfig.class); + if (giteeGlobalConfig != null && giteeGlobalConfig.getGiteeConnectionConfigs().isEmpty()) { + giteeGlobalConfig.getGiteeConnectionConfigs().add(new GiteeConnectionConfig("", null, false)); + } + } + +} diff --git a/src/main/java/com/gitee/jenkins/config/GiteeItemConfig.java b/src/main/java/com/gitee/jenkins/config/GiteeItemConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..b3c88c61e03704e4422bedea685d235da8f3ae27 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/config/GiteeItemConfig.java @@ -0,0 +1,78 @@ +package com.gitee.jenkins.config; + +import com.gitee.jenkins.api.client.GiteeClient; +import hudson.Extension; +import hudson.model.Job; +import hudson.model.JobProperty; +import hudson.model.JobPropertyDescriptor; +import hudson.util.ListBoxModel; +import jenkins.model.Jenkins; +import lombok.Getter; +import net.sf.json.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.jenkinsci.Symbol; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.StaplerRequest; + +import java.util.Optional; + +/** + * 单个Item内Gitee配置 + */ +@Getter +public class GiteeItemConfig extends JobProperty> { + + private String giteeConnectionName; + + @DataBoundConstructor + public GiteeItemConfig(String giteeConnectionName) { + this.giteeConnectionName = giteeConnectionName; + } + + public static GiteeClient getGiteeClient(Job job) { + return Optional.ofNullable(job.getProperty(GiteeItemConfig.class)) + .map(GiteeItemConfig::getGiteeClient) + .orElse(null); + } + + public GiteeClient getGiteeClient() { + if (StringUtils.isNotBlank(giteeConnectionName)) { + GiteeGlobalConfig giteeGlobalConfig = (GiteeGlobalConfig) Jenkins.get().getDescriptor(GiteeGlobalConfig.class); + return giteeGlobalConfig == null ? null : giteeGlobalConfig.getGiteeClient(giteeConnectionName); + } + return null; + } + + @Extension + @Symbol("giteeConnectionName") + public static class DescriptorImpl extends JobPropertyDescriptor { + + @Override + public String getDisplayName() { + return "Gitee connection"; + } + + @Override + public boolean isApplicable(Class jobType) { + return true; + } + + @Override + public JobProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { + return req.bindJSON(GiteeItemConfig.class, formData); + } + + public ListBoxModel doFillGiteeConnectionNameItems() { + ListBoxModel listBoxModel = new ListBoxModel(); + GiteeGlobalConfig giteeGlobalConfig = (GiteeGlobalConfig) Jenkins.get().getDescriptor(GiteeGlobalConfig.class); + if (giteeGlobalConfig != null) { + for (GiteeConnectionConfig giteeConnectionConfig : giteeGlobalConfig.getGiteeConnectionConfigs()) { + listBoxModel.add(giteeConnectionConfig.getName(), giteeConnectionConfig.getName()); + } + } + return listBoxModel; + } + + } + +} diff --git a/src/main/java/com/gitee/jenkins/connection/GiteeApiToken.java b/src/main/java/com/gitee/jenkins/connection/GiteeApiToken.java deleted file mode 100644 index 28cfec42aae5d08aa95050cbf23c9e315e060187..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/connection/GiteeApiToken.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gitee.jenkins.connection; - -import com.cloudbees.plugins.credentials.CredentialsNameProvider; -import com.cloudbees.plugins.credentials.NameWith; -import com.cloudbees.plugins.credentials.common.StandardCredentials; -import hudson.Util; -import hudson.util.Secret; - -/** - * @author Robin Müller - */ -@NameWith(GiteeApiToken.NameProvider.class) -public interface GiteeApiToken extends StandardCredentials { - - Secret getApiToken(); - - class NameProvider extends CredentialsNameProvider { - @Override - public String getName(GiteeApiToken c) { - String description = Util.fixEmptyAndTrim(c.getDescription()); - return Messages.GiteeApiToken_name() + (description != null ? " (" + description + ")" : ""); - } - } -} diff --git a/src/main/java/com/gitee/jenkins/connection/GiteeApiTokenImpl.java b/src/main/java/com/gitee/jenkins/connection/GiteeApiTokenImpl.java deleted file mode 100644 index 99f7a9a4a807ae595ca1a7b974fb0b491b590244..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/connection/GiteeApiTokenImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gitee.jenkins.connection; - -import com.cloudbees.plugins.credentials.CredentialsScope; -import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials; -import hudson.Extension; -import hudson.util.Secret; -import org.kohsuke.stapler.DataBoundConstructor; - -/** - * @author Robin Müller - */ -public final class GiteeApiTokenImpl extends BaseStandardCredentials implements GiteeApiToken { - - private Secret apiToken; - - @DataBoundConstructor - public GiteeApiTokenImpl(CredentialsScope scope, String id, String description, Secret apiToken) { - super(scope, id, description); - this.apiToken = apiToken; - } - - @Override - public Secret getApiToken() { - return apiToken; - } - - @Extension - public static class DescriptorImpl extends BaseStandardCredentialsDescriptor { - @Override - public String getDisplayName() { - return Messages.GiteeApiToken_name(); - } - } -} diff --git a/src/main/java/com/gitee/jenkins/connection/GiteeConnection.java b/src/main/java/com/gitee/jenkins/connection/GiteeConnection.java deleted file mode 100644 index 32390c35a9ce92ea283285a9cd3e66a190eca5a6..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/connection/GiteeConnection.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.gitee.jenkins.connection; - - -import com.cloudbees.plugins.credentials.CredentialsMatchers; -import com.cloudbees.plugins.credentials.CredentialsProvider; -import com.cloudbees.plugins.credentials.CredentialsScope; -import com.cloudbees.plugins.credentials.CredentialsStore; -import com.cloudbees.plugins.credentials.SystemCredentialsProvider; -import com.cloudbees.plugins.credentials.common.StandardCredentials; -import com.cloudbees.plugins.credentials.domains.Domain; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; -import com.gitee.jenkins.gitee.api.GiteeClient; -import com.gitee.jenkins.gitee.api.GiteeClientBuilder; -import com.gitee.jenkins.gitee.api.impl.GiteeV5ClientBuilder; -import hudson.init.InitMilestone; -import hudson.init.Initializer; -import hudson.model.Item; -import hudson.security.ACL; -import hudson.util.Secret; -import jenkins.model.Jenkins; -import org.jenkinsci.plugins.plaincredentials.StringCredentials; -import org.kohsuke.accmod.Restricted; -import org.kohsuke.accmod.restrictions.NoExternalUse; -import org.kohsuke.stapler.DataBoundConstructor; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials; -import static com.gitee.jenkins.gitee.api.GiteeClientBuilder.getGiteeClientBuilderById; - - -/** - * @author Robin Müller - */ -public class GiteeConnection { - private final String name; - private final String url; - private transient String apiToken; - // TODO make final when migration code gets removed - private String apiTokenId; - private GiteeClientBuilder clientBuilder; - private final boolean ignoreCertificateErrors; - private final Integer connectionTimeout; - private final Integer readTimeout; - private transient GiteeClient apiCache; - - public GiteeConnection(String name, String url, String apiTokenId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) { - this( - name, - url, - apiTokenId, - new GiteeV5ClientBuilder(), - ignoreCertificateErrors, - connectionTimeout, - readTimeout - ); - } - - @DataBoundConstructor - public GiteeConnection(String name, String url, String apiTokenId, String clientBuilderId, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) { - this( - name, - url, - apiTokenId, - getGiteeClientBuilderById(clientBuilderId), - ignoreCertificateErrors, - connectionTimeout, - readTimeout - ); - } - - @Restricted(NoExternalUse.class) - public GiteeConnection(String name, String url, String apiTokenId, GiteeClientBuilder clientBuilder, boolean ignoreCertificateErrors, Integer connectionTimeout, Integer readTimeout) { - this.name = name; - this.url = url; - this.apiTokenId = apiTokenId; - this.clientBuilder = clientBuilder; - this.ignoreCertificateErrors = ignoreCertificateErrors; - this.connectionTimeout = connectionTimeout; - this.readTimeout = readTimeout; - } - - public String getName() { - return name; - } - - public String getUrl() { - return url; - } - - public String getApiTokenId() { - return apiTokenId; - } - - public String getClientBuilderId() { - return clientBuilder.id(); - } - - public boolean isIgnoreCertificateErrors() { - return ignoreCertificateErrors; - } - - public int getConnectionTimeout() { - return connectionTimeout; - } - - public int getReadTimeout() { - return readTimeout; - } - - public GiteeClient getClient() { - if (apiCache == null) { - apiCache = clientBuilder.buildClient(url, getApiToken(apiTokenId), ignoreCertificateErrors, connectionTimeout, readTimeout); - } - - return apiCache; - } - - private String getApiToken(String apiTokenId) { - StandardCredentials credentials = CredentialsMatchers.firstOrNull( - lookupCredentials(StandardCredentials.class, (Item) null, ACL.SYSTEM, new ArrayList()), - CredentialsMatchers.withId(apiTokenId)); - if (credentials != null) { - if (credentials instanceof GiteeApiToken) { - return ((GiteeApiToken) credentials).getApiToken().getPlainText(); - } - if (credentials instanceof StringCredentials) { - return ((StringCredentials) credentials).getSecret().getPlainText(); - } - } - throw new IllegalStateException("No credentials found for credentialsId: " + apiTokenId); - } - - - protected GiteeConnection readResolve() { - if (connectionTimeout == null || readTimeout == null) { - return new GiteeConnection(name, url, apiTokenId, new GiteeV5ClientBuilder(), ignoreCertificateErrors, 10, 10); - } - if (clientBuilder == null) { - return new GiteeConnection(name, url, apiTokenId, new GiteeV5ClientBuilder(), ignoreCertificateErrors, connectionTimeout, readTimeout); - } - - return this; - } - - @Initializer(after = InitMilestone.PLUGINS_STARTED) - public static void migrate() throws IOException { - GiteeConnectionConfig descriptor = (GiteeConnectionConfig) Jenkins.getInstance().getDescriptor(GiteeConnectionConfig.class); - for (GiteeConnection connection : descriptor.getConnections()) { - if (connection.apiTokenId == null && connection.apiToken != null) { - for (CredentialsStore credentialsStore : CredentialsProvider.lookupStores(Jenkins.getInstance())) { - if (credentialsStore instanceof SystemCredentialsProvider.StoreImpl) { - List domains = credentialsStore.getDomains(); - connection.apiTokenId = UUID.randomUUID().toString(); - credentialsStore.addCredentials(domains.get(0), - new GiteeApiTokenImpl(CredentialsScope.SYSTEM, connection.apiTokenId, "Gitee API Token", Secret.fromString(connection.apiToken))); - } - } - } - } - descriptor.save(); - } -} diff --git a/src/main/java/com/gitee/jenkins/connection/GiteeConnectionConfig.java b/src/main/java/com/gitee/jenkins/connection/GiteeConnectionConfig.java deleted file mode 100644 index b5df99101cf2d6477f768a39f7f1399f952d82c8..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/connection/GiteeConnectionConfig.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.gitee.jenkins.connection; - - -import com.cloudbees.plugins.credentials.Credentials; -import com.cloudbees.plugins.credentials.CredentialsMatcher; -import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel; -import com.cloudbees.plugins.credentials.common.StandardCredentials; -import com.cloudbees.plugins.credentials.common.StandardListBoxModel; -import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder; -import com.gitee.jenkins.gitee.api.GiteeClient; -import com.gitee.jenkins.gitee.api.GiteeClientBuilder; -import edu.umd.cs.findbugs.annotations.NonNull; -import hudson.Extension; -import hudson.model.Item; -import hudson.security.ACL; -import hudson.util.FormValidation; -import hudson.util.ListBoxModel; -import jenkins.model.GlobalConfiguration; -import jenkins.model.Jenkins; -import net.sf.json.JSONObject; -import org.eclipse.jgit.util.StringUtils; -import org.jenkinsci.plugins.plaincredentials.StringCredentials; -import org.kohsuke.stapler.QueryParameter; -import org.kohsuke.stapler.StaplerRequest; - -import javax.ws.rs.ProcessingException; -import javax.ws.rs.WebApplicationException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.gitee.jenkins.gitee.api.GiteeClientBuilder.getAllGiteeClientBuilders; - - -/** - * @author Robin Müller - */ -@Extension -public class GiteeConnectionConfig extends GlobalConfiguration { - - private Boolean useAuthenticatedEndpoint = true; - private List connections = new ArrayList<>(); - private transient Map connectionMap = new HashMap<>(); - - public GiteeConnectionConfig() { - load(); - refreshConnectionMap(); - } - - @Override - public boolean configure(StaplerRequest req, JSONObject json) throws FormException { - connections = req.bindJSONToList(GiteeConnection.class, json.get("connections")); -// useAuthenticatedEndpoint = json.getBoolean("useAuthenticatedEndpoint"); - refreshConnectionMap(); - save(); - return super.configure(req, json); - } - - public boolean isUseAuthenticatedEndpoint() { - return useAuthenticatedEndpoint; - } - - void setUseAuthenticatedEndpoint(boolean useAuthenticatedEndpoint) { - this.useAuthenticatedEndpoint = useAuthenticatedEndpoint; - } - - public List getConnections() { - return connections; - } - - public void addConnection(GiteeConnection connection) { - connections.add(connection); - connectionMap.put(connection.getName(), connection); - } - - public void setConnections(List newConnections) { - connections = new ArrayList<>(); - connectionMap = new HashMap<>(); - for (GiteeConnection connection: newConnections){ - addConnection(connection); - } - } - - public GiteeClient getClient(String connectionName) { - if (!connectionMap.containsKey(connectionName)) { - return null; - } - return connectionMap.get(connectionName).getClient(); - } - - public FormValidation doCheckName(@QueryParameter String id, @QueryParameter String value) { - if (StringUtils.isEmptyOrNull(value)) { - return FormValidation.error(Messages.name_required()); - } else if (connectionMap.containsKey(value) && !connectionMap.get(value).toString().equals(id)) { - return FormValidation.error(Messages.name_exists(value)); - } else { - return FormValidation.ok(); - } - } - - public FormValidation doCheckUrl(@QueryParameter String value) { - if (StringUtils.isEmptyOrNull(value)) { - return FormValidation.error(Messages.url_required()); - } else { - return FormValidation.ok(); - } - } - - public FormValidation doCheckApiTokenId(@QueryParameter String value) { - if (StringUtils.isEmptyOrNull(value)) { - return FormValidation.error(Messages.apiToken_required()); - } else { - return FormValidation.ok(); - } - } - - public FormValidation doCheckConnectionTimeout(@QueryParameter Integer value) { - if (value == null) { - return FormValidation.error(Messages.connectionTimeout_required()); - } else { - return FormValidation.ok(); - } - } - - public FormValidation doCheckReadTimeout(@QueryParameter Integer value) { - if (value == null) { - return FormValidation.error(Messages.readTimeout_required()); - } else { - return FormValidation.ok(); - } - } - - public FormValidation doTestConnection(@QueryParameter String url, - @QueryParameter String apiTokenId, - @QueryParameter String clientBuilderId, - @QueryParameter boolean ignoreCertificateErrors, - @QueryParameter int connectionTimeout, - @QueryParameter int readTimeout) { - try { - if (clientBuilderId == null) { - clientBuilderId = "v5"; - } - - new GiteeConnection("", url, apiTokenId, clientBuilderId, ignoreCertificateErrors, connectionTimeout, readTimeout).getClient().getCurrentUser(); - return FormValidation.ok(Messages.connection_success()); - } catch (WebApplicationException e) { - return FormValidation.error(Messages.connection_error(e.getMessage())); - } catch (ProcessingException e) { - return FormValidation.error(Messages.connection_error(e.getCause().getMessage())); - } - } - - public ListBoxModel doFillApiTokenIdItems(@QueryParameter String name, @QueryParameter String url) { - if (Jenkins.getInstance().hasPermission(Item.CONFIGURE)) { - AbstractIdCredentialsListBoxModel options = new StandardListBoxModel() - .includeEmptyValue() - .includeMatchingAs(ACL.SYSTEM, - Jenkins.getActiveInstance(), - StandardCredentials.class, - URIRequirementBuilder.fromUri(url).build(), - new GiteeCredentialMatcher()); - if (name != null && connectionMap.containsKey(name)) { - String apiTokenId = connectionMap.get(name).getApiTokenId(); - options.includeCurrentValue(apiTokenId); - for (ListBoxModel.Option option : options) { - if (option.value.equals(apiTokenId)) { - option.selected = true; - } - } - } - return options; - } - return new StandardListBoxModel(); - } - - public ListBoxModel doFillClientBuilderIdItems() { - ListBoxModel model = new ListBoxModel(); - for (GiteeClientBuilder builder : getAllGiteeClientBuilders()) { - model.add(builder.id()); - } - - return model; - } - - private void refreshConnectionMap() { - connectionMap.clear(); - for (GiteeConnection connection : connections) { - connectionMap.put(connection.getName(), connection); - } - } - - private static class GiteeCredentialMatcher implements CredentialsMatcher { - @Override - public boolean matches(@NonNull Credentials credentials) { - try { - return credentials instanceof GiteeApiToken || credentials instanceof StringCredentials; - } catch (Throwable e) { - return false; - } - } - } - //For backwards compatibility. ReadResolve is called on startup - protected GiteeConnectionConfig readResolve() { - if (useAuthenticatedEndpoint == null) { - setUseAuthenticatedEndpoint(false); - } - return this; - } -} diff --git a/src/main/java/com/gitee/jenkins/connection/GiteeConnectionProperty.java b/src/main/java/com/gitee/jenkins/connection/GiteeConnectionProperty.java deleted file mode 100644 index ce985b2ea80777517098d8bedf2cb9d165398773..0000000000000000000000000000000000000000 --- a/src/main/java/com/gitee/jenkins/connection/GiteeConnectionProperty.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.gitee.jenkins.connection; - - -import com.gitee.jenkins.gitee.api.GiteeClient; -import hudson.Extension; -import hudson.model.Job; -import hudson.model.JobProperty; -import hudson.model.JobPropertyDescriptor; -import hudson.model.Run; -import hudson.util.ListBoxModel; -import jenkins.model.Jenkins; -import net.sf.json.JSONObject; -import org.apache.commons.lang.StringUtils; -import org.jenkinsci.Symbol; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.StaplerRequest; - -/** - * @author Robin Müller - */ -public class GiteeConnectionProperty extends JobProperty> { - - private String giteeConnection; - - @DataBoundConstructor - public GiteeConnectionProperty(String giteeConnection) { - this.giteeConnection = giteeConnection; - } - - public String getGiteeConnection() { - return giteeConnection; - } - - public GiteeClient getClient() { - if (StringUtils.isNotEmpty(giteeConnection)) { - GiteeConnectionConfig connectionConfig = (GiteeConnectionConfig) Jenkins.getInstance().getDescriptor(GiteeConnectionConfig.class); - return connectionConfig != null ? connectionConfig.getClient(giteeConnection) : null; - } - return null; - } - - public static GiteeClient getClient(Run build) { - final GiteeConnectionProperty connectionProperty = build.getParent().getProperty(GiteeConnectionProperty.class); - if (connectionProperty != null) { - return connectionProperty.getClient(); - } - return null; - } - - public static GiteeClient getClient(Job job) { - final GiteeConnectionProperty connectionProperty = job.getProperty(GiteeConnectionProperty.class); - if (connectionProperty != null) { - return connectionProperty.getClient(); - } - return null; - } - - - @Extension - @Symbol("giteeConnection") - public static class DescriptorImpl extends JobPropertyDescriptor { - - @Override - public String getDisplayName() { - return "Gitee connection"; - } - - @Override - public boolean isApplicable(Class jobType) { - return true; - } - - @Override - public JobProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - return req.bindJSON(GiteeConnectionProperty.class, formData); - } - - public ListBoxModel doFillGiteeConnectionItems() { - ListBoxModel options = new ListBoxModel(); - GiteeConnectionConfig descriptor = (GiteeConnectionConfig) Jenkins.getInstance().getDescriptor(GiteeConnectionConfig.class); - for (GiteeConnection connection : descriptor.getConnections()) { - options.add(connection.getName(), connection.getName()); - } - return options; - } - } -} diff --git a/src/main/java/com/gitee/jenkins/entity/Branch.java b/src/main/java/com/gitee/jenkins/entity/Branch.java new file mode 100644 index 0000000000000000000000000000000000000000..d7b3e630ef176603ceaedf9dac1f8224b3de36f1 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/Branch.java @@ -0,0 +1,33 @@ +package com.gitee.jenkins.entity; + +import lombok.Data; + +@Data +public class Branch { + + /** + * 标签 + */ + private String label; + + /** + * 分支名称 + */ + private String ref; + + /** + * sha + */ + private String sha; + + /** + * 用户 + */ + private User user; + + /** + * 仓库 + */ + private Repository repo; + +} diff --git a/src/main/java/com/gitee/jenkins/entity/Commit.java b/src/main/java/com/gitee/jenkins/entity/Commit.java new file mode 100644 index 0000000000000000000000000000000000000000..1d1822e8f33df531d09fee2c863dff3c3eb90a19 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/Commit.java @@ -0,0 +1,35 @@ +package com.gitee.jenkins.entity; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class Commit { + + private String id; + + private String treeId; + + private List parentIds; + + private String message; + + private Date timestamp; + + private String url; + + private User author; + + private User committer; + + private Boolean distinct; + + private List added; + + private List removed; + + private List modified; + +} diff --git a/src/main/java/com/gitee/jenkins/entity/CommitComment.java b/src/main/java/com/gitee/jenkins/entity/CommitComment.java new file mode 100644 index 0000000000000000000000000000000000000000..ea6fe8ffcf9170f6c48b09de6050591d9846c0d1 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/CommitComment.java @@ -0,0 +1,12 @@ +package com.gitee.jenkins.entity; + +import lombok.Data; + +@Data +public class CommitComment extends PullRequestComment { + + private String position; + + private String commitId; + +} diff --git a/src/main/java/com/gitee/jenkins/entity/CommitCommentWebHook.java b/src/main/java/com/gitee/jenkins/entity/CommitCommentWebHook.java new file mode 100644 index 0000000000000000000000000000000000000000..755dfa25058ed5fbfd9b89d6f22caf7fe940e801 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/CommitCommentWebHook.java @@ -0,0 +1,45 @@ +package com.gitee.jenkins.entity; + +import com.gitee.jenkins.enums.PullRequestCommentAction; +import com.gitee.jenkins.enums.WebHookType; +import lombok.Data; + +@Data +public class CommitCommentWebHook extends WebHook { + + private PullRequestCommentAction action; + + private CommitComment comment; + + private User author; + + private String url; + + private String note; + + private String noteableType; + + private Integer noteableId; + + private String title; + + private String perIid; + + private String shortCommitId; + + @Override + public WebHookType getWebHookType() { + return WebHookType.COMMIT_COMMENT; + } + + @Override + public String getWebHookDescription() { + return super.getHookName() + " commit sha = " + comment.getCommitId(); + } + + @Override + public String getTargetBranch() { + return ""; + } + +} diff --git a/src/main/java/com/gitee/jenkins/entity/Enterprise.java b/src/main/java/com/gitee/jenkins/entity/Enterprise.java new file mode 100644 index 0000000000000000000000000000000000000000..0eafc4f5dbb875fd8fc6daa5958c6d4c7335b962 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/Enterprise.java @@ -0,0 +1,12 @@ +package com.gitee.jenkins.entity; + +import lombok.Data; + +@Data +public class Enterprise { + + private String name; + + private String url; + +} diff --git a/src/main/java/com/gitee/jenkins/entity/Label.java b/src/main/java/com/gitee/jenkins/entity/Label.java new file mode 100644 index 0000000000000000000000000000000000000000..d307e088d316cd7e77005934f79887abda80f96e --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/Label.java @@ -0,0 +1,14 @@ +package com.gitee.jenkins.entity; + +import lombok.Data; + +@Data +public class Label { + + private Integer id; + + private String name; + + private String color; + +} diff --git a/src/main/java/com/gitee/jenkins/entity/PullRequest.java b/src/main/java/com/gitee/jenkins/entity/PullRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..e5e280b100a5d97775be84d0156a972f6e392d76 --- /dev/null +++ b/src/main/java/com/gitee/jenkins/entity/PullRequest.java @@ -0,0 +1,160 @@ +package com.gitee.jenkins.entity; + +import com.gitee.jenkins.enums.PullRequestState; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class PullRequest { + + /** + * PR id + */ + private Integer id; + + /** + * PR 序号 + */ + private Integer number; + + private PullRequestState state; + + private String htmlUrl; + + private String diffUrl; + + private String patchUrl; + + /** + * PR 标题 + */ + private String title; + + /** + * PR 内容 + */ + private String body; + + /** + * PR 标签 + */ + private List