From 57ff16d304d7a28394ed7393ee2f8891f715a740 Mon Sep 17 00:00:00 2001 From: Steven Cooney Date: Mon, 3 Jun 2019 11:21:53 +0100 Subject: [PATCH] Send Build Result to Harbormaster Once a build with the phabricator build feature configured is completed then the build status will be sent back to harbormaster. --- README.md | 15 +++++ .../phabricator-plugin-common/pom.xml | 6 ++ .../xlab/teamcity/phabricator/Constants.java | 5 +- .../phabricator/PhabricatorPluginConfig.java | 17 +++++ .../phabricator-plugin-server/pom.xml | 8 ++- .../teamcity/phabricator/BuildTracker.java | 62 ++++++++++++++++--- .../phabricatorBuildFeature.jsp | 6 +- 7 files changed, 107 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 1774b8b..229d7ce 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,21 @@ The teamcity plugin comprises of server and agent plugins for teamcity. #### Server The server plugin monitors builds with the phabricator feature enabled waiting for builds to finish and notify phabricator. +Once build is triggered from phabricator using **Harbomaster-Teamcity-Plugin** and the phabricator build feature is configured on the build configuration then the server plugin will wait and listen for the build to finish before reporting the result back to harbormaster to be displayed in phabricator. + +## Getting Started + +**Harbormaster-Teamcity-Plugin** +No building is needed for for the harbormaster plugin just dev away and copy the files into the `src/extensions` folder with your phabricator instance + +**Teamcity-Phabricator-Plugin** + +You will need to move in to the `Teamcity-Phabricator-Plugin/` folder: + +* To build the plugins (server and agent) just run: `mvn package` + +By default the teamcity plugin is equipped with teamcity-sdk-maven-plugin which allows for a local instance of teamcity with debugging capabilities. See their documentation for how to use: https://github.com/JetBrains/teamcity-sdk-maven-plugin + ## Useful Links * https://confluence.jetbrains.com/display/TCD10/Web+UI+Extensions diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/pom.xml b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/pom.xml index 5b1ac97..21a52e8 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/pom.xml +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/pom.xml @@ -16,6 +16,12 @@ ${teamcity-version} provided + + + org.apache.httpcomponents + httpclient + 4.5.8 + diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/Constants.java b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/Constants.java index aab23e8..97906e9 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/Constants.java +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/Constants.java @@ -5,9 +5,10 @@ public class Constants { public static final String PLUGIN_NAME = "phabricator"; public static final String PLUGIN_DISPLAY_NAME = "Phabricator Plugin"; - // Build Feature + // Build Feature Settings public static final String BUILD_FEATURE_TYPE = "phabricator-build-feature"; - public static final String PHABRICATOR_URL_SETTING = "phabricator_url_setting"; + public static final String PHABRICATOR_URL_SETTING = "plugin.phabricatorUrl"; + public static final String PHABRICATOR_CONDUIT_TOKEN_SETTING = "plugin.conduitToken"; // Build Config public static final String BRANCH_NAME = "env.PHAB_BRANCH_NAME"; diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/PhabricatorPluginConfig.java b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/PhabricatorPluginConfig.java index be8750b..0e1b3e6 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/PhabricatorPluginConfig.java +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-common/src/main/java/uk/xlab/teamcity/phabricator/PhabricatorPluginConfig.java @@ -20,6 +20,7 @@ public class PhabricatorPluginConfig { // Build Feature Variables private URL phabricatorUrl; + private String conduitToken; // Harbormaster Variables private String branchName; @@ -61,6 +62,10 @@ public class PhabricatorPluginConfig { logger.warn(String.format("Failed to parse phabricator URL: %s", params.get(Constants.PHABRICATOR_URL_SETTING)), e); } + case Constants.PHABRICATOR_CONDUIT_TOKEN_SETTING: + logger.info("Found Phabricator Conduit Token"); + conduitToken = params.get(Constants.PHABRICATOR_CONDUIT_TOKEN_SETTING); + case Constants.BRANCH_NAME: logger.info(String.format("Found branch name: %s", params.get(Constants.BRANCH_NAME))); branchName = params.get(Constants.BRANCH_NAME); @@ -91,6 +96,18 @@ public class PhabricatorPluginConfig { return false; } + public URL getPhabricatorURL() { + return phabricatorUrl; + } + + public String getConduitToken() { + return conduitToken; + } + + public String getHarbormasterPHID() { + return harbormasterPHID; + } + private URL parsePhabricatorURL(String input) throws MalformedURLException { URL inputURL = new URL(input); String scheme = inputURL.getProtocol(); diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/pom.xml b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/pom.xml index cac3d43..5c98bfb 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/pom.xml +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/pom.xml @@ -8,8 +8,8 @@ phabricator-plugin-server jar - + uk.xlab.teamcity.phabricator phabricator-plugin-common @@ -39,6 +39,12 @@ test + + + org.apache.httpcomponents + httpclient + 4.5.8 + diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/java/uk/xlab/teamcity/phabricator/BuildTracker.java b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/java/uk/xlab/teamcity/phabricator/BuildTracker.java index d7e297b..4d2e250 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/java/uk/xlab/teamcity/phabricator/BuildTracker.java +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/java/uk/xlab/teamcity/phabricator/BuildTracker.java @@ -1,12 +1,25 @@ package uk.xlab.teamcity.phabricator; +import java.net.URL; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import jetbrains.buildServer.messages.Status; import jetbrains.buildServer.serverSide.SBuildFeatureDescriptor; import jetbrains.buildServer.serverSide.SRunningBuild; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + /** * Class that is run in a thread once a build has started. If the build does not * have the phabricator build feature then the tread should come to an end @@ -49,11 +62,10 @@ public class BuildTracker implements Runnable { // Setup plugin specific configuration // TODO: implement AppConfig as PluginConfig phabricatorConfig.setParameters(params); - + // Now we have set all the parameters we need to check if // everything is present and correct for us to continue - if (!phabricatorConfig.isPluginSetup()) - { + if (!phabricatorConfig.isPluginSetup()) { logger.info("Plugin incorrectly configured"); return; } @@ -63,10 +75,46 @@ public class BuildTracker implements Runnable { } logger.info(String.format("Build %s finished: %s", build.getBuildNumber(), build.getBuildStatus())); - - if (build.getStatusDescriptor().isSuccessful()) { - logger.info("Successful Build"); - } + String harbormasterBuildStatus = parseTeamCityBuildStatus(build.getBuildStatus()); + NotifyHarbormaster(harbormasterBuildStatus); } } + + /** + * Compose and dispatch an API call to harbormaster to notify of the build + * status + */ + private void NotifyHarbormaster(String buildStatus) { + URL phabricatorURL = phabricatorConfig.getPhabricatorURL(); + + try (CloseableHttpClient client = HttpClients.createDefault()) { + String requestEndpoint = String.format("%s/api/harbormaster.sendmessage", phabricatorURL.toString()); + logger.info(String.format("Sending build status to: %s", requestEndpoint)); + HttpPost httpPost = new HttpPost(requestEndpoint); + + List params = new ArrayList(); + params.add(new BasicNameValuePair("api.token", phabricatorConfig.getConduitToken())); + params.add(new BasicNameValuePair("buildTargetPHID", phabricatorConfig.getHarbormasterPHID())); + params.add(new BasicNameValuePair("type", buildStatus)); + httpPost.setEntity(new UrlEncodedFormEntity(params)); + + try (CloseableHttpResponse response = client.execute(httpPost)) { + String responseText = EntityUtils.toString(response.getEntity()); + logger.info(String.format("Phabricator response: %s", responseText)); + } + + } catch (Exception exception) { + // Just catching any Exception because the request to Phabricator may have + // failed and we should investigate + logger.error("Request to harbormaster failed", exception); + } + } + + private String parseTeamCityBuildStatus(Status buildFinishedStatus){ + if (buildFinishedStatus.isSuccessful()) { + return "pass"; + } + + return "fail"; + } } diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/resources/buildServerResources/phabricatorBuildFeature.jsp b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/resources/buildServerResources/phabricatorBuildFeature.jsp index b4d78b2..e98c329 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/resources/buildServerResources/phabricatorBuildFeature.jsp +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-server/src/main/resources/buildServerResources/phabricatorBuildFeature.jsp @@ -3,7 +3,9 @@ - + + Report build status in real-time to your Phabricator instance. -Phabricator URL: +Phabricator URL: +Conduit Token: