diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..48bf230e --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1 @@ +buildPlugin() \ No newline at end of file diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml new file mode 100644 index 00000000..f4dbf542 --- /dev/null +++ b/findbugs-exclude.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/pom.xml b/pom.xml index 53ff98b1..32571ba1 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ bitbucket - 1.1.6-SNAPSHOT + 1.1.9-SNAPSHOT hpi Jenkins Bitbucket Plugin integrate Jenkins with BitBucket. @@ -66,6 +66,7 @@ org.codehaus.mojo findbugs-maven-plugin + true findbugs-exclude.xml @@ -150,4 +151,4 @@ - \ No newline at end of file + diff --git a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketHookReceiver.java b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketHookReceiver.java index 85990fe1..64e22530 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketHookReceiver.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketHookReceiver.java @@ -53,7 +53,7 @@ public void doIndex(StaplerRequest req) throws IOException { payloadProcessor.processPayload(payload, req); } else { - LOGGER.log(Level.WARNING, "The Jenkins job cannot be triggered. You might no have configured correctly the WebHook on BitBucket with the last slash `http:///bitbucket-hook/`"); + LOGGER.log(Level.WARNING, "The Jenkins job cannot be triggered. You might not have configured correctly the WebHook on BitBucket with the last slash `http:///bitbucket-hook/` or a 'Test connection' invocation of the hook was triggered."); } } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java index d8add285..45657684 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java @@ -88,6 +88,11 @@ private boolean match(SCM scm, URIish url) { if (scm instanceof GitSCM) { for (RemoteConfig remoteConfig : ((GitSCM) scm).getRepositories()) { for (URIish urIish : remoteConfig.getURIs()) { + // needed cause the ssh and https URI differs in Bitbucket Server. + if(urIish.getPath().startsWith("/scm")){ + urIish = urIish.setPath(urIish.getPath().substring(4)); + } + LOGGER.log(Level.FINE, "Trying to match {0} ", urIish.toString() + "<-->" + url.toString()); if (GitStatus.looselyMatches(urIish, url)) { return true; } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessor.java b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessor.java index cf9f4a36..2c785958 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessor.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessor.java @@ -1,5 +1,7 @@ package com.cloudbees.jenkins.plugins; +import java.net.MalformedURLException; +import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,6 +27,11 @@ public void processPayload(JSONObject payload, HttpServletRequest request) { LOGGER.log(Level.INFO, "Processing new Webhooks payload"); processWebhookPayload(payload); } + } else if (payload.has("actor") && payload.has("repository")) { + if ("repo:push".equals(request.getHeader("x-event-key"))) { + LOGGER.log(Level.INFO, "Processing new Webhooks payload"); + processWebhookPayloadBitBucketServer(payload); + } } else { LOGGER.log(Level.INFO, "Processing old POST service payload"); processPostServicePayload(payload); @@ -52,6 +59,29 @@ private void processWebhookPayload(JSONObject payload) { } + /** + * Payload processor for BitBucket server. The plugin Post Webhooks for Bitbucket + * https://marketplace.atlassian.com/plugins/nl.topicus.bitbucket.bitbucket-webhooks/server/overview + * should be installed and configured + * + * @param payload + */ + private void processWebhookPayloadBitBucketServer(JSONObject payload) { + JSONObject repo = payload.getJSONObject("repository"); + String user = payload.getJSONObject("actor").getString("username"); + String url = ""; + if (repo.getJSONObject("links").getJSONArray("self").size() != 0) { + try { + URL pushHref = new URL(repo.getJSONObject("links").getJSONArray("self").getJSONObject(0).getString("href")); + url = pushHref.toString().replaceFirst(new String("projects.*"), new String(repo.getString("fullName").toLowerCase())); + String scm = repo.has("scmId") ? repo.getString("scmId") : "git"; + probe.triggerMatchingJobs(user, url, scm, payload.toString()); + } catch (MalformedURLException e) { + LOGGER.log(Level.WARNING, String.format("URL %s is malformed", url), e); + } + } + } + /* { "canon_url": "https://bitbucket.org", diff --git a/src/test/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessorTest.java b/src/test/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessorTest.java index af4f4d5d..5e289ff9 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessorTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/BitbucketPayloadProcessorTest.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest; +import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.junit.Before; @@ -60,6 +61,32 @@ public void testProcessWebhookPayload() { verify(probe).triggerMatchingJobs(user, url, "hg", hgLoad.toString()); } + @Test + public void processWebhookPayloadBitBucketServer() { + when(request.getHeader("user-agent")).thenReturn("Apache-HttpClient/4.5.1 (Java/1.8.0_102)"); + when(request.getHeader("x-event-key")).thenReturn("repo:push"); + + String user = "test_user"; + String url = "https://bitbucket.org/ce/test_repo"; + + JSONObject href = new JSONObject(); + href.element("href", "https://bitbucket.org/projects/CE/repos/test_repo/browse"); + + // Set actor and repository so that payload processor will parse as Bitbucket Server Post Webhook payload + JSONObject payload = new JSONObject() + .element("actor", new JSONObject() + .element("username", user)) + .element("repository", new JSONObject() + .element("links", new JSONObject() + .element("self", new JSONArray() + .element(href))) + .element("fullName", "CE/test_repo")); + + payloadProcessor.processPayload(payload, request); + + verify(probe).triggerMatchingJobs(user, url, "git", payload.toString()); + } + @Test public void testProcessPostServicePayload() { // Ensure header isn't set so that payload processor will parse as old POST service payload