1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-20 10:48:40 +01:00

Record build success or failure on buildable objects

Summary:
Fixes T4810. When a buildable completes, make an effort to update the corresponding object with a success or failure message. Commits don't support this yet, but revisions do.

{F144614}

Test Plan:
  - Used `bin/harbormaster build` and `bin/harbormaster update` to run a pile of builds.
  - Tried good/bad builds.
  - Sent some normal mail to make sure the mail reentrancy change didn't break stuff.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4810

Differential Revision: https://secure.phabricator.com/D8803
This commit is contained in:
epriestley 2014-04-17 16:04:14 -07:00
parent 49bc32f12d
commit 95a405da10
5 changed files with 161 additions and 8 deletions

View file

@ -360,11 +360,13 @@ final class HarbormasterBuildEngine extends Phobject {
* @return void
*/
private function updateBuildable(HarbormasterBuildable $buildable) {
$viewer = $this->getViewer();
$lock_key = 'harbormaster.buildable:'.$buildable->getID();
$lock = PhabricatorGlobalLock::newLock($lock_key)->lock(15);
$buildable = id(new HarbormasterBuildableQuery())
->setViewer($this->getViewer())
->setViewer($viewer)
->withIDs(array($buildable->getID()))
->needBuilds(true)
->executeOne();
@ -389,12 +391,62 @@ final class HarbormasterBuildEngine extends Phobject {
$new_status = HarbormasterBuildable::STATUS_BUILDING;
}
if ($buildable->getBuildableStatus() != $new_status) {
$old_status = $buildable->getBuildableStatus();
$did_update = ($old_status != $new_status);
if ($did_update) {
$buildable->setBuildableStatus($new_status);
$buildable->save();
}
$lock->unlock();
// If we changed the buildable status, try to post a transaction to the
// object about it. We can safely do this outside of the locked region.
// NOTE: We only post transactions for automatic buildables, not for
// manual ones: manual builds are test builds, whoever is doing tests
// can look at the results themselves, and other users generally don't
// care about the outcome.
if ($did_update && !$buildable->getIsManualBuildable()) {
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($buildable->getBuildablePHID()))
->executeOne();
if ($object instanceof PhabricatorApplicationTransactionInterface) {
$template = $object->getApplicationTransactionTemplate();
if ($template) {
$template
->setTransactionType(PhabricatorTransactions::TYPE_BUILDABLE)
->setMetadataValue(
'harbormaster:buildablePHID',
$buildable->getPHID())
->setOldValue($old_status)
->setNewValue($new_status);
$harbormaster_phid = id(new PhabricatorApplicationHarbormaster())
->getPHID();
$daemon_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_DAEMON,
array());
$editor = $object->getApplicationTransactionEditor()
->setActor($viewer)
->setActingAsPHID($harbormaster_phid)
->setContentSource($daemon_source)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
$editor->applyTransactions(
$object->getApplicationTransactionObject(),
array($template));
}
}
}
}
}

View file

@ -292,19 +292,32 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
return $this->save();
}
protected function didWriteData() {
parent::didWriteData();
public function save() {
if ($this->getID()) {
return parent::save();
}
if (!$this->getWorkerTaskID()) {
// NOTE: When mail is sent from CLI scripts that run tasks in-process, we
// may re-enter this method from within scheduleTask(). The implementation
// is intended to avoid anything awkward if we end up reentering this
// method.
$this->openTransaction();
// Save to generate a task ID.
parent::save();
// Queue a task to send this mail.
$mailer_task = PhabricatorWorker::scheduleTask(
'PhabricatorMetaMTAWorker',
$this->getID());
// Save again to update the task ID.
$this->setWorkerTaskID($mailer_task->getID());
$this->save();
}
}
$result = parent::save();
$this->saveTransaction();
return $result;
}
public function buildDefaultMailer() {
return PhabricatorEnv::newObjectFromConfig('metamta.mail-adapter');

View file

@ -9,6 +9,7 @@ final class PhabricatorTransactions {
const TYPE_JOIN_POLICY = 'core:join-policy';
const TYPE_EDGE = 'core:edge';
const TYPE_CUSTOMFIELD = 'core:customfield';
const TYPE_BUILDABLE = 'harbormaster:buildable';
const COLOR_RED = 'red';
const COLOR_ORANGE = 'orange';

View file

@ -155,6 +155,10 @@ abstract class PhabricatorApplicationTransactionEditor
$types[] = PhabricatorTransactions::TYPE_CUSTOMFIELD;
}
if ($this->object instanceof HarbormasterBuildableInterface) {
$types[] = PhabricatorTransactions::TYPE_BUILDABLE;
}
return $types;
}
@ -222,6 +226,7 @@ abstract class PhabricatorApplicationTransactionEditor
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
case PhabricatorTransactions::TYPE_BUILDABLE:
return $xaction->getNewValue();
case PhabricatorTransactions::TYPE_EDGE:
return $this->getEdgeTransactionNewValue($xaction);
@ -311,6 +316,8 @@ abstract class PhabricatorApplicationTransactionEditor
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_BUILDABLE:
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());
break;
@ -321,6 +328,7 @@ abstract class PhabricatorApplicationTransactionEditor
$field = $this->getCustomFieldForTransaction($object, $xaction);
return $field->applyApplicationTransactionInternalEffects($xaction);
}
return $this->applyCustomInternalTransaction($object, $xaction);
}
@ -328,6 +336,8 @@ abstract class PhabricatorApplicationTransactionEditor
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_BUILDABLE:
return;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$subeditor = id(new PhabricatorSubscriptionsEditor())
->setObject($object)

