From ef0656b1de4d78d0026b473717734e9e33f8c2d2 Mon Sep 17 00:00:00 2001 From: Steven Cooney Date: Wed, 5 Jun 2019 13:37:40 +0100 Subject: [PATCH] Add TeamCity Agent Add a TeamCity agent to which run after the VCS sources have been applied to trigger arcanist patch and pull in any changes from the specified Phabricator revision onto master and verify they build. --- .../phabricator/AgentBuildExtension.java | 31 ++++++++++-- .../teamcity/phabricator/ArcanistClient.java | 50 +++++++++++++++++++ .../phabricator/PhabricatorPluginConfig.java | 28 ++++++++++- 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/ArcanistClient.java diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/AgentBuildExtension.java b/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/AgentBuildExtension.java index 8a2a89c..b88e9f0 100644 --- a/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/AgentBuildExtension.java +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/AgentBuildExtension.java @@ -16,6 +16,7 @@ import uk.xlab.teamcity.phabricator.logging.PhabricatorAgentLogger; public class AgentBuildExtension extends AgentLifeCycleAdapter { + private static final String OUTPUT_PREFIX = "Phabricator Plugin - %s"; private PhabricatorAgentLogger agentLogLogger; private BuildProgressLogger buildLogger; private PhabricatorPluginConfig phabricatorConfig; @@ -57,12 +58,26 @@ public class AgentBuildExtension extends AgentLifeCycleAdapter { // everything is present and correct for us to continue if (!phabricatorConfig.isPluginSetup()) { agentLogLogger.info("Plugin incorrectly configured"); + phabricatorTriggeredBuild = false; return; } phabricatorTriggeredBuild = true; agentLogLogger.info("Plugin ready"); - buildLogger.message("Phabricator Plugin - Active"); + buildLogger.message(String.format(OUTPUT_PREFIX, "Active")); + + buildLogger.message(String.format(OUTPUT_PREFIX, String.format("%s: %s", Constants.PHABRICATOR_URL_SETTING, + phabricatorConfig.getPhabricatorURL().toString()))); + buildLogger.message(String.format(OUTPUT_PREFIX, String.format("%s: %s", + Constants.PHABRICATOR_ARCANIST_PATH_SETTING, phabricatorConfig.getPathToArcanist()))); + buildLogger.message(String.format(OUTPUT_PREFIX, + String.format("%s: %s", Constants.BUILD_ID, phabricatorConfig.getBuildId()))); + buildLogger.message(String.format(OUTPUT_PREFIX, + String.format("%s: %s", Constants.DIFF_ID, phabricatorConfig.getDiffId()))); + buildLogger.message(String.format(OUTPUT_PREFIX, String.format("%s: %s", Constants.HARBORMASTER_PHID, + phabricatorConfig.getPhabricatorURL().toString()))); + buildLogger.message(String.format(OUTPUT_PREFIX, + String.format("%s: %s", Constants.REVISION_ID, phabricatorConfig.getRevisionId()))); } @Override @@ -72,7 +87,17 @@ public class AgentBuildExtension extends AgentLifeCycleAdapter { return; } - buildLogger.message("PHAB: SOURCES HAVE UPDATED"); - agentLogLogger.info("PHAB: SOURCES HAVE UPDATED"); + buildLogger.message(String.format(OUTPUT_PREFIX, "Attempting arc patch")); + agentLogLogger.info("Attempting arc patch"); + + ArcanistClient arcanistClient = new ArcanistClient(phabricatorConfig.getPathToArcanist(), + runningBuild.getCheckoutDirectory().getPath(), phabricatorConfig.getPhabricatorURL().toString(), + phabricatorConfig.getConduitToken(), agentLogLogger); + + int patchCode = arcanistClient.patch(phabricatorConfig.getDiffId()); + + if (patchCode > 0) { + runningBuild.stopBuild("Patch failed to apply. Check the agent output log for patch failure detals."); + } } } diff --git a/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/ArcanistClient.java b/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/ArcanistClient.java new file mode 100644 index 0000000..5c25b66 --- /dev/null +++ b/Teamcity-Phabricator-Plugin/phabricator-plugin-agent/src/main/java/uk/xlab/teamcity/phabricator/ArcanistClient.java @@ -0,0 +1,50 @@ +package uk.xlab.teamcity.phabricator; + +import uk.xlab.teamcity.phabricator.logging.PhabricatorAgentLogger; + +public class ArcanistClient { + + private final String arcPath; + private final String workingDir; + private final String conduitAPI; + private final String token; + + private final PhabricatorAgentLogger agentLogLogger; + + public ArcanistClient( + final String pathToArcanist, + final String workingDirectory, + final String phabricatorURL, + final String conduitToken, + final PhabricatorAgentLogger logger + ) { + arcPath = pathToArcanist; + workingDir = workingDirectory; + conduitAPI = phabricatorURL; + token = conduitToken; + agentLogLogger = logger; + } + + public int patch(String diffId) { + try { + + Command commandToExecute = new CommandBuilder() + .setCommand(arcPath) + .setAction("patch") + .setWorkingDir(workingDir) + .setArg("--diff") + .setArg(diffId) + .setFlagWithValueEquals("--conduit-uri", conduitAPI) + .setFlagWithValueEquals("--conduit-token", token) + .build(); + return commandToExecute.executeAndWait(); + + } catch (IllegalArgumentException e) { + agentLogLogger.warn("Building command failed", e); + } catch (Exception e) { + agentLogLogger.warn("Patching error", e); + } + + return 1; + } +} 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 e80db73..91f4ad0 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 @@ -48,6 +48,15 @@ public class PhabricatorPluginConfig { * @param parameters */ public void setParameters(Map parameters) { + // Clear the class variables to avoid any lingering references + phabricatorUrl = null; + conduitToken = null; + pathToArcanist = null; + buildId = null; + diffId = null; + harbormasterPHID = null; + revisionId = null; + params = parameters; logger.info("Looking for parameters"); @@ -71,7 +80,8 @@ public class PhabricatorPluginConfig { conduitToken = params.get(Constants.PHABRICATOR_CONDUIT_TOKEN_SETTING); break; case Constants.PHABRICATOR_ARCANIST_PATH_SETTING: - logger.info(String.format("Found Phabricator Arcanist Path: %s", params.get(Constants.PHABRICATOR_ARCANIST_PATH_SETTING))); + logger.info(String.format("Found Phabricator Arcanist Path: %s", + params.get(Constants.PHABRICATOR_ARCANIST_PATH_SETTING))); pathToArcanist = params.get(Constants.PHABRICATOR_ARCANIST_PATH_SETTING); break; case Constants.BUILD_ID: @@ -116,10 +126,26 @@ public class PhabricatorPluginConfig { return conduitToken; } + public String getPathToArcanist() { + return pathToArcanist; + } + + public String getBuildId() { + return buildId; + } + + public String getDiffId() { + return diffId; + } + public String getHarbormasterPHID() { return harbormasterPHID; } + public String getRevisionId() { + return revisionId; + } + private URL parsePhabricatorURL(String input) throws MalformedURLException { URL inputURL = new URL(input); return inputURL;