1
0
Fork 0

Add PathToArc Parameter on Build Feature & Moving Logging Classes

Add a new field on the build feature dialog allowing the user to specify where arcanist command is located on the agent. We will need this information to execute the patching process upon which we will be building.

This commit also add Command and CommandBuilder into Common which we will be using to execute arcanist to apply the `arc patch` during the build so we can actually build the changes from the revision,

Also moved the three logging based files into a sub-folder causing many file updates of just an import.
This commit is contained in:
Steven Cooney 2019-06-05 11:52:25 +01:00
parent cefb59b73a
commit abfa8f840d
14 changed files with 150 additions and 6 deletions

View file

@ -12,6 +12,7 @@ import jetbrains.buildServer.agent.AgentLifeCycleListener;
import jetbrains.buildServer.agent.AgentRunningBuild; import jetbrains.buildServer.agent.AgentRunningBuild;
import jetbrains.buildServer.agent.BuildProgressLogger; import jetbrains.buildServer.agent.BuildProgressLogger;
import jetbrains.buildServer.util.EventDispatcher; import jetbrains.buildServer.util.EventDispatcher;
import uk.xlab.teamcity.phabricator.logging.PhabricatorAgentLogger;
public class AgentBuildExtension extends AgentLifeCycleAdapter { public class AgentBuildExtension extends AgentLifeCycleAdapter {

View file

@ -6,5 +6,5 @@
default-autowire="constructor"> default-autowire="constructor">
<bean class="uk.xlab.teamcity.phabricator.AgentBuildExtension" /> <bean class="uk.xlab.teamcity.phabricator.AgentBuildExtension" />
<bean class="uk.xlab.teamcity.phabricator.PhabricatorAgentLogger" /> <bean class="uk.xlab.teamcity.phabricator.logging.PhabricatorAgentLogger" />
</beans> </beans>

View file

@ -0,0 +1,47 @@
package uk.xlab.teamcity.phabricator;
import java.io.File;
import static uk.xlab.teamcity.phabricator.CommonUtils.*;
public class Command {
private final File workingDir;
private String[] fullCommand;
private ProcessBuilder processBuilder;
private Process process;
public Command(final String[] executableAndArguments, final String workingDirectory) {
workingDir = isNullOrEmpty(workingDirectory) ? null : new File(workingDirectory);
fullCommand = executableAndArguments;
// ProcessBuilder requires the full command to be an array to prepend the
// executable to the front;
processBuilder = new ProcessBuilder(executableAndArguments);
processBuilder.directory(workingDir);
processBuilder.inheritIO();
}
public int executeAndWait() throws Exception {
// May well fail and throw an exception but we will handle that in the agent
// plugin.
process = processBuilder.start();
return process.waitFor();
}
@Override
public String toString() {
if (fullCommand.length < 1) {
return "Command not setup";
}
String printableCommand = String.join(" ", fullCommand);
// The workingDir might not have been explicitly set
if (processBuilder.directory() == null) {
return String.format("Command: %s", printableCommand);
}
return String.format("WorkingDir: %s - Command: %s", processBuilder.directory().toString(), printableCommand);
}
}

View file

@ -0,0 +1,82 @@
package uk.xlab.teamcity.phabricator;
import static uk.xlab.teamcity.phabricator.CommonUtils.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CommandBuilder {
private String command = null;
private String action = null;
private String workingDir = null;
private List<String> args = new ArrayList<String>();
public CommandBuilder setWorkingDir(String workingDir) {
if (isNullOrEmpty(workingDir))
throw new IllegalArgumentException("Need to provide valid working directory");
else
this.workingDir = workingDir;
return this;
}
public CommandBuilder setCommand(String cmd) {
if (isNullOrEmpty(cmd))
throw new IllegalArgumentException("Need to provide a valid command");
else
this.command = cmd;
return this;
}
public CommandBuilder setAction(String action) {
if (isNullOrEmpty(action))
throw new IllegalArgumentException("Need to provide a valid action");
else
this.action = action;
return this;
}
public CommandBuilder setArg(String arg) {
if (isNullOrEmpty(arg))
throw new IllegalArgumentException("Need to provide a valid argument");
else
this.args.add(arg);
return this;
}
public CommandBuilder setFlagWithValueEquals(String key, String value) {
this.args.add(String.format("%s=%s", formatFlag(key), value));
return this;
}
public Command build() {
if (isNullOrEmpty(this.command)) {
throw new IllegalArgumentException("Must provide a command");
}
else {
this.args.add(0, this.command);
}
if (!isNullOrEmpty(this.action)) {
this.args.add(1, this.action);
}
return new Command(args.toArray(new String[args.size()]), this.workingDir);
}
private static String formatFlag(String flag) {
Pattern withFlag = Pattern.compile("^\\-\\-[a-zA-Z0-9-]+$");
Pattern singleWord = Pattern.compile("^\\w$");
Matcher m = withFlag.matcher(flag.trim());
Matcher m1 = singleWord.matcher(flag.trim());
if (m.matches()) {
return flag.trim();
} else if (m1.matches()) {
return String.format("--%s", flag);
} else {
throw new IllegalArgumentException(String.format("%s is not a valid flag", flag));
}
}
}

View file

@ -9,6 +9,7 @@ public class Constants {
public static final String BUILD_FEATURE_TYPE = "phabricator-build-feature"; public static final String BUILD_FEATURE_TYPE = "phabricator-build-feature";
public static final String PHABRICATOR_URL_SETTING = "plugin.phabricatorUrl"; public static final String PHABRICATOR_URL_SETTING = "plugin.phabricatorUrl";
public static final String PHABRICATOR_CONDUIT_TOKEN_SETTING = "plugin.conduitToken"; public static final String PHABRICATOR_CONDUIT_TOKEN_SETTING = "plugin.conduitToken";
public static final String PHABRICATOR_ARCANIST_PATH_SETTING = "plugin.pathToArc";
// Build Config // Build Config
public static final String BUILD_ID = "phabricator.BUILD_ID"; public static final String BUILD_ID = "phabricator.BUILD_ID";

View file

@ -3,6 +3,9 @@ package uk.xlab.teamcity.phabricator;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import uk.xlab.teamcity.phabricator.logging.PhabricatorPluginLogger;
import static uk.xlab.teamcity.phabricator.CommonUtils.*; import static uk.xlab.teamcity.phabricator.CommonUtils.*;
/** /**
@ -21,6 +24,7 @@ public class PhabricatorPluginConfig {
// Build Feature Variables // Build Feature Variables
private URL phabricatorUrl; private URL phabricatorUrl;
private String conduitToken; private String conduitToken;
private String pathToArcanist;
// Harbormaster Variables // Harbormaster Variables
private String buildId; private String buildId;
@ -66,6 +70,10 @@ public class PhabricatorPluginConfig {
logger.info("Found Phabricator Conduit Token"); logger.info("Found Phabricator Conduit Token");
conduitToken = params.get(Constants.PHABRICATOR_CONDUIT_TOKEN_SETTING); conduitToken = params.get(Constants.PHABRICATOR_CONDUIT_TOKEN_SETTING);
break; break;
case 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: case Constants.BUILD_ID:
logger.info(String.format("Found build id: %s", params.get(Constants.BUILD_ID))); logger.info(String.format("Found build id: %s", params.get(Constants.BUILD_ID)));
buildId = params.get(Constants.BUILD_ID); buildId = params.get(Constants.BUILD_ID);
@ -92,7 +100,7 @@ public class PhabricatorPluginConfig {
} }
public boolean isPluginSetup() { public boolean isPluginSetup() {
if (!isNull(phabricatorUrl) && !isNullOrEmpty(buildId) && !isNullOrEmpty(diffId) if (!isNull(phabricatorUrl) && !isNull(pathToArcanist) && !isNullOrEmpty(buildId) && !isNullOrEmpty(diffId)
&& !isNullOrEmpty(harbormasterPHID) && !isNullOrEmpty(revisionId)) { && !isNullOrEmpty(harbormasterPHID) && !isNullOrEmpty(revisionId)) {
return true; return true;
} }

View file

@ -1,4 +1,4 @@
package uk.xlab.teamcity.phabricator; package uk.xlab.teamcity.phabricator.logging;
import jetbrains.buildServer.log.Loggers; import jetbrains.buildServer.log.Loggers;

View file

@ -1,4 +1,4 @@
package uk.xlab.teamcity.phabricator; package uk.xlab.teamcity.phabricator.logging;
public interface PhabricatorPluginLogger { public interface PhabricatorPluginLogger {

View file

@ -1,4 +1,4 @@
package uk.xlab.teamcity.phabricator; package uk.xlab.teamcity.phabricator.logging;
import jetbrains.buildServer.log.Loggers; import jetbrains.buildServer.log.Loggers;

View file

@ -10,6 +10,7 @@ import java.util.Map;
import jetbrains.buildServer.messages.Status; import jetbrains.buildServer.messages.Status;
import jetbrains.buildServer.serverSide.SBuildFeatureDescriptor; import jetbrains.buildServer.serverSide.SBuildFeatureDescriptor;
import jetbrains.buildServer.serverSide.SRunningBuild; import jetbrains.buildServer.serverSide.SRunningBuild;
import uk.xlab.teamcity.phabricator.logging.PhabricatorServerLogger;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;

View file

@ -6,6 +6,7 @@ import jetbrains.buildServer.serverSide.BuildServerAdapter;
import jetbrains.buildServer.serverSide.BuildServerListener; import jetbrains.buildServer.serverSide.BuildServerListener;
import jetbrains.buildServer.serverSide.SRunningBuild; import jetbrains.buildServer.serverSide.SRunningBuild;
import jetbrains.buildServer.util.EventDispatcher; import jetbrains.buildServer.util.EventDispatcher;
import uk.xlab.teamcity.phabricator.logging.PhabricatorServerLogger;
/** /**
* Listen for builds been started and track their progress with BuildTracker * Listen for builds been started and track their progress with BuildTracker

View file

@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull;
import jetbrains.buildServer.serverSide.BuildFeature; import jetbrains.buildServer.serverSide.BuildFeature;
import jetbrains.buildServer.web.openapi.PluginDescriptor; import jetbrains.buildServer.web.openapi.PluginDescriptor;
import uk.xlab.teamcity.phabricator.logging.PhabricatorServerLogger;
public class PhabricatorPluginBuildFeature extends BuildFeature { public class PhabricatorPluginBuildFeature extends BuildFeature {

View file

@ -5,7 +5,7 @@
default-autowire="constructor"> default-autowire="constructor">
<bean class="uk.xlab.teamcity.phabricator.PhabricatorPluginBuildFeature" /> <bean class="uk.xlab.teamcity.phabricator.PhabricatorPluginBuildFeature" />
<bean class="uk.xlab.teamcity.phabricator.PhabricatorServerLogger" />
<bean class="uk.xlab.teamcity.phabricator.PhabricatorBuildServerAdapter" /> <bean class="uk.xlab.teamcity.phabricator.PhabricatorBuildServerAdapter" />
<bean class="uk.xlab.teamcity.phabricator.PhabricatorBuildStartContextProcessor" /> <bean class="uk.xlab.teamcity.phabricator.PhabricatorBuildStartContextProcessor" />
<bean class="uk.xlab.teamcity.phabricator.logging.PhabricatorServerLogger" />
</beans> </beans>

View file

@ -5,7 +5,9 @@
<c:set var="phabricatorUrl" value="${propertiesBean.properties['plugin.phabricatorUrl']}" /> <c:set var="phabricatorUrl" value="${propertiesBean.properties['plugin.phabricatorUrl']}" />
<c:set var="conduitToken" value="${propertiesBean.properties['plugin.conduitToken']}" /> <c:set var="conduitToken" value="${propertiesBean.properties['plugin.conduitToken']}" />
<c:set var="pathToArc" value="${propertiesBean.properties['plugin.pathToArc']}" />
<tr><td colspan="2">Report build status in real-time to your Phabricator instance.</td></tr> <tr><td colspan="2">Report build status in real-time to your Phabricator instance.</td></tr>
<tr><th>Phabricator URL:</th><td><props:textProperty name="plugin.phabricatorUrl"/></td></tr> <tr><th>Phabricator URL:</th><td><props:textProperty name="plugin.phabricatorUrl"/></td></tr>
<tr><th>Conduit Token:</th><td><props:passwordProperty name="plugin.conduitToken" size="54"/></td></tr> <tr><th>Conduit Token:</th><td><props:passwordProperty name="plugin.conduitToken" size="54"/></td></tr>
<tr><th>Path To Arcanist:</th><td><props:textProperty name="plugin.pathToArc"/></td></tr>