View file

@ -52,6 +52,8 @@ abstract class PhabricatorApplicationTransaction
public function shouldGenerateOldValue() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_BUILDABLE:
return false;
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
return false;
}
@ -234,6 +236,12 @@ abstract class PhabricatorApplicationTransaction
$phids[] = array($new);
}
break;
case PhabricatorTransactions::TYPE_BUILDABLE:
$phid = $this->getMetadataValue('harbormaster:buildablePHID');
if ($phid) {
$phids[] = array($phid);
}
break;
}
return array_mergev($phids);
@ -325,12 +333,24 @@ abstract class PhabricatorApplicationTransaction
return 'lock';
case PhabricatorTransactions::TYPE_EDGE:
return 'link';
case PhabricatorTransactions::TYPE_BUILDABLE:
return 'wrench';
}
return 'edit';
}
public function getColor() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_BUILDABLE:
switch ($this->getNewValue()) {
case HarbormasterBuildable::STATUS_PASSED:
return 'green';
case HarbormasterBuildable::STATUS_FAILED:
return 'red';
}
break;
}
return null;
}
@ -379,6 +399,17 @@ abstract class PhabricatorApplicationTransaction
}
public function shouldHideForMail(array $xactions) {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_BUILDABLE:
switch ($this->getNewValue()) {
case HarbormasterBuildable::STATUS_PASSED:
// For now, just never send mail when builds pass. We might let
// you customize this later, but in most cases this is probably
// completely uninteresting.
return true;
}
}
return $this->shouldHide();
}
@ -537,6 +568,24 @@ abstract class PhabricatorApplicationTransaction
$this->renderHandleLink($author_phid));
}
case PhabricatorTransactions::TYPE_BUILDABLE:
switch ($this->getNewValue()) {
case HarbormasterBuildable::STATUS_PASSED:
return pht(
'%s completed building %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(
$this->getMetadataValue('harbormaster:buildablePHID')));
case HarbormasterBuildable::STATUS_FAILED:
return pht(
'%s failed to build %s!',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(
$this->getMetadataValue('harbormaster:buildablePHID')));
default:
return null;
}
default:
return pht(
'%s edited this %s.',
@ -596,6 +645,25 @@ abstract class PhabricatorApplicationTransaction
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
case PhabricatorTransactions::TYPE_BUILDABLE:
switch ($this->getNewValue()) {
case HarbormasterBuildable::STATUS_PASSED:
return pht(
'%s completed building %s for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(
$this->getMetadataValue('harbormaster:buildablePHID')),
$this->renderHandleLink($object_phid));
case HarbormasterBuildable::STATUS_FAILED:
return pht(
'%s failed to build %s for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(
$this->getMetadataValue('harbormaster:buildablePHID')),
$this->renderHandleLink($object_phid));
default:
return null;
}
}
@ -649,6 +717,15 @@ abstract class PhabricatorApplicationTransaction
return pht('Changed Policy');
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
return pht('Changed Subscribers');
case PhabricatorTransactions::TYPE_BUILDABLE:
switch ($this->getNewValue()) {
case HarbormasterBuildable::STATUS_PASSED:
return pht('Build Passed');
case HarbormasterBuildable::STATUS_FAILED:
return pht('Build Failed');
default:
return pht('Build Status');
}
default:
return pht('Updated');
}