getSetting('uri'); if ($uri) { $domain = id(new PhutilURI($uri))->getDomain(); } $method = $this->formatSettingForDescription('method', 'POST'); $domain = $this->formatValueForDescription($domain); if ($this->getSetting('credential')) { return pht( 'Make an authenticated HTTP %s request to %s.', $method, $domain); } else { return pht( 'Make an HTTP %s request to %s.', $method, $domain); } } public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { $viewer = PhabricatorUser::getOmnipotentUser(); // Settings includes the custom fields set in getFieldSpecifications() $settings = $this->getSettings(); $variables = $build_target->getVariables(); // Combined TeamCity URI $uri = $settings['uri'] . '/app/rest/buildQueue'; $method = 'POST'; $contentType = 'application/xml'; // Using TeamCityXmlBuildBuilder create the payload to send to // TeamCity server $xmlBuilder = new TeamCityXmlBuildBuilder(); $payload = $xmlBuilder ->addBuildId($settings['buildId']) ->addBranchName(implode(array("D", $variables['buildable.revision'], "-", $variables['build.id']))) ->addPhabBuildId($variables['build.id']) ->addDiffId($variables['buildable.diff']) ->addHarbormasterPHID($variables['target.phid']) ->addRevisionId(implode(array("D", $variables['buildable.revision']))) ->build(); $future = id(new HTTPSFuture($uri, $payload)) ->setMethod($method) ->addHeader('Content-Type', $contentType) ->addHeader('Origin', $settings['uri']) ->setTimeout(60); // Add credentials to HTTP request if they have been set $credential_phid = $this->getSetting('credential'); if ($credential_phid) { $key = PassphraseTokenKey::loadFromPHID( $credential_phid, $viewer); $future->addHeader( 'Authorization', implode(array("Bearer ", $key->getPasswordEnvelope()->openEnvelope())) ); } $this->resolveFutures( $build, $build_target, array($future)); list($status, $body, $headers) = $future->resolve(); $header_lines = array(); // TODO: We don't currently preserve the entire "HTTP" response header, but // should. Once we do, reproduce it here faithfully. $status_code = $status->getStatusCode(); $header_lines[] = "HTTP {$status_code}"; foreach ($headers as $header) { list($head, $tail) = $header; $header_lines[] = "{$head}: {$tail}"; } $header_lines = implode("\n", $header_lines); $build_target ->newLog($uri, 'http.head') ->append($header_lines); $build_target ->newLog($uri, 'http.body') ->append($body); if ($status->isError()) { throw new HarbormasterBuildFailureException(); } } public function getFieldSpecifications() { return array( 'uri' => array( 'name' => pht('URI'), 'type' => 'text', 'required' => true, ), 'buildId' => array( 'name' => pht('TeamCity Build Configuration ID'), 'type' => 'text', 'required' => true, ), 'credential' => array( 'name' => pht('TeamCity Credentials'), 'type' => 'credential', 'required' => true, 'credential.type' => PassphraseTokenCredentialType::CREDENTIAL_TYPE, 'credential.provides' => PassphraseTokenCredentialType::PROVIDES_TYPE, ), ); } public function supportsWaitForMessage() { return true; } }