1
0
Fork 0
Teamcity-Phabricator-Plugin/Harbormaster-Teamcity-Plugin/HarbormasterTeamCityBuildStepImplementation.php
Steven Cooney 11558ddf54 Add Harbormaster TeamCity Plugin
The complete plugin required to trigger a teamcity build from a harbormaster build plan.
2019-05-30 13:16:13 +01:00

147 lines
4.2 KiB
PHP

<?php
final class HarbormasterTeamCityBuildStepImplementation
extends HarbormasterBuildStepImplementation {
public function getName() {
return pht('Build with TeamCity');
}
public function getGenericDescription() {
return pht('Trigger TeamCity Builds with Harbormaster');
}
public function getBuildStepGroupKey() {
return HarbormasterExternalBuildStepGroup::GROUPKEY;
}
public function getDescription() {
$domain = null;
$uri = $this->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;
}
}