diff options
17 files changed, 1136 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21e5893 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +target/ +work/ + +# +# Eclipse metadata. +# +.project +.classpath +.settings/ + +# +# Eclipse and Maven build results +# +bin/ + +# IntelliJ metadata. +*.iml +*.ipr +*.iws +.idea/ @@ -0,0 +1,57 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.jenkins-ci.plugins</groupId> + <artifactId>plugin</artifactId> + <version>1.509.4</version><!-- which version of Jenkins is this plugin built against? --> + </parent> + + <groupId>bitbucket-pullrequest-builder</groupId> + <artifactId>bitbucket-pullrequest-builder</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>hpi</packaging> + + <!-- get every artifact through repo.jenkins-ci.org, which proxies all the artifacts that we need --> + <repositories> + <repository> + <id>repo.jenkins-ci.org</id> + <url>http://repo.jenkins-ci.org/public/</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-http</artifactId> + <version>2.4</version> + </dependency> + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-jaxrs</artifactId> + <version>1.9.13</version> + </dependency> + </dependencies> + + <pluginRepositories> + <pluginRepository> + <id>repo.jenkins-ci.org</id> + <url>http://repo.jenkins-ci.org/public/</url> + </pluginRepository> + </pluginRepositories> + +</project> diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildListener.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildListener.java new file mode 100644 index 0000000..95931ad --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildListener.java @@ -0,0 +1,36 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import hudson.Extension; +import hudson.model.AbstractBuild; +import hudson.model.TaskListener; +import hudson.model.listeners.RunListener; + +import javax.annotation.Nonnull; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +@Extension +public class BitbucketBuildListener extends RunListener<AbstractBuild> { + private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName()); + + @Override + public void onStarted(AbstractBuild abstractBuild, TaskListener listener) { + logger.info("BuildListener onStarted called."); + BitbucketBuildTrigger trigger = BitbucketBuildTrigger.getTrigger(abstractBuild.getProject()); + if (trigger == null) { + return; + } + trigger.getBuilder().getBuilds().onStarted(abstractBuild); + } + + @Override + public void onCompleted(AbstractBuild abstractBuild, @Nonnull TaskListener listener) { + BitbucketBuildTrigger trigger = BitbucketBuildTrigger.getTrigger(abstractBuild.getProject()); + if (trigger == null) { + return; + } + trigger.getBuilder().getBuilds().onCompleted(abstractBuild); + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java new file mode 100644 index 0000000..47d94dc --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java @@ -0,0 +1,160 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import antlr.ANTLRException; +import hudson.Extension; +import hudson.model.*; +import hudson.model.queue.QueueTaskFuture; +import hudson.triggers.Trigger; +import hudson.triggers.TriggerDescriptor; +import net.sf.json.JSONObject; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.StaplerRequest; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { + private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName()); + private final String projectPath; + private final String cron; + private final String username; + private final String password; + private final String repositoryOwner; + private final String repositoryName; + transient private BitbucketPullRequestsBuilder bitbucketPullRequestsBuilder; + + @Extension + public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); + + @DataBoundConstructor + public BitbucketBuildTrigger( + String projectPath, + String cron, + String username, + String password, + String repositoryOwner, + String repositoryName) throws ANTLRException { + super(cron); + this.projectPath = projectPath; + this.cron = cron; + this.username = username; + this.password = password; + this.repositoryOwner = repositoryOwner; + this.repositoryName = repositoryName; + } + + public String getProjectPath() { + return this.projectPath; + } + + public String getCron() { + return this.cron; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getRepositoryOwner() { + return repositoryOwner; + } + + public String getRepositoryName() { + return repositoryName; + } + + @Override + public void start(AbstractProject<?, ?> project, boolean newInstance) { + try { + this.bitbucketPullRequestsBuilder = BitbucketPullRequestsBuilder.getBuilder(); + this.bitbucketPullRequestsBuilder.setProject(project); + this.bitbucketPullRequestsBuilder.setTrigger(this); + this.bitbucketPullRequestsBuilder.setupBuilder(); + } catch(IllegalStateException e) { + logger.log(Level.SEVERE, "Can't start trigger", e); + return; + } + super.start(project, newInstance); + } + + public static BitbucketBuildTrigger getTrigger(AbstractProject project) { + Trigger trigger = project.getTrigger(BitbucketBuildTrigger.class); + return (BitbucketBuildTrigger)trigger; + } + + public BitbucketPullRequestsBuilder getBuilder() { + return this.bitbucketPullRequestsBuilder; + } + + public QueueTaskFuture<?> startJob(BitbucketCause cause) { + Map<String, ParameterValue> values = new HashMap<String, ParameterValue>(); + values.put("sourceBranch", new StringParameterValue("sourceBranch", cause.getSourceBranch())); + values.put("targetBranch", new StringParameterValue("targetBranch", cause.getTargetBranch())); + values.put("repositoryOwner", new StringParameterValue("repositoryOwner", cause.getRepositoryOwner())); + values.put("repositonyName", new StringParameterValue("repositoryName", cause.getRepositoryName())); + values.put("pullRequestId", new StringParameterValue("pullRequestId", cause.getPullRequestId())); + values.put("destinationRepositoryOwner", new StringParameterValue("destinationRepositoryOwner", cause.getDestinationRepositoryOwner())); + values.put("destinationRepositoryName", new StringParameterValue("destinationRepositoryName", cause.getDestinationRepositoryName())); + values.put("pullRequestTitle", new StringParameterValue("pullRequestTitle", cause.getPullRequestTitle())); + return this.job.scheduleBuild2(0, cause, new ParametersAction(new ArrayList(values.values()))); + } + + private Map<String, ParameterValue> getDefaultParameters() { + Map<String, ParameterValue> values = new HashMap<String, ParameterValue>(); + ParametersDefinitionProperty definitionProperty = this.job.getProperty(ParametersDefinitionProperty.class); + + if (definitionProperty != null) { + for (ParameterDefinition definition : definitionProperty.getParameterDefinitions()) { + values.put(definition.getName(), definition.getDefaultParameterValue()); + } + } + return values; + } + + @Override + public void run() { + if(this.getBuilder().getProject().isDisabled()) { + logger.info("Build Skip."); + } else { + this.bitbucketPullRequestsBuilder.run(); + } + this.getDescriptor().save(); + } + + @Override + public void stop() { + super.stop(); + } + + public static final class BitbucketBuildTriggerDescriptor extends TriggerDescriptor { + public BitbucketBuildTriggerDescriptor() { + load(); + } + + @Override + public boolean isApplicable(Item item) { + return true; + } + + @Override + public String getDisplayName() { + return "Bitbucket Pull Requests Builder"; + } + + @Override + public boolean configure(StaplerRequest req, JSONObject json) throws FormException { + save(); + return super.configure(req, json); + } + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java new file mode 100644 index 0000000..a940ca9 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java @@ -0,0 +1,65 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import hudson.model.AbstractBuild; +import hudson.model.Cause; +import hudson.model.Result; +import jenkins.model.Jenkins; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +public class BitbucketBuilds { + private static final Logger logger = Logger.getLogger(BitbucketBuilds.class.getName()); + private BitbucketBuildTrigger trigger; + private BitbucketRepository repository; + + public BitbucketBuilds(BitbucketBuildTrigger trigger, BitbucketRepository repository) { + this.trigger = trigger; + this.repository = repository; + } + + public BitbucketCause getCause(AbstractBuild build) { + Cause cause = build.getCause(BitbucketCause.class); + if (cause == null || !(cause instanceof BitbucketCause)) { + return null; + } + return (BitbucketCause) cause; + } + + public void onStarted(AbstractBuild build) { + BitbucketCause cause = this.getCause(build); + if (cause == null) { + return; + } + try { + build.setDescription(cause.getShortDescription()); + } catch (IOException e) { + logger.log(Level.SEVERE, "Can't update build description", e); + } + } + + public void onCompleted(AbstractBuild build) { + BitbucketCause cause = this.getCause(build); + if (cause == null) { + return; + } + Result result = build.getResult(); + String rootUrl = Jenkins.getInstance().getRootUrl(); + String buildUrl = ""; + if (rootUrl == null) { + buildUrl = " PLEASE SET JENKINS ROOT URL FROM GLOBAL CONFIGURATION " + build.getUrl(); + } + else { + buildUrl = rootUrl + build.getUrl(); + } + if(result == Result.SUCCESS) { + repository.postFinishedComment(cause.getPullRequestId(), true, buildUrl); + } else if (result == Result.FAILURE || result == Result.UNSTABLE) { + repository.postFinishedComment(cause.getPullRequestId(), false, buildUrl); + } + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java new file mode 100644 index 0000000..1cb5da4 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java @@ -0,0 +1,76 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import hudson.model.Cause; + +/** + * Created by nishio + */ +public class BitbucketCause extends Cause { + private final String sourceBranch; + private final String targetBranch; + private final String repositoryOwner; + private final String repositoryName; + private final String pullRequestId; + private final String destinationRepositoryOwner; + private final String destinationRepositoryName; + private final String pullRequestTitle; + public static final String BITBUCKET_URL = "https://bitbucket.org/"; + + public BitbucketCause(String sourceBranch, + String targetBranch, + String repositoryOwner, + String repositoryName, + String pullRequestId, + String destinationRepositoryOwner, + String destinationRepositoryName, + String pullRequestTitle) { + this.sourceBranch = sourceBranch; + this.targetBranch = targetBranch; + this.repositoryOwner = repositoryOwner; + this.repositoryName = repositoryName; + this.pullRequestId = pullRequestId; + this.destinationRepositoryOwner = destinationRepositoryOwner; + this.destinationRepositoryName = destinationRepositoryName; + this.pullRequestTitle = pullRequestTitle; + } + + public String getSourceBranch() { + return sourceBranch; + } + public String getTargetBranch() { + return targetBranch; + } + + public String getRepositoryOwner() { + return repositoryOwner; + } + + public String getRepositoryName() { + return repositoryName; + } + + public String getPullRequestId() { + return pullRequestId; + } + + + public String getDestinationRepositoryOwner() { + return destinationRepositoryOwner; + } + + public String getDestinationRepositoryName() { + return destinationRepositoryName; + } + + public String getPullRequestTitle() { + return pullRequestTitle; + } + + @Override + public String getShortDescription() { + String description = "<a href=" + BITBUCKET_URL + this.getDestinationRepositoryOwner() + "/"; + description += this.getDestinationRepositoryName() + "/pull-request/" + this.getPullRequestId(); + description += ">#" + this.getPullRequestId() + " " + this.getPullRequestTitle() + "</a>"; + return description; + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java new file mode 100644 index 0000000..2f0a018 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java @@ -0,0 +1,63 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValue; +import hudson.model.AbstractProject; + +import java.util.Collection; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +public class BitbucketPullRequestsBuilder { + private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName()); + private AbstractProject<?, ?> project; + private BitbucketBuildTrigger trigger; + private BitbucketRepository repository; + private BitbucketBuilds builds; + + public static BitbucketPullRequestsBuilder getBuilder() { + return new BitbucketPullRequestsBuilder(); + } + + public void stop() { + // TODO? + } + + public void run() { + logger.info("Build Start."); + this.repository.init(); + Collection<BitbucketPullRequestResponseValue> targetPullRequests = this.repository.getTargetPullRequests(); + this.repository.postBuildStartCommentTo(targetPullRequests); + this.repository.addFutureBuildTasks(targetPullRequests); + } + + public BitbucketPullRequestsBuilder setupBuilder() { + if (this.project == null || this.trigger == null) { + throw new IllegalStateException(); + } + this.repository = new BitbucketRepository(this.trigger.getProjectPath(), this); + this.builds = new BitbucketBuilds(this.trigger, this.repository); + return this; + } + + public void setProject(AbstractProject<?, ?> project) { + this.project = project; + } + + public void setTrigger(BitbucketBuildTrigger trigger) { + this.trigger = trigger; + } + + public AbstractProject<?, ?> getProject() { + return this.project; + } + + public BitbucketBuildTrigger getTrigger() { + return this.trigger; + } + + public BitbucketBuilds getBuilds() { + return this.builds; + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java new file mode 100644 index 0000000..ec13f38 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java @@ -0,0 +1,119 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; + +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketApiClient; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestComment; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValue; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValueRepository; +import jenkins.model.Jenkins; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +public class BitbucketRepository { + private static final Logger logger = Logger.getLogger(BitbucketRepository.class.getName()); + public static final String BUILD_START_MARKER = "[BuildStart]"; + public static final String BUILD_FINISH_MARKER = "[BuildFinished]"; + public static final String BUILD_REQUEST_MARKER = "test this please"; + private String projectPath; + private BitbucketPullRequestsBuilder builder; + private BitbucketBuildTrigger trigger; + private BitbucketApiClient client; + + public BitbucketRepository(String projectPath, BitbucketPullRequestsBuilder builder) { + this.projectPath = projectPath; + this.builder = builder; + } + + public void init() { + trigger = this.builder.getTrigger(); + client = new BitbucketApiClient( + trigger.getUsername(), + trigger.getPassword(), + trigger.getRepositoryOwner(), + trigger.getRepositoryName()); + } + + public Collection<BitbucketPullRequestResponseValue> getTargetPullRequests() { + logger.info("Fetch PullRequests."); + List<BitbucketPullRequestResponseValue> pullRequests = client.getPullRequests(); + List<BitbucketPullRequestResponseValue> targetPullRequests = new ArrayList<BitbucketPullRequestResponseValue>(); + for(BitbucketPullRequestResponseValue pullRequest : pullRequests) { + if (isBuildTarget(pullRequest)) { + targetPullRequests.add(pullRequest); + } + } + return targetPullRequests; + } + + public void postBuildStartCommentTo(Collection<BitbucketPullRequestResponseValue> pullRequests) { + for(BitbucketPullRequestResponseValue pullRequest : pullRequests) { + String comment = BUILD_START_MARKER; + comment += " Build Triggered. Waiting to hear about " + pullRequest.getSource().getRepository().getFullName(); + this.client.postPullRequestComment(pullRequest.getId(), comment); + } + } + + public void addFutureBuildTasks(Collection<BitbucketPullRequestResponseValue> pullRequests) { + for(BitbucketPullRequestResponseValue pullRequest : pullRequests) { + BitbucketCause cause = new BitbucketCause( + pullRequest.getSource().getBranch().getName(), + pullRequest.getDestination().getBranch().getName(), + pullRequest.getSource().getRepository().getOwnerName(), + pullRequest.getSource().getRepository().getRepositoryName(), + pullRequest.getId(), + pullRequest.getDestination().getRepository().getOwnerName(), + pullRequest.getDestination().getRepository().getRepositoryName(), + pullRequest.getTitle()); + this.builder.getTrigger().startJob(cause); + } + } + + public void postFinishedComment(String pullRequestId, boolean success, String buildUrl) { + String comment = BUILD_FINISH_MARKER; + if (success) { + comment += " Test PASSed. Refer to this link for build results."; + } else { + comment += " Test FAILed. Refer to this link for build results."; + } + comment += buildUrl; + this.client.postPullRequestComment(pullRequestId, comment); + } + + private boolean isBuildTarget(BitbucketPullRequestResponseValue pullRequest) { + boolean shouldBuild = true; + if (pullRequest.getState() != null && pullRequest.getState().equals("OPEN")) { + BitbucketPullRequestResponseValueRepository destination = pullRequest.getDestination(); + String owner = destination.getRepository().getOwnerName(); + String repositoryName = destination.getRepository().getRepositoryName(); + String id = pullRequest.getId(); + List<BitbucketPullRequestComment> comments = client.getPullRequestComments(owner, repositoryName, id); + if (comments != null) { + Collections.sort(comments); + Collections.reverse(comments); + for(BitbucketPullRequestComment comment : comments) { + String content = comment.getContent(); + if (content == null || content.isEmpty()) { + continue; + } + content = content.toLowerCase(); + if (content.contains(BUILD_START_MARKER.toLowerCase())) { + shouldBuild = false; + break; + } + if (content.contains(BUILD_REQUEST_MARKER.toLowerCase())) { + shouldBuild = true; + break; + } + } + } + } + return shouldBuild; + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketApiClient.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketApiClient.java new file mode 100644 index 0000000..200b81e --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketApiClient.java @@ -0,0 +1,117 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.apache.commons.httpclient.*; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by nishio + */ +public class BitbucketApiClient { + private static final Logger logger = Logger.getLogger(BitbucketApiClient.class.getName()); + private static final String BITBUCKET_HOST = "bitbucket.org"; + private static final String V1_API_BASE_URL = "https://bitbucket.org/api/1.0/repositories/"; + private static final String V2_API_BASE_URL = "https://bitbucket.org/api/2.0/repositories/"; + private String owner; + private String repositoryName; + private Credentials credentials; + + public BitbucketApiClient(String username, String password, String owner, String repositoryName) { + this.credentials = new UsernamePasswordCredentials(username, password); + this.owner = owner; + this.repositoryName = repositoryName; + } + + public List<BitbucketPullRequestResponseValue> getPullRequests() { + String response = getRequest(V2_API_BASE_URL + this.owner + "/" + this.repositoryName + "/pullrequests/"); + try { + return parsePullRequestJson(response).getPrValues(); + } catch(Exception e) { + logger.log(Level.WARNING, "invalid pull request response.", e); + } + return null; + } + + public List<BitbucketPullRequestComment> getPullRequestComments(String commentOwnerName, String commentRepositoryName, String pullRequestId) { + String response = getRequest( + V1_API_BASE_URL + commentOwnerName + "/" + commentRepositoryName + "/pullrequests/" + pullRequestId + "/comments"); + try { + return parseCommentJson(response); + } catch(Exception e) { + logger.log(Level.WARNING, "invalid pull request response.", e); + } + return null; + } + + public void postPullRequestComment(String pullRequestId, String comment) { + String path = V1_API_BASE_URL + this.owner + "/" + this.repositoryName + "/pullrequests/" + pullRequestId + "/comments"; + try { + NameValuePair content = new NameValuePair("content", comment); + postRequest(path, new NameValuePair[]{ content }); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + private String getRequest(String path) { + HttpClient client = new HttpClient(); + client.getState().setCredentials(AuthScope.ANY, credentials); + GetMethod httpget = new GetMethod(path); + client.getParams().setAuthenticationPreemptive(true); + String response = null; + try { + client.executeMethod(httpget); + response = httpget.getResponseBodyAsString(); + } catch (HttpException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return response; + } + + private void postRequest(String path, NameValuePair[] params) throws UnsupportedEncodingException { + HttpClient client = new HttpClient(); + client.getState().setCredentials(AuthScope.ANY, credentials); + PostMethod httppost = new PostMethod(path); + httppost.setRequestBody(params); + client.getParams().setAuthenticationPreemptive(true); + try { + client.executeMethod(httppost); + String response = httppost.getResponseBodyAsString(); + logger.info("API Request Response: " + response); + } catch (HttpException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private BitbucketPullRequestResponse parsePullRequestJson(String response) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + BitbucketPullRequestResponse parsedResponse; + parsedResponse = mapper.readValue(response, BitbucketPullRequestResponse.class); + return parsedResponse; + } + + private List<BitbucketPullRequestComment> parseCommentJson(String response) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + List<BitbucketPullRequestComment> parsedResponse; + parsedResponse = mapper.readValue( + response, + new TypeReference<List<BitbucketPullRequestComment>>() { + }); + return parsedResponse; + } + +} + diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestComment.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestComment.java new file mode 100644 index 0000000..2e1e18e --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestComment.java @@ -0,0 +1,118 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Comparator; + +/** + * Created by nishio + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestComment implements Comparable<BitbucketPullRequestComment> { + private Boolean isEntityAuthor; + private Integer pullRequestId; + private String contentRendered; + private Boolean deleted; + private String UtcLastUpdated; + private Integer commentId; + private String content; + private String UtcCreatedOn; + private Boolean isSpam; + + @JsonProperty("is_entity_author") + public Boolean getIsEntityAuthor() { + return isEntityAuthor; + } + + @JsonProperty("is_entity_author") + public void setIsEntityAuthor(Boolean isEntityAuthor) { + this.isEntityAuthor = isEntityAuthor; + } + + @JsonProperty("pull_request_id") + public Integer getPullRequestId() { + return pullRequestId; + } + + @JsonProperty("pull_request_id") + public void setPullRequestId(Integer pullRequestId) { + this.pullRequestId = pullRequestId; + } + + @JsonProperty("content_rendered") + public String getContentRendered() { + return contentRendered; + } + + @JsonProperty("content_rendered") + public void setContentRendered(String contentRendered) { + this.contentRendered = contentRendered; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } + + @JsonProperty("utc_last_updated") + public String getUtcLastUpdated() { + return UtcLastUpdated; + } + + @JsonProperty("utc_last_updated") + public void setUtcLastUpdated(String utcLastUpdated) { + UtcLastUpdated = utcLastUpdated; + } + + @JsonProperty("comment_id") + public Integer getCommentId() { + return commentId; + } + + @JsonProperty("comment_id") + public void setCommentId(Integer commentId) { + this.commentId = commentId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @JsonProperty("utc_created_on") + public String getUtcCreatedOn() { + return UtcCreatedOn; + } + + @JsonProperty("utc_created_on") + public void setUtcCreatedOn(String utcCreatedOn) { + UtcCreatedOn = utcCreatedOn; + } + + @JsonProperty("is_spam") + public Boolean getIsSpam() { + return isSpam; + } + + @JsonProperty("is_spam") + public void setIsSpam(Boolean isSpam) { + this.isSpam = isSpam; + } + + public int compareTo(BitbucketPullRequestComment target) { + if (this.getCommentId() > target.getCommentId()) { + return 1; + } else if (this.getCommentId().equals(target.getCommentId())) { + return 0; + } else { + return -1; + } + } +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponse.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponse.java new file mode 100644 index 0000000..82e6009 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponse.java @@ -0,0 +1,58 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.List; + +/** + * Created by nishio + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestResponse { + private int pageLength; + private List<BitbucketPullRequestResponseValue> prValues; + private int page; + private int size; + + @JsonProperty("pagelen") + public int getPageLength() { + return pageLength; + } + + @JsonProperty("pagelen") + public void setPageLength(int pageLength) { + this.pageLength = pageLength; + } + + @JsonProperty("values") + public List<BitbucketPullRequestResponseValue> getPrValues() { + return prValues; + } + + @JsonProperty("values") + public void setPrValues(List<BitbucketPullRequestResponseValue> prValues) { + this.prValues = prValues; + } + + @JsonProperty("page") + public int getPage() { + return page; + } + + @JsonProperty("page") + public void setPage(int page) { + this.page = page; + } + + @JsonProperty("size") + public int getSize() { + return size; + } + + @JsonProperty("size") + public void setSize(int size) { + this.size = size; + } + +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValue.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValue.java new file mode 100644 index 0000000..e8be708 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValue.java @@ -0,0 +1,130 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Created by nishio + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestResponseValue { + private String description; + private Boolean closeSourceBranch; + private String title; + private BitbucketPullRequestResponseValueRepository destination; + private String reason; + private String closedBy; + private BitbucketPullRequestResponseValueRepository source; + private String state; + private String createdOn; + private String updatedOn; + private String mergeCommit; + private String id; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @JsonProperty("close_source_branch") + public Boolean getCloseSourceBranch() { + return closeSourceBranch; + } + + @JsonProperty("close_source_branch") + public void setCloseSourceBranch(Boolean closeSourceBranch) { + this.closeSourceBranch = closeSourceBranch; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public BitbucketPullRequestResponseValueRepository getDestination() { + return destination; + } + + public void setDestination(BitbucketPullRequestResponseValueRepository destination) { + this.destination = destination; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @JsonProperty("closed_by") + public String getClosedBy() { + return closedBy; + } + + @JsonProperty("closed_by") + public void setClosedBy(String closedBy) { + this.closedBy = closedBy; + } + + public BitbucketPullRequestResponseValueRepository getSource() { + return source; + } + + public void setSource(BitbucketPullRequestResponseValueRepository source) { + this.source = source; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + @JsonProperty("created_on") + public String getCreatedOn() { + return createdOn; + } + + @JsonProperty("created_on") + public void setCreatedOn(String createdOn) { + this.createdOn = createdOn; + } + + @JsonProperty("updated_on") + public String getUpdatedOn() { + return updatedOn; + } + + @JsonProperty("updated_on") + public void setUpdatedOn(String updatedOn) { + this.updatedOn = updatedOn; + } + + @JsonProperty("merge_commit") + public String getMergeCommit() { + return mergeCommit; + } + + @JsonProperty("merge_commit") + public void setMergeCommit(String mergeCommit) { + this.mergeCommit = mergeCommit; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepository.java new file mode 100644 index 0000000..76eeaf2 --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepository.java @@ -0,0 +1,35 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Created by nishio + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestResponseValueRepository { + private BitbucketPullRequestResponseValueRepositoryRepository repository; + private BitbucketPullRequestResponseValueRepositoryBranch branch; + + @JsonProperty("repository") + public BitbucketPullRequestResponseValueRepositoryRepository getRepository() { + return repository; + } + + @JsonProperty("repository") + public void setRepository(BitbucketPullRequestResponseValueRepositoryRepository repository) { + this.repository = repository; + } + + @JsonProperty("branch") + public BitbucketPullRequestResponseValueRepositoryBranch getBranch() { + return branch; + } + + @JsonProperty("branch") + public void setBranch(BitbucketPullRequestResponseValueRepositoryBranch branch) { + this.branch = branch; + } +} + + diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryBranch.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryBranch.java new file mode 100644 index 0000000..2fa2eee --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryBranch.java @@ -0,0 +1,16 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestResponseValueRepositoryBranch { + private String Name; + + public String getName() { + return Name; + } + + public void setName(String name) { + Name = name; + } +}
\ No newline at end of file diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryRepository.java new file mode 100644 index 0000000..d8ff67e --- /dev/null +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/BitbucketPullRequestResponseValueRepositoryRepository.java @@ -0,0 +1,43 @@ +package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BitbucketPullRequestResponseValueRepositoryRepository { + private String fullName; + private String name; + + @JsonProperty("full_name") + public String getFullName() { + return fullName; + } + + @JsonProperty("full_name") + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getOwnerName() { + if (this.fullName != null) { + return this.fullName.split("/")[0]; + } + return null; + } + + public String getRepositoryName() { + if (this.fullName != null) { + return this.fullName.split("/")[1]; + } + return null; + } +} + diff --git a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly new file mode 100644 index 0000000..964cc85 --- /dev/null +++ b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly @@ -0,0 +1,17 @@ +<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> + <f:entry title="Cron" field="cron"> + <f:textbox /> + </f:entry> + <f:entry title="Bitbucket BasicAuth Username" field="username"> + <f:textbox /> + </f:entry> + <f:entry title="Bitbucket BasicAuth Password" field="password"> + <f:password /> + </f:entry> + <f:entry title="RepositoryOwner" field="repositoryOwner"> + <f:textbox /> + </f:entry> + <f:entry title="RespositoryName" field="repositoryName"> + <f:textbox /> + </f:entry> +</j:jelly>
\ No newline at end of file diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly new file mode 100644 index 0000000..538998f --- /dev/null +++ b/src/main/resources/index.jelly @@ -0,0 +1,6 @@ +<!-- + This view is used to render the installed plugins page. +--> +<div> + This plugin is a sample to explain how to write a Jenkins plugin. +</div> |