@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Execute Herald again after promoting revisions out of the "Draft" state

Summary:
Fixes T13027. Ref T2543. When revisions promote from "Draft" because builds finish or no builds are configured, the status currently switches from "Draft" to "Needs Review" without re-running Herald.

This means that some rules -- notably, "Send me an email" rules -- don't fire as soon as they should.

Instead of applying this promotion in a hacky way inline, queue it and apply it normally in a second edit, after the current group finishes.

Test Plan:
- Created a revision, reviewed Herald transcripts.
- Saw three Herald passes:
- First pass (revision creation) triggered builds and no email.
- Second pass (builds finished) did not trigger builds (no update) and did not trigger email (revision still a draft).
- Third pass (after promotion out of 'draft') did not trigger builds (no update) but did trigger email (revision no longer a draft).

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13027, T2543

Differential Revision: https://secure.phabricator.com/D18819

+52 -17
+4 -12
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 1588 1588 ->setAuthorPHID($author_phid) 1589 1589 ->setTransactionType( 1590 1590 DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE) 1591 - ->setOldValue(false) 1592 1591 ->setNewValue(true); 1593 - 1594 - $xaction = $this->populateTransaction($object, $xaction); 1595 1592 1596 1593 // If we're creating this revision and immediately moving it out of 1597 1594 // the draft state, mark this as a create transaction so it gets ··· 1601 1598 $xaction->setIsCreateTransaction(true); 1602 1599 } 1603 1600 1604 - $object->openTransaction(); 1605 - $object 1606 - ->setStatus(DifferentialRevisionStatus::NEEDS_REVIEW) 1607 - ->save(); 1608 - 1609 - $xaction->save(); 1610 - $object->saveTransaction(); 1611 - 1612 - $xactions[] = $xaction; 1601 + // Queue this transaction and apply it separately after the current 1602 + // batch of transactions finishes so that Herald can fire on the new 1603 + // revision state. See T13027 for discussion. 1604 + $this->queueTransaction($xaction); 1613 1605 } 1614 1606 } 1615 1607
+9 -5
src/applications/differential/xaction/DifferentialRevisionRequestReviewTransaction.php
··· 57 57 'revisions.')); 58 58 } 59 59 60 - if (!$this->isViewerRevisionAuthor($object, $viewer)) { 61 - throw new Exception( 62 - pht( 63 - 'You can not request review of this revision because you are not '. 64 - 'the author of the revision.')); 60 + // When revisions automatically promote out of "Draft" after builds finish, 61 + // the viewer may be acting as the Harbormaster application. 62 + if (!$viewer->isOmnipotent()) { 63 + if (!$this->isViewerRevisionAuthor($object, $viewer)) { 64 + throw new Exception( 65 + pht( 66 + 'You can not request review of this revision because you are not '. 67 + 'the author of the revision.')); 68 + } 65 69 } 66 70 } 67 71
+39
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 70 70 private $feedRelatedPHIDs = array(); 71 71 private $modularTypes; 72 72 73 + private $transactionQueue = array(); 74 + 73 75 const STORAGE_ENCODING_BINARY = 'binary'; 74 76 75 77 /** ··· 1173 1175 'objectPHID' => $object->getPHID(), 1174 1176 'priority' => PhabricatorWorker::PRIORITY_ALERTS, 1175 1177 )); 1178 + 1179 + $this->flushTransactionQueue($object); 1176 1180 1177 1181 return $xactions; 1178 1182 } ··· 3862 3866 3863 3867 public function getCreateObjectTitleForFeed($author, $object) { 3864 3868 return pht('%s created an object: %s.', $author, $object); 3869 + } 3870 + 3871 + /* -( Queue )-------------------------------------------------------------- */ 3872 + 3873 + protected function queueTransaction( 3874 + PhabricatorApplicationTransaction $xaction) { 3875 + $this->transactionQueue[] = $xaction; 3876 + return $this; 3877 + } 3878 + 3879 + private function flushTransactionQueue($object) { 3880 + if (!$this->transactionQueue) { 3881 + return; 3882 + } 3883 + 3884 + $xactions = $this->transactionQueue; 3885 + $this->transactionQueue = array(); 3886 + 3887 + $editor = $this->newQueueEditor(); 3888 + 3889 + return $editor->applyTransactions($object, $xactions); 3890 + } 3891 + 3892 + private function newQueueEditor() { 3893 + $editor = id(newv(get_class($this), array())) 3894 + ->setActor($this->getActor()) 3895 + ->setContentSource($this->getContentSource()) 3896 + ->setContinueOnNoEffect($this->getContinueOnNoEffect()) 3897 + ->setContinueOnMissingFields($this->getContinueOnMissingFields()); 3898 + 3899 + if ($this->actingAsPHID !== null) { 3900 + $editor->setActingAsPHID($this->actingAsPHID); 3901 + } 3902 + 3903 + return $editor; 3865 3904 } 3866 3905 3867 3906 }