Page MenuHomePhabricator

D7510.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -26,6 +26,7 @@
'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php',
'ArcanistBritishTestCase' => 'configuration/__tests__/ArcanistBritishTestCase.php',
'ArcanistBrowseWorkflow' => 'workflow/ArcanistBrowseWorkflow.php',
+ 'ArcanistBuildAgentWorkflow' => 'workflow/ArcanistBuildAgentWorkflow.php',
'ArcanistBundle' => 'parser/ArcanistBundle.php',
'ArcanistBundleTestCase' => 'parser/__tests__/ArcanistBundleTestCase.php',
'ArcanistCSSLintLinter' => 'lint/linter/ArcanistCSSLintLinter.php',
@@ -167,6 +168,7 @@
'ArcanistXHPASTLinter' => 'lint/linter/ArcanistXHPASTLinter.php',
'ArcanistXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistXHPASTLinterTestCase.php',
'ArcanistXUnitTestResultParser' => 'unit/engine/ArcanistXUnitTestResultParser.php',
+ 'BuildStepImplementation' => 'build/BuildStepImplementation.php',
'CSharpToolsTestEngine' => 'unit/engine/CSharpToolsTestEngine.php',
'ComprehensiveLintEngine' => 'lint/engine/ComprehensiveLintEngine.php',
'ExampleLintEngine' => 'lint/engine/ExampleLintEngine.php',
@@ -180,6 +182,7 @@
'PhutilUnitTestEngine' => 'unit/engine/PhutilUnitTestEngine.php',
'PhutilUnitTestEngineTestCase' => 'unit/engine/__tests__/PhutilUnitTestEngineTestCase.php',
'PytestTestEngine' => 'unit/engine/PytestTestEngine.php',
+ 'SleepBuildStepImplementation' => 'build/SleepBuildStepImplementation.php',
'UnitTestableArcanistLintEngine' => 'lint/engine/UnitTestableArcanistLintEngine.php',
'XUnitTestEngine' => 'unit/engine/XUnitTestEngine.php',
'XUnitTestResultParserTestCase' => 'unit/engine/__tests__/XUnitTestResultParserTestCase.php',
@@ -202,6 +205,7 @@
'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow',
'ArcanistBritishTestCase' => 'ArcanistTestCase',
'ArcanistBrowseWorkflow' => 'ArcanistBaseWorkflow',
+ 'ArcanistBuildAgentWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistBundleTestCase' => 'ArcanistTestCase',
'ArcanistCSSLintLinter' => 'ArcanistExternalLinter',
'ArcanistCSSLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
@@ -323,6 +327,7 @@
'PhutilUnitTestEngine' => 'ArcanistBaseUnitTestEngine',
'PhutilUnitTestEngineTestCase' => 'ArcanistTestCase',
'PytestTestEngine' => 'ArcanistBaseUnitTestEngine',
+ 'SleepBuildStepImplementation' => 'BuildStepImplementation',
'UnitTestableArcanistLintEngine' => 'ArcanistLintEngine',
'XUnitTestEngine' => 'ArcanistBaseUnitTestEngine',
'XUnitTestResultParserTestCase' => 'ArcanistTestCase',
diff --git a/src/build/BuildStepImplementation.php b/src/build/BuildStepImplementation.php
new file mode 100644
--- /dev/null
+++ b/src/build/BuildStepImplementation.php
@@ -0,0 +1,88 @@
+<?php
+
+abstract class BuildStepImplementation {
+
+ private $settings;
+
+ const SETTING_TYPE_STRING = 'string';
+ const SETTING_TYPE_INTEGER = 'integer';
+ const SETTING_TYPE_BOOLEAN = 'boolean';
+
+ public static function getImplementations() {
+ $symbols = id(new PhutilSymbolLoader())
+ ->setAncestorClass("BuildStepImplementation")
+ ->setConcreteOnly(true)
+ ->selectAndLoadSymbols();
+ return ipull($symbols, 'name');
+ }
+
+ /**
+ * The name of the implementation.
+ */
+ abstract public function getName();
+
+ /**
+ * The generic description of the implementation.
+ */
+ public function getGenericDescription() {
+ return '';
+ }
+
+ /**
+ * The description of the implementation, based on the current settings.
+ */
+ public function getDescription() {
+ return '';
+ }
+
+ /**
+ * Run the build step against the specified build.
+ */
+ abstract public function execute(RemoteHarbormasterBuild $build);
+
+ /**
+ * Gets the settings for this build step.
+ */
+ public function getSettings() {
+ return $this->settings;
+ }
+
+ /**
+ * Validate the current settings of this build step.
+ */
+ public function validate() {
+ return true;
+ }
+
+ /**
+ * Loads the settings for this build step implementation from the build step.
+ */
+ public final function loadSettings(array $details) {
+ $this->settings = array();
+ $this->validateSettingDefinitions();
+ foreach ($this->getSettingDefinitions() as $name => $opt) {
+ $this->settings[$name] = idx($details, $name, null);
+ }
+ return $this->settings;
+ }
+
+ /**
+ * Validates that the setting definitions for this implementation are valid.
+ */
+ public final function validateSettingDefinitions() {
+ foreach ($this->getSettingDefinitions() as $name => $opt) {
+ if (!isset($opt['type'])) {
+ throw new Exception(
+ 'Setting definition \''.$name.
+ '\' is missing type requirement.');
+ }
+ }
+ }
+
+ /**
+ * Return an array of settings for this step implementation.
+ */
+ public function getSettingDefinitions() {
+ return array();
+ }
+}
diff --git a/src/build/RemoteHarbormasterBuild.php b/src/build/RemoteHarbormasterBuild.php
new file mode 100644
--- /dev/null
+++ b/src/build/RemoteHarbormasterBuild.php
@@ -0,0 +1,5 @@
+<?php
+
+final class RemoteHarbormasterBuild {
+
+}
diff --git a/src/build/SleepBuildStepImplementation.php b/src/build/SleepBuildStepImplementation.php
new file mode 100644
--- /dev/null
+++ b/src/build/SleepBuildStepImplementation.php
@@ -0,0 +1,45 @@
+<?php
+
+final class SleepBuildStepImplementation extends BuildStepImplementation {
+
+ public function getName() {
+ return pht('Sleep');
+ }
+
+ public function getGenericDescription() {
+ return pht('Sleep for a specified number of seconds.');
+ }
+
+ public function getDescription() {
+ $settings = $this->getSettings();
+
+ return pht('Sleep for %s seconds.', $settings['seconds']);
+ }
+
+ public function execute(RemoteHarbormasterBuild $build) {
+ $settings = $this->getSettings();
+
+ sleep($settings['seconds']);
+ }
+
+ public function validateSettings() {
+ $settings = $this->getSettings();
+
+ if ($settings['seconds'] === null) {
+ return false;
+ }
+ if (!is_int($settings['seconds'])) {
+ return false;
+ }
+ return true;
+ }
+
+ public function getSettingDefinitions() {
+ return array(
+ 'seconds' => array(
+ 'name' => 'Seconds',
+ 'description' => 'The number of seconds to sleep for.',
+ 'type' => BuildStepImplementation::SETTING_TYPE_INTEGER));
+ }
+
+}
diff --git a/src/workflow/ArcanistBuildAgentWorkflow.php b/src/workflow/ArcanistBuildAgentWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/workflow/ArcanistBuildAgentWorkflow.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Runs a harbormaster build agent on the local machine
+ * @group workflow
+ */
+
+final class ArcanistBuildAgentWorkflow extends ArcanistBaseWorkflow {
+
+ public function getWorkflowName() {
+ return 'agent';
+ }
+
+ public function requiresConduit() {
+ return true;
+ }
+
+ public function requiresAuthentication() {
+ return true;
+ }
+
+ public function getCommandSynopses() {
+ return phutil_console_format(<<<EOTEXT
+ **agent** [__options__]
+EOTEXT
+ );
+ }
+
+ public function getCommandHelp() {
+ return phutil_console_format(<<<EOTEXT
+ Supports: http, https
+ Runs a Harbormaster agent on the current machine. You must
+ explicitly provide the Conduit URI for this command.
+EOTEXT
+ );
+ }
+
+ public function getArguments() {
+ return array(
+ 'category' => array(
+ 'short' => 'c',
+ 'param' => 'category',
+ 'help' => "Specify the category of the build agent.",
+ )
+ );
+ }
+
+ public function run() {
+ $console = PhutilConsole::getConsole();
+ $console->writeOut("Starting build agent...\n");
+
+ // Pool for agent instructions.
+ $conduit = $this->getConduit();
+ while (true) {
+ $item = $conduit->callMethodSynchronous('agent.nextbuild', array());
+ if ($item["exists"]) {
+ $steps = $item["steps"];
+
+ // $steps is an array like so:
+ // array(
+ // array(
+ // "class" => "SleepBuildStepImplementation",
+ // "details" => "{\"seconds\":5}"),
+ // array(
+ // "class" => "SleepBuildStepImplementation",
+ // "details" => "{\"seconds\":15}"))
+ // TODO: Do something with this.
+ } else {
+ $console->writeOut("> No build to pick up. \n");
+ sleep(15);
+ }
+ }
+
+ }
+}
+

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/53/t7/z54z3uxqeivdowu3
Default Alt Text
D7510.diff (8 KB)

Event Timeline