Skip to content

Commit

Permalink
Warnings, Skips, and Failures (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonvarga committed Oct 7, 2021
1 parent 0567f0e commit 3ddc8f8
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 31 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ class AppServiceProvider extends Provider
}
```


## Triggering Command Failures

If you are using the SSG in a CI environment, you may want to prevent the command from succeeding if any pages aren't generated (e.g. to prevent deployment of an incomplete site).

By default, the command will finish and exit with a success code even if there were un-generated pages. You can tell configure the SSG to fail early on errors, or even on warnings.

```php
'failures' => 'errors', // or 'warnings'
```


## Deployment Examples

These examples assume your workflow will be to author content **locally** and _not_ using the control panel in production.
Expand Down
13 changes: 13 additions & 0 deletions config/ssg.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,17 @@
'directory' => 'img',
],

/*
|--------------------------------------------------------------------------
| Failures
|--------------------------------------------------------------------------
|
| You may configure whether the console command will exit early with a
| failure status code when it encounters errors or warnings. You may
| want to do this to prevent deployments in CI environments, etc.
|
*/

'failures' => false, // 'errors' or 'warnings'

];
15 changes: 12 additions & 3 deletions src/Commands/StaticSiteGenerate.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Console\Command;
use Statamic\StaticSite\Generator;
use Statamic\Console\RunsInPlease;
use Statamic\StaticSite\GenerationFailedException;
use Wilderborn\Partyline\Facade as Partyline;

class StaticSiteGenerate extends Command
Expand Down Expand Up @@ -55,8 +56,16 @@ public function handle()
$this->comment('You may be able to speed up site generation significantly by installing spatie/fork and using multiple workers (requires PHP 8+).');
}

$this->generator
->workers($workers ?? 1)
->generate();
try {
$this->generator
->workers($workers ?? 1)
->generate();
} catch (GenerationFailedException $e) {
$this->line($e->getConsoleMessage());
$this->error('Static site generation failed.');
return 1;
}

return 0;
}
}
25 changes: 25 additions & 0 deletions src/GenerationFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Statamic\StaticSite;

class GenerationFailedException extends \Exception
{
private $consoleMessage;

public static function withConsoleMessage($message)
{
return (new static)->setConsoleMessage($message);
}

public function setConsoleMessage($message)
{
$this->consoleMessage = $message;

return $this;
}

public function getConsoleMessage()
{
return $this->consoleMessage;
}
}
98 changes: 70 additions & 28 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,10 @@ class Generator
protected $config;
protected $request;
protected $after;
protected $count = 0;
protected $skips = 0;
protected $warnings = 0;
protected $viewPaths;
protected $extraUrls;
protected $workers = 1;
protected $taskResults;

public function __construct(Application $app, Filesystem $files, Router $router, Tasks $tasks)
{
Expand Down Expand Up @@ -90,17 +88,8 @@ public function generate()
->clearDirectory()
->createContentFiles()
->createSymlinks()
->copyFiles();

Partyline::info('Static site generated into ' . $this->config['destination']);

if ($this->skips) {
Partyline::warn("[!] {$this->skips}/{$this->count} pages not generated");
}

if ($this->warnings) {
Partyline::warn("[!] {$this->warnings}/{$this->count} pages generated with warnings");
}
->copyFiles()
->outputSummary();

if ($this->after) {
call_user_func($this->after);
Expand Down Expand Up @@ -167,6 +156,8 @@ public function copyFiles()

Partyline::line("<info>[✔]</info> $source copied to $dest");
}

return $this;
}

protected function createContentFiles()
Expand All @@ -184,11 +175,33 @@ protected function createContentFiles()

$results = $this->tasks->run(...$closures);

$this->outputResults($results);
if ($this->anyTasksFailed($results)) {
throw GenerationFailedException::withConsoleMessage("\x1B[1A\x1B[2K");
}

$this->taskResults = $this->compileTasksResults($results);

$this->outputTasksResults();

return $this;
}

protected function anyTasksFailed($results)
{
return collect($results)->contains('');
}

protected function compileTasksResults(array $results)
{
$results = collect($results);

return [
'count' => $results->sum('count'),
'warnings' => $results->flatMap->warnings,
'errors' => $results->flatMap->errors,
];
}

protected function gatherContent()
{
Partyline::line('Gathering content to be generated...');
Expand Down Expand Up @@ -225,7 +238,8 @@ protected function makeContentGenerationClosures($pages, $request)
{
return $pages->split($this->workers)->map(function ($pages) use ($request) {
return function () use ($pages, $request) {
$count = $skips = $warnings = 0;
$count = 0;
$warnings = [];
$errors = [];

foreach ($pages as $page) {
Expand All @@ -242,33 +256,50 @@ protected function makeContentGenerationClosures($pages, $request)
try {
$generated = $page->generate($request);
} catch (NotGeneratedException $e) {
$skips++;
if ($this->shouldFail($e)) {
throw GenerationFailedException::withConsoleMessage("\x1B[1A\x1B[2K".$e->consoleMessage());
}

$errors[] = $e->consoleMessage();
continue;
}

if ($generated->hasWarning()) {
$warnings++;
if ($this->shouldFail($generated)) {
throw GenerationFailedException::withConsoleMessage($generated->consoleMessage());
}

$warnings[] = $generated->consoleMessage();
}
}

return compact('count', 'skips', 'warnings', 'errors');
return compact('count', 'warnings', 'errors');
};
})->all();
}

protected function outputResults($results)
protected function outputTasksResults()
{
$results = collect($results);
$results = $this->taskResults;

Partyline::line("\x1B[1A\x1B[2K<info>[✔]</info> Generated {$results['count']} content files");

$results['warnings']->merge($results['errors'])->each(fn ($error) => Partyline::line($error));
}

protected function outputSummary()
{
Partyline::info('');
Partyline::info('Static site generated into ' . $this->config['destination']);

$total = $this->taskResults['count'];

Partyline::line("\x1B[1A\x1B[2K<info>[✔]</info> Generated {$results->sum('count')} content files");
if ($errors = count($this->taskResults['errors'])) {
Partyline::warn("[!] {$errors}/{$total} pages not generated");
}

if ($results->sum('skips')) {
$results->reduce(function ($carry, $item) {
return $carry->merge($item['errors']);
}, collect())->each(function ($error) {
Partyline::line($error);
});
if ($warnings = count($this->taskResults['warnings'])) {
Partyline::warn("[!] {$warnings}/{$total} pages generated with warnings");
}
}

Expand Down Expand Up @@ -367,4 +398,15 @@ protected function checkConcurrencySupport()

throw new \RuntimeException('To use multiple workers, you must install PHP 8 and spatie/fork.');
}

protected function shouldFail($item)
{
$config = $this->config['failures'];

if ($item instanceof NotGeneratedException) {
return in_array($config, ['warnings', 'errors']);
}

return $config === 'warnings';
}
}

0 comments on commit 3ddc8f8

Please sign in to comment.