3 final class HarbormasterBuildkiteHookController
4 extends HarbormasterController
{
6 public function shouldRequireLogin() {
11 * @phutil-external-symbol class PhabricatorStartup
13 public function handleRequest(AphrontRequest
$request) {
14 $raw_body = PhabricatorStartup
::getRawInput();
15 $body = phutil_json_decode($raw_body);
17 $event = idx($body, 'event');
18 if ($event != 'build.finished') {
19 return $this->newHookResponse(pht('OK: Ignored event.'));
22 $build = idx($body, 'build');
23 if (!is_array($build)) {
26 'Expected "%s" property to contain a dictionary.',
30 $meta_data = idx($build, 'meta_data');
31 if (!is_array($meta_data)) {
34 'Expected "%s" property to contain a dictionary.',
38 $target_phid = idx($meta_data, 'buildTargetPHID');
40 return $this->newHookResponse(pht('OK: No Harbormaster target PHID.'));
43 $viewer = PhabricatorUser
::getOmnipotentUser();
44 $target = id(new HarbormasterBuildTargetQuery())
46 ->withPHIDs(array($target_phid))
47 ->needBuildSteps(true)
52 'Harbormaster build target "%s" does not exist.',
56 $step = $target->getBuildStep();
57 $impl = $step->getStepImplementation();
58 if (!($impl instanceof HarbormasterBuildkiteBuildStepImplementation
)) {
61 'Harbormaster build target "%s" is not a Buildkite build step. '.
62 'Only Buildkite steps may be updated via the Buildkite hook.',
66 $webhook_token = $impl->getSetting('webhook.token');
67 $request_token = $request->getHTTPHeader('X-Buildkite-Token');
69 if (!phutil_hashes_are_identical($webhook_token, $request_token)) {
72 'Buildkite request to target "%s" had the wrong authentication '.
73 'token. The Buildkite pipeline and Harbormaster build step must '.
74 'be configured with the same token.',
78 $state = idx($build, 'state');
81 $message_type = HarbormasterMessageType
::MESSAGE_PASS
;
84 $message_type = HarbormasterMessageType
::MESSAGE_FAIL
;
88 $api_method = 'harbormaster.sendmessage';
90 'buildTargetPHID' => $target_phid,
91 'type' => $message_type,
94 $unguarded = AphrontWriteGuard
::beginScopedUnguardedWrites();
96 id(new ConduitCall($api_method, $api_params))
102 return $this->newHookResponse(pht('OK: Processed event.'));
105 private function newHookResponse($message) {
106 $response = new AphrontWebpageResponse();
107 $response->setContent($message);