@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Document how to use `harbormaster.sendmessage` to report lint and unit results

Summary: Fixes T7419. This doesn't really do anything, just adds documentation.

Test Plan:
- Read the documentation:

{F688899}

- Created a build plan which makes an HTTP request to `example.com` and waits for a result.
- Ran that build plan manually.
- Called `harbormaster.sendmessage` manually with the example lint/unit values to provide a result.
- Saw the results report correctly and the message ("fail") process as expected:

{F688902}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T7419

Differential Revision: https://secure.phabricator.com/D13789

+364 -29
+2
src/__phutil_library_map__.php
··· 990 990 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php', 991 991 'HarbormasterManagementUpdateWorkflow' => 'applications/harbormaster/management/HarbormasterManagementUpdateWorkflow.php', 992 992 'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php', 993 + 'HarbormasterMessageType' => 'applications/harbormaster/engine/HarbormasterMessageType.php', 993 994 'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php', 994 995 'HarbormasterPlanController' => 'applications/harbormaster/controller/HarbormasterPlanController.php', 995 996 'HarbormasterPlanDisableController' => 'applications/harbormaster/controller/HarbormasterPlanDisableController.php', ··· 4702 4703 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow', 4703 4704 'HarbormasterManagementUpdateWorkflow' => 'HarbormasterManagementWorkflow', 4704 4705 'HarbormasterManagementWorkflow' => 'PhabricatorManagementWorkflow', 4706 + 'HarbormasterMessageType' => 'Phobject', 4705 4707 'HarbormasterObject' => 'HarbormasterDAO', 4706 4708 'HarbormasterPlanController' => 'HarbormasterController', 4707 4709 'HarbormasterPlanDisableController' => 'HarbormasterPlanController',
+25 -2
src/applications/conduit/method/ConduitAPIMethod.php
··· 1 1 <?php 2 2 3 3 /** 4 - * @task status Method Status 5 - * @task pager Paging Results 4 + * @task info Method Information 5 + * @task status Method Status 6 + * @task pager Paging Results 6 7 */ 7 8 abstract class ConduitAPIMethod 8 9 extends Phobject 9 10 implements PhabricatorPolicyInterface { 10 11 12 + 11 13 const METHOD_STATUS_STABLE = 'stable'; 12 14 const METHOD_STATUS_UNSTABLE = 'unstable'; 13 15 const METHOD_STATUS_DEPRECATED = 'deprecated'; 14 16 17 + 18 + /** 19 + * Get a short, human-readable text summary of the method. 20 + * 21 + * @return string Short summary of method. 22 + * @task info 23 + */ 24 + public function getMethodSummary() { 25 + return $this->getMethodDescription(); 26 + } 27 + 28 + 29 + /** 30 + * Get a detailed description of the method. 31 + * 32 + * This method should return remarkup. 33 + * 34 + * @return string Detailed description of the method. 35 + * @task info 36 + */ 15 37 abstract public function getMethodDescription(); 38 + 16 39 abstract protected function defineParamTypes(); 17 40 abstract protected function defineReturnType(); 18 41
+1 -1
src/applications/conduit/query/PhabricatorConduitSearchEngine.php
··· 174 174 $item = id(new PHUIObjectItemView()) 175 175 ->setHeader($method_name) 176 176 ->setHref($this->getApplicationURI('method/'.$method_name.'/')) 177 - ->addAttribute($method->getMethodDescription()); 177 + ->addAttribute($method->getMethodSummary()); 178 178 179 179 switch ($method->getMethodStatus()) { 180 180 case ConduitAPIMethod::METHOD_STATUS_STABLE:
+191 -5
src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php
··· 7 7 return 'harbormaster.sendmessage'; 8 8 } 9 9 10 + public function getMethodSummary() { 11 + return pht( 12 + 'Send a message about the status of a build target to Harbormaster, '. 13 + 'notifying the application of build results in an external system.'); 14 + } 15 + 10 16 public function getMethodDescription() { 17 + $messages = HarbormasterMessageType::getAllMessages(); 18 + 19 + $head_type = pht('Constant'); 20 + $head_desc = pht('Description'); 21 + $head_key = pht('Key'); 22 + $head_type = pht('Type'); 23 + $head_name = pht('Name'); 24 + 25 + $rows = array(); 26 + $rows[] = "| {$head_type} | {$head_desc} |"; 27 + $rows[] = '|--------------|--------------|'; 28 + foreach ($messages as $message) { 29 + $description = HarbormasterMessageType::getMessageDescription($message); 30 + $rows[] = "| `{$message}` | {$description} |"; 31 + } 32 + $message_table = implode("\n", $rows); 33 + 34 + $rows = array(); 35 + $rows[] = "| {$head_key} | {$head_type} | {$head_desc} |"; 36 + $rows[] = '|-------------|--------------|--------------|'; 37 + $unit_spec = HarbormasterBuildUnitMessage::getParameterSpec(); 38 + foreach ($unit_spec as $key => $parameter) { 39 + $type = idx($parameter, 'type'); 40 + $type = str_replace('|', pht(' or '), $type); 41 + $description = idx($parameter, 'description'); 42 + $rows[] = "| `{$key}` | //{$type}// | {$description} |"; 43 + } 44 + $unit_table = implode("\n", $rows); 45 + 46 + $rows = array(); 47 + $rows[] = "| {$head_key} | {$head_name} | {$head_desc} |"; 48 + $rows[] = '|-------------|--------------|--------------|'; 49 + $results = ArcanistUnitTestResult::getAllResultCodes(); 50 + foreach ($results as $result_code) { 51 + $name = ArcanistUnitTestResult::getResultCodeName($result_code); 52 + $description = ArcanistUnitTestResult::getResultCodeDescription( 53 + $result_code); 54 + $rows[] = "| `{$result_code}` | **{$name}** | {$description} |"; 55 + } 56 + $result_table = implode("\n", $rows); 57 + 58 + $rows = array(); 59 + $rows[] = "| {$head_key} | {$head_type} | {$head_desc} |"; 60 + $rows[] = '|-------------|--------------|--------------|'; 61 + $lint_spec = HarbormasterBuildLintMessage::getParameterSpec(); 62 + foreach ($lint_spec as $key => $parameter) { 63 + $type = idx($parameter, 'type'); 64 + $type = str_replace('|', pht(' or '), $type); 65 + $description = idx($parameter, 'description'); 66 + $rows[] = "| `{$key}` | //{$type}// | {$description} |"; 67 + } 68 + $lint_table = implode("\n", $rows); 69 + 70 + $rows = array(); 71 + $rows[] = "| {$head_key} | {$head_name} |"; 72 + $rows[] = '|-------------|--------------|'; 73 + $severities = ArcanistLintSeverity::getLintSeverities(); 74 + foreach ($severities as $key => $name) { 75 + $rows[] = "| `{$key}` | **{$name}** |"; 76 + } 77 + $severity_table = implode("\n", $rows); 78 + 79 + $valid_unit = array( 80 + array( 81 + 'name' => 'PassingTest', 82 + 'result' => ArcanistUnitTestResult::RESULT_PASS, 83 + ), 84 + array( 85 + 'name' => 'FailingTest', 86 + 'result' => ArcanistUnitTestResult::RESULT_FAIL, 87 + ), 88 + ); 89 + 90 + $valid_lint = array( 91 + array( 92 + 'name' => pht('Syntax Error'), 93 + 'code' => 'EXAMPLE1', 94 + 'severity' => ArcanistLintSeverity::SEVERITY_ERROR, 95 + 'path' => 'path/to/example.c', 96 + 'line' => 17, 97 + 'char' => 3, 98 + ), 99 + array( 100 + 'name' => pht('Not A Haiku'), 101 + 'code' => 'EXAMPLE2', 102 + 'severity' => ArcanistLintSeverity::SEVERITY_ERROR, 103 + 'path' => 'path/to/source.cpp', 104 + 'line' => 23, 105 + 'char' => 1, 106 + 'description' => pht( 107 + 'This function definition is not a haiku.'), 108 + ), 109 + ); 110 + 111 + $json = new PhutilJSON(); 112 + $valid_unit = $json->encodeAsList($valid_unit); 113 + $valid_lint = $json->encodeAsList($valid_lint); 114 + 11 115 return pht( 12 - 'Send a message to a build target, notifying it of results in an '. 13 - 'external system.'); 116 + "Send a message about the status of a build target to Harbormaster, ". 117 + "notifying the application of build results in an external system.". 118 + "\n\n". 119 + "Sending Messages\n". 120 + "================\n". 121 + "If you run external builds, you can use this method to publish build ". 122 + "results back into Harbormaster after the external system finishes work ". 123 + "or as it makes progress.". 124 + "\n\n". 125 + "The simplest way to use this method is to call it once after the ". 126 + "build finishes with a `pass` or `fail` message. This will record the ". 127 + "build result, and continue the next step in the build if the build was ". 128 + "waiting for a result.". 129 + "\n\n". 130 + "When you send a status message about a build target, you can ". 131 + "optionally include detailed `lint` or `unit` results alongside the ". 132 + "message. See below for details.". 133 + "\n\n". 134 + "If you want to report intermediate results but a build hasn't ". 135 + "completed yet, you can use the `work` message. This message doesn't ". 136 + "have any direct effects, but allows you to send additional data to ". 137 + "update the progress of the build target. The target will continue ". 138 + "waiting for a completion message, but the UI will update to show the ". 139 + "progress which has been made.". 140 + "\n\n". 141 + "Message Types\n". 142 + "=============\n". 143 + "When you send Harbormaster a message, you must include a `type`, ". 144 + "which describes the overall state of the build. For example, use ". 145 + "`pass` to tell Harbomaster that a build completed successfully.". 146 + "\n\n". 147 + "Supported message types are:". 148 + "\n\n". 149 + "%s". 150 + "\n\n". 151 + "Unit Results\n". 152 + "============\n". 153 + "You can report test results alongside a message. The simplest way to ". 154 + "do this is to report all the results alongside a `pass` or `fail` ". 155 + "message, but you can also send a `work` message to report intermediate ". 156 + "results.\n\n". 157 + "To provide unit test results, pass a list of results in the `unit` ". 158 + "parameter. Each result shoud be a dictionary with these keys:". 159 + "\n\n". 160 + "%s". 161 + "\n\n". 162 + "The `result` parameter recognizes these test results:". 163 + "\n\n". 164 + "%s". 165 + "\n\n". 166 + "This is a simple, valid value for the `unit` parameter. It reports ". 167 + "one passing test and one failing test:\n\n". 168 + "\n\n". 169 + "```lang=json\n". 170 + "%s". 171 + "```". 172 + "\n\n". 173 + "Lint Results\n". 174 + "============\n". 175 + "Like unit test results, you can report lint results alongside a ". 176 + "message. The `lint` parameter should contain results as a list of ". 177 + "dictionaries with these keys:". 178 + "\n\n". 179 + "%s". 180 + "\n\n". 181 + "The `severity` parameter recognizes these severity levels:". 182 + "\n\n". 183 + "%s". 184 + "\n\n". 185 + "This is a simple, valid value for the `lint` parameter. It reports one ". 186 + "error and one warning:". 187 + "\n\n". 188 + "```lang=json\n". 189 + "%s". 190 + "```". 191 + "\n\n", 192 + $message_table, 193 + $unit_table, 194 + $result_table, 195 + $valid_unit, 196 + $lint_table, 197 + $severity_table, 198 + $valid_lint); 14 199 } 15 200 16 201 protected function defineParamTypes() { 17 - $type_const = $this->formatStringConstants(array('pass', 'fail')); 202 + $messages = HarbormasterMessageType::getAllMessages(); 203 + $type_const = $this->formatStringConstants($messages); 18 204 19 205 return array( 20 206 'buildTargetPHID' => 'required phid', 21 - 'lint' => 'optional list<wild>', 207 + 'type' => 'required '.$type_const, 22 208 'unit' => 'optional list<wild>', 23 - 'type' => 'required '.$type_const, 209 + 'lint' => 'optional list<wild>', 24 210 ); 25 211 } 26 212
+6 -3
src/applications/harbormaster/engine/HarbormasterBuildEngine.php
··· 317 317 foreach ($messages as $message) { 318 318 $target = $waiting_targets[$message->getBuildTargetPHID()]; 319 319 320 - $new_status = null; 321 320 switch ($message->getType()) { 322 - case 'pass': 321 + case HarbormasterMessageType::MESSAGE_PASS: 323 322 $new_status = HarbormasterBuildTarget::STATUS_PASSED; 324 323 break; 325 - case 'fail': 324 + case HarbormasterMessageType::MESSAGE_FAIL: 326 325 $new_status = HarbormasterBuildTarget::STATUS_FAILED; 326 + break; 327 + case HarbormasterMessageType::MESSAGE_WORK: 328 + default: 329 + $new_status = null; 327 330 break; 328 331 } 329 332
+44
src/applications/harbormaster/engine/HarbormasterMessageType.php
··· 1 + <?php 2 + 3 + final class HarbormasterMessageType extends Phobject { 4 + 5 + const MESSAGE_PASS = 'pass'; 6 + const MESSAGE_FAIL = 'fail'; 7 + const MESSAGE_WORK = 'work'; 8 + 9 + public static function getAllMessages() { 10 + return array_keys(self::getMessageSpecifications()); 11 + } 12 + 13 + public static function getMessageDescription($message) { 14 + $spec = self::getMessageSpecification($message); 15 + if (!$spec) { 16 + return null; 17 + } 18 + return idx($spec, 'description'); 19 + } 20 + 21 + private static function getMessageSpecification($message) { 22 + $specs = self::getMessageSpecifications(); 23 + return idx($specs, $message); 24 + } 25 + 26 + private static function getMessageSpecifications() { 27 + return array( 28 + self::MESSAGE_PASS => array( 29 + 'description' => pht( 30 + 'Report that the target is complete, and the target has passed.'), 31 + ), 32 + self::MESSAGE_FAIL => array( 33 + 'description' => pht( 34 + 'Report that the target is complete, and the target has failed.'), 35 + ), 36 + self::MESSAGE_WORK => array( 37 + 'description' => pht( 38 + 'Report that work on the target is ongoing. This message can be '. 39 + 'used to report partial results during a build.'), 40 + ), 41 + ); 42 + } 43 + 44 + }
+48 -9
src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php
··· 20 20 ->setBuildTargetPHID($build_target->getPHID()); 21 21 } 22 22 23 + public static function getParameterSpec() { 24 + return array( 25 + 'name' => array( 26 + 'type' => 'string', 27 + 'description' => pht( 28 + 'Short message name, like "Syntax Error".'), 29 + ), 30 + 'code' => array( 31 + 'type' => 'string', 32 + 'description' => pht( 33 + 'Lint message code identifying the type of message, like "ERR123".'), 34 + ), 35 + 'severity' => array( 36 + 'type' => 'string', 37 + 'description' => pht( 38 + 'Severity of the message.'), 39 + ), 40 + 'path' => array( 41 + 'type' => 'string', 42 + 'description' => pht( 43 + 'Path to the file containing the lint message, from the project '. 44 + 'root.'), 45 + ), 46 + 'line' => array( 47 + 'type' => 'optional int', 48 + 'description' => pht( 49 + 'Line number in the file where the text which triggered the '. 50 + 'message first appears. The first line of the file is line 1, '. 51 + 'not line 0.'), 52 + ), 53 + 'char' => array( 54 + 'type' => 'optional int', 55 + 'description' => pht( 56 + 'Byte position on the line where the text which triggered the '. 57 + 'message starts. The first byte on the line is byte 1, not byte '. 58 + '0. This position is byte-based (not character-based) because '. 59 + 'not all lintable files have a valid character encoding.'), 60 + ), 61 + 'description' => array( 62 + 'type' => 'optional string', 63 + 'description' => pht( 64 + 'Long explanation of the lint message.'), 65 + ), 66 + ); 67 + } 68 + 23 69 public static function newFromDictionary( 24 70 HarbormasterBuildTarget $build_target, 25 71 array $dict) { 26 72 27 73 $obj = self::initializeNewLintMessage($build_target); 28 74 29 - $spec = array( 30 - 'path' => 'string', 31 - 'line' => 'optional int', 32 - 'char' => 'optional int', 33 - 'code' => 'string', 34 - 'severity' => 'string', 35 - 'name' => 'string', 36 - 'description' => 'optional string', 37 - ); 75 + $spec = self::getParameterSpec(); 76 + $spec = ipull($spec, 'type'); 38 77 39 78 // We're just going to ignore extra keys for now, to make it easier to 40 79 // add stuff here later on.
+47 -9
src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
··· 19 19 ->setBuildTargetPHID($build_target->getPHID()); 20 20 } 21 21 22 + public static function getParameterSpec() { 23 + return array( 24 + 'name' => array( 25 + 'type' => 'string', 26 + 'description' => pht( 27 + 'Short test name, like "ExampleTest".'), 28 + ), 29 + 'result' => array( 30 + 'type' => 'string', 31 + 'description' => pht( 32 + 'Result of the test.'), 33 + ), 34 + 'namespace' => array( 35 + 'type' => 'optional string', 36 + 'description' => pht( 37 + 'Optional namespace for this test. This is organizational and '. 38 + 'is often a class or module name, like "ExampleTestCase".'), 39 + ), 40 + 'engine' => array( 41 + 'type' => 'optional string', 42 + 'description' => pht( 43 + 'Test engine running the test, like "JavascriptTestEngine". This '. 44 + 'primarily prevents collisions between tests with the same name '. 45 + 'in different test suites (for example, a Javascript test and a '. 46 + 'Python test).'), 47 + ), 48 + 'duration' => array( 49 + 'type' => 'optional float|int', 50 + 'description' => pht( 51 + 'Runtime duration of the test, in seconds.'), 52 + ), 53 + 'path' => array( 54 + 'type' => 'optional string', 55 + 'description' => pht( 56 + 'Path to the file where the test is declared, relative to the '. 57 + 'project root.'), 58 + ), 59 + 'coverage' => array( 60 + 'type' => 'optional map<string, wild>', 61 + 'description' => pht( 62 + 'Coverage information for this test.'), 63 + ), 64 + ); 65 + } 66 + 22 67 public static function newFromDictionary( 23 68 HarbormasterBuildTarget $build_target, 24 69 array $dict) { 25 70 26 71 $obj = self::initializeNewUnitMessage($build_target); 27 72 28 - $spec = array( 29 - 'engine' => 'optional string', 30 - 'namespace' => 'optional string', 31 - 'name' => 'string', 32 - 'result' => 'string', 33 - 'duration' => 'optional float|int', 34 - 'path' => 'optional string', 35 - 'coverage' => 'optional map<string, wild>', 36 - ); 73 + $spec = self::getParameterSpec(); 74 + $spec = ipull($spec, 'type'); 37 75 38 76 // We're just going to ignore extra keys for now, to make it easier to 39 77 // add stuff here later on.