diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1629,6 +1629,7 @@ 'PhabricatorMail' => 'applications/metamta/PhabricatorMail.php', 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php', 'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php', + 'PhabricatorMailImplementationFileTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationFileTestAdapter.php', 'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php', 'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php', @@ -4379,6 +4380,7 @@ 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', + 'PhabricatorMailImplementationFileTestAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', diff --git a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php --- a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php +++ b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php @@ -183,6 +183,9 @@ if (count($failed)) { $build->setBuildStatus(HarbormasterBuild::STATUS_FAILED); $build->save(); + + $this->handleFailedBuild($build); + return; } @@ -191,6 +194,9 @@ if (count($complete) == count($steps)) { $build->setBuildStatus(HarbormasterBuild::STATUS_PASSED); $build->save(); + + $this->handlePassedBuild($build); + return; } @@ -231,6 +237,9 @@ // normally be possible, but we should communicate it more clearly. $build->setBuildStatus(HarbormasterBuild::STATUS_FAILED); $build->save(); + + $this->handleFailedBuild($build); + return; } @@ -245,4 +254,62 @@ } } + private function handleFailedBuild(HarbormasterBuild $build) { + $subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID( + $build->getBuildPlanPHID()); + + $build_uri = new PhutilURI('/harbormaster/build/'.$build->getID().'/'); + $prod_uri = PhabricatorEnv::getProductionURI(''); + + // TODO: Do we need to check to see if the subscriber can see + // the buildable this build applies to? + + // TODO: Include more information + + $body = pht('Link to build: %s', $prod_uri.$build_uri); + + $subject = pht('Build ').$build->getID(); + + $mail = new PhabricatorMetaMTAMail(); + $mail->setSubject($subject) + ->setSubjectPrefix('[Harbormaster]') + ->setVarySubjectPrefix('[Build Failed]') + ->addHeader('Thread-Topic', pht('Build Failed ').$build->getID()) + ->addTos($subscribers) + ->setBody($body) + ->setRelatedPHID($build->getPHID()) + ->setIsBulk(true); + + $mail->saveAndSend(); + } + + private function handlePassedBuild(HarbormasterBuild $build) { + $subscribers = PhabricatorSubscribersQuery::loadSubscribersForPHID( + $build->getBuildPlanPHID()); + + $build_uri = new PhutilURI('/harbormaster/build/'.$build->getID().'/'); + $prod_uri = PhabricatorEnv::getProductionURI(''); + + // TODO: Do we need to check to see if the subscriber can see + // the buildable this build applies to? + + // TODO: Include more information + + $body = pht('Link to build: %s', $prod_uri.$build_uri); + + $subject = pht('Build ').$build->getID(); + + $mail = new PhabricatorMetaMTAMail(); + $mail->setSubject($subject) + ->setSubjectPrefix('[Harbormaster]') + ->setVarySubjectPrefix('[Build Passed]') + ->addHeader('Thread-Topic', pht('Build Passed ').$build->getID()) + ->addTos($subscribers) + ->setBody($body) + ->setRelatedPHID($build->getPHID()) + ->setIsBulk(true); + + $mail->saveAndSend(); + } + } diff --git a/src/applications/metamta/adapter/PhabricatorMailImplementationFileTestAdapter.php b/src/applications/metamta/adapter/PhabricatorMailImplementationFileTestAdapter.php new file mode 100644 --- /dev/null +++ b/src/applications/metamta/adapter/PhabricatorMailImplementationFileTestAdapter.php @@ -0,0 +1,95 @@ +config = $config; + } + + public function setFrom($email, $name = '') { + $this->guts['from'] = $email; + $this->guts['from-name'] = $name; + return $this; + } + + public function addReplyTo($email, $name = '') { + if (empty($this->guts['reply-to'])) { + $this->guts['reply-to'] = array(); + } + $this->guts['reply-to'][] = array( + 'email' => $email, + 'name' => $name, + ); + return $this; + } + + public function addTos(array $emails) { + foreach ($emails as $email) { + $this->guts['tos'][] = $email; + } + return $this; + } + + public function addCCs(array $emails) { + foreach ($emails as $email) { + $this->guts['ccs'][] = $email; + } + return $this; + } + + public function addAttachment($data, $filename, $mimetype) { + $this->guts['attachments'][] = array( + 'data' => $data, + 'filename' => $filename, + 'mimetype' => $mimetype + ); + return $this; + } + + public function addHeader($header_name, $header_value) { + $this->guts['headers'][] = array($header_name, $header_value); + return $this; + } + + public function setBody($body) { + $this->guts['body'] = $body; + return $this; + } + + public function setSubject($subject) { + $this->guts['subject'] = $subject; + return $this; + } + + public function setIsHTML($is_html) { + $this->guts['is-html'] = $is_html; + return $this; + } + + public function supportsMessageIDHeader() { + return $this->config['supportsMessageIDHeader']; + } + + public function send() { + $this->guts['did-send'] = true; + + $file = PhabricatorFile::newFromFileData( + json_encode($this->guts, JSON_PRETTY_PRINT), + array( + 'name' => time().'.mail.txt', + 'ttl' => time() + (5 * 60))); + + return true; + } + + public function getGuts() { + return $this->guts; + } +}