Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -767,6 +767,7 @@ 'LiskIsolationTestDAOException' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAOException.php', 'LiskMigrationIterator' => 'infrastructure/storage/lisk/LiskMigrationIterator.php', 'LiskRawMigrationIterator' => 'infrastructure/storage/lisk/LiskRawMigrationIterator.php', + 'LocalCommandBuildStepImplementation' => 'applications/harbormaster/step/LocalCommandBuildStepImplementation.php', 'ManiphestActionMenuEventListener' => 'applications/maniphest/event/ManiphestActionMenuEventListener.php', 'ManiphestBatchEditController' => 'applications/maniphest/controller/ManiphestBatchEditController.php', 'ManiphestCapabilityBulkEdit' => 'applications/maniphest/capability/ManiphestCapabilityBulkEdit.php', @@ -2199,6 +2200,7 @@ 'SleepBuildStepImplementation' => 'applications/harbormaster/step/SleepBuildStepImplementation.php', 'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php', 'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php', + 'VariableBuildStepImplementation' => 'applications/harbormaster/step/VariableBuildStepImplementation.php', ), 'function' => array( @@ -3016,6 +3018,7 @@ 'LiskIsolationTestDAOException' => 'Exception', 'LiskMigrationIterator' => 'PhutilBufferedIterator', 'LiskRawMigrationIterator' => 'PhutilBufferedIterator', + 'LocalCommandBuildStepImplementation' => 'VariableBuildStepImplementation', 'ManiphestActionMenuEventListener' => 'PhabricatorEventListener', 'ManiphestBatchEditController' => 'ManiphestController', 'ManiphestCapabilityBulkEdit' => 'PhabricatorPolicyCapability', @@ -4662,5 +4665,6 @@ 'SleepBuildStepImplementation' => 'BuildStepImplementation', 'SlowvoteEmbedView' => 'AphrontView', 'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject', + 'VariableBuildStepImplementation' => 'BuildStepImplementation', ), )); Index: src/applications/harbormaster/controller/HarbormasterStepEditController.php =================================================================== --- src/applications/harbormaster/controller/HarbormasterStepEditController.php +++ src/applications/harbormaster/controller/HarbormasterStepEditController.php @@ -63,6 +63,11 @@ $form = id(new AphrontFormView()) ->setUser($viewer); + $instructions = $implementation->getSettingRemarkupInstructions(); + if ($instructions !== null) { + $form->appendRemarkupInstructions($instructions); + } + // We need to render out all of the fields for the settings that // the implementation has. foreach ($implementation->getSettingDefinitions() as $name => $opt) { Index: src/applications/harbormaster/step/BuildStepImplementation.php =================================================================== --- src/applications/harbormaster/step/BuildStepImplementation.php +++ src/applications/harbormaster/step/BuildStepImplementation.php @@ -85,4 +85,11 @@ public function getSettingDefinitions() { return array(); } + + /** + * Return relevant setting instructions as Remarkup. + */ + public function getSettingRemarkupInstructions() { + return null; + } } Index: src/applications/harbormaster/step/LocalCommandBuildStepImplementation.php =================================================================== --- /dev/null +++ src/applications/harbormaster/step/LocalCommandBuildStepImplementation.php @@ -0,0 +1,53 @@ +getSettings(); + + return pht('Run \'%s\' on the local web server.', $settings['command']); + } + + public function execute(HarbormasterBuild $build) { + $settings = $this->getSettings(); + + list($err, $stdout, $stderr) = exec_manual( + '%C', + $this->mergeVariables($build, $settings['command'])); + + if ($err) { + // TODO: Create a log entry with the command output. + $build->setBuildStatus(HarbormasterBuild::STATUS_FAILED); + } + } + + public function validateSettings() { + $settings = $this->getSettings(); + + if ($settings['command'] === null) { + return false; + } + if (!is_string($settings['command'])) { + return false; + } + return true; + } + + public function getSettingDefinitions() { + return array( + 'command' => array( + 'name' => 'Command', + 'description' => 'The command to execute on the local web server.', + 'type' => BuildStepImplementation::SETTING_TYPE_STRING)); + } + +} Index: src/applications/harbormaster/step/VariableBuildStepImplementation.php =================================================================== --- /dev/null +++ src/applications/harbormaster/step/VariableBuildStepImplementation.php @@ -0,0 +1,64 @@ + null, + 'commit' => null, + 'repository' => null, + 'vcs' => null, + 'uri' => null); + + $buildable = $build->getBuildable(); + $object = $buildable->getBuildableObject(); + + $repo = null; + if ($object instanceof DifferentialRevision) { + $results['revision'] = $object->getID(); + $repo = $object->getRepository(); + } else if ($object instanceof PhabricatorRepositoryCommit) { + $results['commit'] = $object->getCommitIdentifier(); + $repo = $object->getRepository(); + } + + $results['repository'] = $repo->getCallsign(); + $results['vcs'] = $repo->getVersionControlSystem(); + $results['uri'] = $repo->getPublicRemoteURI(); + + return $results; + } + + public function mergeVariables(HarbormasterBuild $build, $string) { + $variables = $this->retrieveVariablesFromBuild($build); + foreach ($variables as $name => $value) { + if ($value === null) { + $value = ''; + } + $string = str_replace('#{'.$name.'}', $value, $string); + } + return $string; + } + + public function getAvailableVariables() { + return array( + 'revision' => pht('The differential revision ID, if applicable.'), + 'commit' => pht('The commit identifier, if applicable.'), + 'repository' => pht('The callsign of the repository in Phabricator.'), + 'vcs' => pht('The version control system, either "svn", "hg" or "git".'), + 'uri' => pht('The URI to clone or checkout the repository from.')); + } + + public function getSettingRemarkupInstructions() { + $text = ''; + $text .= pht('The following variables are available: ')."\n"; + $text .= "\n"; + foreach ($this->getAvailableVariables() as $name => $desc) { + $text .= ' - `'.$name.'`: '.$desc."\n"; + } + $text .= "\n"; + $text .= "Use `#{name}` to merge a variable into a setting."; + return $text; + } + +}