diff --git a/src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php index 89d4002eef..8a522c4926 100644 --- a/src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php @@ -1,215 +1,223 @@ logSilencedCall($build, $build_target, pht('Buildkite')); throw new HarbormasterBuildFailureException(); } $buildable = $build->getBuildable(); $object = $buildable->getBuildableObject(); if (!($object instanceof HarbormasterBuildkiteBuildableInterface)) { throw new Exception( pht('This object does not support builds with Buildkite.')); } $organization = $this->getSetting('organization'); $pipeline = $this->getSetting('pipeline'); $uri = urisprintf( 'https://api.buildkite.com/v2/organizations/%s/pipelines/%s/builds', $organization, $pipeline); $data_structure = array( 'commit' => $object->getBuildkiteCommit(), 'branch' => $object->getBuildkiteBranch(), 'message' => pht( 'Harbormaster Build %s ("%s") for %s', $build->getID(), $build->getName(), $buildable->getMonogram()), 'env' => array( 'HARBORMASTER_BUILD_TARGET_PHID' => $build_target->getPHID(), ), 'meta_data' => array( 'buildTargetPHID' => $build_target->getPHID(), + + // See PHI611. These are undocumented secret magic. + 'phabricator:build:id' => (int)$build->getID(), + 'phabricator:build:url' => + PhabricatorEnv::getProductionURI($build->getURI()), + 'phabricator:buildable:id' => (int)$buildable->getID(), + 'phabricator:buildable:url' => + PhabricatorEnv::getProductionURI($buildable->getURI()), ), ); $json_data = phutil_json_encode($data_structure); $credential_phid = $this->getSetting('token'); $api_token = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withPHIDs(array($credential_phid)) ->needSecrets(true) ->executeOne(); if (!$api_token) { throw new Exception( pht( 'Unable to load API token ("%s")!', $credential_phid)); } $token = $api_token->getSecret()->openEnvelope(); $future = id(new HTTPSFuture($uri, $json_data)) ->setMethod('POST') ->addHeader('Content-Type', 'application/json') ->addHeader('Accept', 'application/json') ->addHeader('Authorization', "Bearer {$token}") ->setTimeout(60); $this->resolveFutures( $build, $build_target, array($future)); $this->logHTTPResponse($build, $build_target, $future, pht('Buildkite')); list($status, $body) = $future->resolve(); if ($status->isError()) { throw new HarbormasterBuildFailureException(); } $response = phutil_json_decode($body); $uri_key = 'web_url'; $build_uri = idx($response, $uri_key); if (!$build_uri) { throw new Exception( pht( 'Buildkite did not return a "%s"!', $uri_key)); } $target_phid = $build_target->getPHID(); $api_method = 'harbormaster.createartifact'; $api_params = array( 'buildTargetPHID' => $target_phid, 'artifactType' => HarbormasterURIArtifact::ARTIFACTCONST, 'artifactKey' => 'buildkite.uri', 'artifactData' => array( 'uri' => $build_uri, 'name' => pht('View in Buildkite'), 'ui.external' => true, ), ); id(new ConduitCall($api_method, $api_params)) ->setUser($viewer) ->execute(); } public function getFieldSpecifications() { return array( 'token' => array( 'name' => pht('API Token'), 'type' => 'credential', 'credential.type' => PassphraseTokenCredentialType::CREDENTIAL_TYPE, 'credential.provides' => PassphraseTokenCredentialType::PROVIDES_TYPE, 'required' => true, ), 'organization' => array( 'name' => pht('Organization Name'), 'type' => 'text', 'required' => true, ), 'pipeline' => array( 'name' => pht('Pipeline Name'), 'type' => 'text', 'required' => true, ), 'webhook.token' => array( 'name' => pht('Webhook Token'), 'type' => 'text', 'required' => true, ), ); } public function supportsWaitForMessage() { return false; } public function shouldWaitForMessage(HarbormasterBuildTarget $target) { return true; } }