Commit 3a65c4a5 authored by Sean Madsen's avatar Sean Madsen

Merge branch '68_tmp-dir-publishing' into 'master'

Publish to temp directory

See merge request !72
parents 1abe28c6 f65c034f
......@@ -3,7 +3,6 @@
parameters:
books_dir: %kernel.root_dir%/../books
publish_path_root: %kernel.root_dir%/../web
repos_path_root: %kernel.root_dir%/../var/repos
services:
......@@ -24,13 +23,24 @@ services:
publisher:
class: AppBundle\Utils\Publisher
arguments:
- '@request_stack'
- '@publish.logger'
- '@filesystem'
- '@library'
- %repos_path_root%
- %publish_path_root%
- '@mkdocs'
- '@git'
- '@paths'
filesystem:
class: AppBundle\Utils\FileSystem
paths:
class: AppBundle\Utils\Paths
arguments:
- '%kernel.root_dir%'
- '%kernel.cache_dir%'
git:
class: AppBundle\Utils\GitTools
publish.logger:
class: Monolog\Logger
......
......@@ -17,7 +17,7 @@
}
},
"require": {
"php": "^5.6|^7.0",
"php": "^7.0",
"symfony/symfony": "3.0.*",
"doctrine/orm": "^2.5",
"twig/twig": "^1.33",
......
......@@ -2,6 +2,7 @@
namespace AppBundle\Controller;
use AppBundle\Utils\Publisher;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
......@@ -12,7 +13,7 @@ use AppBundle\Model\Library;
class PublishController extends Controller {
/**
* @var \AppBundle\Utils\Publisher
* @var Publisher
*/
private $publisher;
......@@ -22,9 +23,13 @@ class PublishController extends Controller {
private $publishSuccess;
/**
* @param string $identifier
*
* @return Response
*
* @Route("/admin/publish{identifier}" , requirements={"identifier": ".*"})
*/
public function PublishAction(Request $request, $identifier) {
public function PublishAction($identifier) {
$this->publisher = $this->get('publisher');
$bookSlug = Library::parseIdentifier($identifier)['bookSlug'];
if ($bookSlug) {
......@@ -44,6 +49,10 @@ class PublishController extends Controller {
}
/**
* @param Request $request
*
* @return Response
*
* @Route("/admin/listen")
*/
public function ListenAction(Request $request) {
......@@ -63,45 +72,55 @@ class PublishController extends Controller {
if ($identifiers) {
$this->publisher = $this->get('publisher');
foreach ($identifiers as $identifier) {
$this->publisher->publish("{$identifier}/{$processor->branch}");
if ($this->publisher->version) {
$this->sendEmail($processor->recipients);
}
$fullIdentifier = "{$identifier}/{$processor->branch}";
$this->publisher->publish($fullIdentifier);
$this->sendEmail($fullIdentifier);
}
$response = $this->publisher->getMessagesInPlainText();
}
else {
$response = "CRITICAL - No books found which match {$processor->repo}";
}
return new Response($response, 200);
}
/**
* Send notification emails after publishing
*
* @param array $extraRecipients
* Array of strings for email addresses that should receive the
* notification email. If non are specified, then the email will be sent to
* all addresses set in the book's yaml configuration.
* @param string $identifier
*/
private function sendEmail($extraRecipients = array()) {
$subject = $this->publisher->status;
$recipients = array_unique(array_merge(
$extraRecipients,
$this->publisher->language->watchers));
private function sendEmail(string $identifier) {
/**
* Array of strings for email addresses that should receive the
* notification email. If none are specified, then the email will be sent to
* all addresses set in the book's yaml configuration
*/
$extraRecipients = $this->get('github.hook.processor')->recipients;
$library = $this->get('library');
$messages = $this->get('publisher')->getMessages();
$parts = $library::parseIdentifier($identifier);
$book = $library->getBookBySlug($parts['bookSlug']);
$language = $book->getLanguageByCode($parts['languageCode']);
$version = $language->getVersionByDescriptor($parts['versionDescriptor']);
$webPath = sprintf('%s/%s/%s', $book->slug, $language->code, $version->branch);
$subject = "Publishing Successful";
$recipients = array_unique(array_merge($extraRecipients, $language->watchers));
$renderParams = [
'publishURLBase' => $webPath,
'status' => $subject,
'messages' => $messages,
];
$body = $this->renderView('AppBundle:Emails:notify.html.twig', $renderParams);
$mail = \Swift_Message::newInstance()
->setSubject("$subject")
->setSubject($subject)
->setFrom('no-reply@civicrm.org', "CiviCRM docs")
->setTo($recipients)
->setBody(
$this->renderView('AppBundle:Emails:notify.html.twig',
array(
'publishURLBase' => $this->publisher->publishURLBase,
'status' => $this->publisher->status,
'messages' => $this->publisher->messages,
)
), 'text/html'
);
->setBody($body, 'text/html');
$this->get('mailer')->send($mail);
}
......
......@@ -3,7 +3,6 @@
namespace AppBundle\Model;
use AppBundle\Utils\LocaleTools;
use \AppBundle\Model\Version;
class Language {
......@@ -162,7 +161,7 @@ class Language {
* @return string
* e.g. "Spanish"
*/
public function englishName() {
public function getEnglishName() {
return LocaleTools::getLanguageNameInLocale($this->code, 'en');
}
......@@ -185,10 +184,10 @@ class Language {
*/
public function descriptiveName() {
if ($this->code == 'en') {
return $this->englishName();
return $this->getEnglishName();
}
else {
return $this->nativeName() . " (" . $this->englishName() . ")";
return $this->nativeName() . " (" . $this->getEnglishName() . ")";
}
}
......
<?php
namespace AppBundle\Utils;
use Symfony\Component\Filesystem\Filesystem as BaseFileSystem;
class FileSystem extends BaseFileSystem {
/**
* @param $source
* @param $target
*/
public function copyDir($source, $target) {
$this->mkdir($target);
$mode = \RecursiveIteratorIterator::SELF_FIRST;
$directoryIterator = new \RecursiveDirectoryIterator($source);
$iterator = new \RecursiveIteratorIterator($directoryIterator, $mode);
foreach ($iterator as $item) {
if ($item->isDir()) {
$targetDir = $target.DIRECTORY_SEPARATOR. $iterator->getSubPathName();
$this->mkdir($targetDir);
} else {
$targetFilename = $target.DIRECTORY_SEPARATOR. $iterator->getSubPathName();
$this->copy($item, $targetFilename);
}
}
}
/**
* @param string $dir
*/
public function removeDir($dir) {
if (!$this->exists($dir)) {
return;
}
$childFirst = \RecursiveIteratorIterator::CHILD_FIRST;
$noDots = \RecursiveDirectoryIterator::SKIP_DOTS;
$directoryIterator = new \RecursiveDirectoryIterator($dir, $noDots);
$iterator = new \RecursiveIteratorIterator($directoryIterator, $childFirst);
foreach ($iterator as $item) {
if ($item->isDir()) {
$this->removeDir($item->getPathname());
} else {
$this->remove($item->getPathname());
}
}
rmdir($dir);
}
}
<?php
namespace AppBundle\Utils;
use Symfony\Component\Process\Process;
class GitTools {
/**
* @param $repoPath
*
* @return string
*/
public function getCurrentBranch($repoPath): string {
$checkBranch = new Process('git rev-parse --abbrev-ref HEAD', $repoPath);
$checkBranch->run();
$currentBranch = trim($checkBranch->getOutput());
return $currentBranch;
}
/**
* @param string $repoPath
*/
public function pull($repoPath) {
$gitPull = new Process('git pull', $repoPath);
$gitPull->run();
if (!$gitPull->isSuccessful()) {
$msg = "Unable to run 'git pull'. Output: " . $gitPull->getErrorOutput();
throw new \Exception($msg);
}
}
/**
* @param $repoURL
* @param $repoPath
*
* @throws \Exception
*/
public function clone($repoURL, $repoPath) {
$process = new Process("git clone {$repoURL} {$repoPath}");
$process->run();
if (!$process->isSuccessful()) {
$msg = "Unable to run 'git clone'. Output: " . $process->getErrorOutput();
throw new \Exception($msg);
}
}
/**
* @param $repoPath
*
* @throws \Exception
*/
public function fetch($repoPath) {
$process = new Process('git fetch', $repoPath);
$process->run();
if (!$process->isSuccessful()) {
$msg = "Unable to run 'git fetch'. Output: " . $process->getErrorOutput();
throw new \Exception($msg);
}
}
/**
* If we are on the not on the correct branch, attempt to check it out
* (first locally, then remotely).
*
* @param string $repoPath
* @param string $branch
*/
public function checkout(string $repoPath, string $branch) {
$currentBranch = $this->getCurrentBranch($repoPath);
if ($currentBranch != $branch) {
if (!$this->localBranchExists($repoPath, $branch)) {
if (!$this->remoteBranchExists($repoPath, $branch)) {
$err = "'{$branch}' branch does not exist " . "remotely or locally.";
throw new \Exception($err);
}
}
$process = new Process("git checkout {$branch}", $repoPath);
$process->run();
if (!$process->isSuccessful()) {
$err = "Unable to run 'git checkout'\n" . $process->getErrorOutput();
throw new \Exception($err);
}
}
}
/**
* @param $repoPath
* @param $branch
*
* @return bool
*/
private function localBranchExists($repoPath, $branch) {
$cmd = "git show-ref --verify refs/heads/{$branch}";
$process = new Process($cmd, $repoPath);
$process->run();
return $process->isSuccessful();
}
/**
* @param $repoPath
* @param $branch
*
* @return bool
*/
private function remoteBranchExists($repoPath, $branch) {
$cmd = sprintf("git show-ref --verify refs/remotes/origin/{$branch}");
$process = new Process($cmd, $repoPath);
$process->run();
return $process->isSuccessful();
}
}
<?php
namespace AppBundle\Utils;
class Paths {
/**
* @var string The root of the application
*/
protected $kernelRoot;
/**
* @var string The cache directory for the current environment
*/
protected $cacheDir;
/**
* @param string $kernelRoot
* @param string $cacheDir
*/
public function __construct($kernelRoot, $cacheDir) {
$this->kernelRoot = $kernelRoot;
$this->cacheDir = $cacheDir;
}
/**
* @return string
*/
public function getKernelRoot(): string {
return $this->kernelRoot;
}
/**
* @return string
*/
public function getPublishPathRoot(): string {
return $this->kernelRoot . '/../web';
}
/**
* @return string
*/
public function getRepoPathRoot(): string {
return $this->kernelRoot . '/../var/repos';
}
/**
* @return string
*/
public function getCacheDir(): string {
return $this->cacheDir;
}
}
This diff is collapsed.
<?php
namespace AppBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector;
use Symfony\Component\HttpFoundation\Response;
class PublishControllerTest extends WebTestCase {
/**
* Check that listen endpoint is working and sends mail
*/
public function testListenAction() {
$client = static::createClient();
$client->enableProfiler();
$body = $this->getGithubRequestBody();
$headers = $this->getHeaders();
$endpoint = '/admin/listen';
$client->request('POST', $endpoint, [], [], $headers, $body);
$statusCode = $client->getResponse()->getStatusCode();
$this->assertEquals(Response::HTTP_OK, $statusCode);
/** @var MessageDataCollector $mailCollector */
$mailCollector = $client->getProfile()->getCollector('swiftmailer');
/** @var \Swift_Message[] $mails */
$mails = $mailCollector->getMessages();
$this->assertCount(1, $mails);
$sentMessage = array_shift($mails);
$this->assertContains('Publishing Successful', $sentMessage->getBody());
}
/**
* @return string
*/
private function getGithubRequestBody(): string {
$body = [
'ref' => 'refs/heads/master',
'commits' => [],
'repository' => [
'html_url' => 'https://github.com/civicrm/civicrm-dev-docs',
],
];
return json_encode($body);
}
/**
* @return array
*/
private function getHeaders(): array {
$headers = [
'HTTP_X-GitHub-Event' => 'push', // prefix required for non-standard
'Content-Type' => 'application/json'
];
return $headers;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment