1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Add a CircleCI webhook

Summary: Ref T9456. This makes everything work, except that CircleCI doesn't fetch tags which are not ancestors of branch heads.

Test Plan: Ran passing builds through CircleCI.

Reviewers: chad

Reviewed By: chad

Subscribers: dpaola2, JustinTulloss

Maniphest Tasks: T9456

Differential Revision: https://secure.phabricator.com/D14288
This commit is contained in:
epriestley 2015-10-15 09:07:31 -07:00
parent f82db7524b
commit 7868c5d7d0
5 changed files with 112 additions and 3 deletions

View file

@ -1108,6 +1108,7 @@ phutil_register_library_map(array(
'HarbormasterBuiltinBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php', 'HarbormasterBuiltinBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php',
'HarbormasterCircleCIBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterCircleCIBuildStepImplementation.php', 'HarbormasterCircleCIBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterCircleCIBuildStepImplementation.php',
'HarbormasterCircleCIBuildableInterface' => 'applications/harbormaster/interface/HarbormasterCircleCIBuildableInterface.php', 'HarbormasterCircleCIBuildableInterface' => 'applications/harbormaster/interface/HarbormasterCircleCIBuildableInterface.php',
'HarbormasterCircleCIHookController' => 'applications/harbormaster/controller/HarbormasterCircleCIHookController.php',
'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php', 'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php',
'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php', 'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php',
'HarbormasterCreateArtifactConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php', 'HarbormasterCreateArtifactConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php',
@ -5338,6 +5339,7 @@ phutil_register_library_map(array(
'HarbormasterBuildableViewController' => 'HarbormasterController', 'HarbormasterBuildableViewController' => 'HarbormasterController',
'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup',
'HarbormasterCircleCIBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterCircleCIBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
'HarbormasterCircleCIHookController' => 'HarbormasterController',
'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod', 'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod',
'HarbormasterController' => 'PhabricatorController', 'HarbormasterController' => 'PhabricatorController',
'HarbormasterCreateArtifactConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterCreateArtifactConduitAPIMethod' => 'HarbormasterConduitAPIMethod',

View file

@ -91,6 +91,9 @@ final class PhabricatorHarbormasterApplication extends PhabricatorApplication {
'lint/' => array( 'lint/' => array(
'(?P<id>\d+)/' => 'HarbormasterLintMessagesController', '(?P<id>\d+)/' => 'HarbormasterLintMessagesController',
), ),
'hook/' => array(
'circleci/' => 'HarbormasterCircleCIHookController',
),
), ),
); );
} }

View file

@ -0,0 +1,87 @@
<?php
final class HarbormasterCircleCIHookController
extends HarbormasterController {
public function shouldRequireLogin() {
return false;
}
/**
* @phutil-external-symbol class PhabricatorStartup
*/
public function handleRequest(AphrontRequest $request) {
$raw_body = PhabricatorStartup::getRawInput();
$body = phutil_json_decode($raw_body);
$payload = $body['payload'];
$parameters = idx($payload, 'build_parameters');
if (!$parameters) {
$parameters = array();
}
$target_phid = idx($parameters, 'HARBORMASTER_BUILD_TARGET_PHID');
// NOTE: We'll get callbacks here for builds we triggered, but also for
// arbitrary builds the system executes for other reasons. So it's normal
// to get some notifications with no Build Target PHID. We just ignore
// these under the assumption that they're routine builds caused by events
// like branch updates.
if ($target_phid) {
$viewer = PhabricatorUser::getOmnipotentUser();
$target = id(new HarbormasterBuildTargetQuery())
->setViewer($viewer)
->withPHIDs(array($target_phid))
->needBuildSteps(true)
->executeOne();
if ($target) {
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$this->updateTarget($target, $payload);
}
}
$response = new AphrontWebpageResponse();
$response->setContent(pht("Request OK\n"));
return $response;
}
private function updateTarget(
HarbormasterBuildTarget $target,
array $payload) {
$step = $target->getBuildStep();
$impl = $step->getStepImplementation();
if (!($impl instanceof HarbormasterCircleCIBuildStepImplementation)) {
throw new Exception(
pht(
'Build target ("%s") has the wrong type of build step. Only '.
'CircleCI build steps may be updated via the CircleCI webhook.',
$target->getPHID()));
}
switch (idx($payload, 'status')) {
case 'success':
case 'fixed':
$message_type = HarbormasterMessageType::MESSAGE_PASS;
break;
default:
$message_type = HarbormasterMessageType::MESSAGE_FAIL;
break;
}
$viewer = PhabricatorUser::getOmnipotentUser();
$api_method = 'harbormaster.sendmessage';
$api_params = array(
'buildTargetPHID' => $target->getPHID(),
'type' => $message_type,
);
id(new ConduitCall($api_method, $api_params))
->setUser($viewer)
->execute();
}
}

View file

@ -20,6 +20,9 @@ final class HarbormasterCircleCIBuildStepImplementation
} }
public function getEditInstructions() { public function getEditInstructions() {
$hook_uri = '/harbormaster/hook/circleci/';
$hook_uri = PhabricatorEnv::getProductionURI($hook_uri);
return pht(<<<EOTEXT return pht(<<<EOTEXT
WARNING: This build step is new and experimental! WARNING: This build step is new and experimental!
@ -38,7 +41,15 @@ To build **commits** with CircleCI, they must:
Webhook Configuration Webhook Configuration
===================== =====================
IMPORTANT: This has not been implemented yet. Add this webhook to your `circle.yml` file to make CircleCI report results
to Harbormaster. Until you install this hook, builds will hang waiting for
a response from CircleCI.
```lang=yml
notify:
webhooks:
- url: %s
```
Environment Environment
=========== ===========
@ -50,7 +61,8 @@ These variables will be available in the build environment:
| `HARBORMASTER_BUILD_TARGET_PHID` | PHID of the Build Target. | `HARBORMASTER_BUILD_TARGET_PHID` | PHID of the Build Target.
EOTEXT EOTEXT
); ,
$hook_uri);
} }
public static function getGitHubPath($uri) { public static function getGitHubPath($uri) {

View file

@ -17,8 +17,13 @@ final class HarbormasterBuildMessage extends HarbormasterDAO
private $buildTarget = self::ATTACHABLE; private $buildTarget = self::ATTACHABLE;
public static function initializeNewMessage(PhabricatorUser $actor) { public static function initializeNewMessage(PhabricatorUser $actor) {
$actor_phid = $actor->getPHID();
if (!$actor_phid) {
$actor_phid = id(new PhabricatorHarbormasterApplication())->getPHID();
}
return id(new HarbormasterBuildMessage()) return id(new HarbormasterBuildMessage())
->setAuthorPHID($actor->getPHID()) ->setAuthorPHID($actor_phid)
->setIsConsumed(0); ->setIsConsumed(0);
} }