diff --git a/app/Console/Commands/Bundle/Render.php b/app/Console/Commands/Bundle/Render.php
index 4768daa..e12d862 100644
--- a/app/Console/Commands/Bundle/Render.php
+++ b/app/Console/Commands/Bundle/Render.php
@@ -4,6 +4,7 @@
use App\Classes\Bundle;
use Illuminate\Console\Command;
+use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -13,13 +14,6 @@
class Render extends Command
{
- /**
- * The name and signature of the console command.
- *
- * @var string
- */
- protected $signature = 'bundle:render { --a|assets : Rebuild assets }';
-
/**
* The console command description.
*
@@ -27,49 +21,219 @@ class Render extends Command
*/
protected $description = 'Render bundles';
+ protected Filesystem $sourceDisk;
+
+ protected Filesystem $targetDisk;
+
+ public function __construct()
+ {
+ $this->signature = 'bundle:render
+ { --a|assets : Rebuild assets - implies -c }
+ { --c|clear-cache : Clear cache before rendering }
+ { --d|dry-run : Show what would be done but do nothing }
+ { --no-deploy : Do not deploy, do not ask to deploy }
+ { --r|recursive : Also render sub-bundles }
+ { --source-disk= : Use specified content disk - Defaults to ' . env('CONTENT_DISK') . ' }
+ { --target-disk= : Use specified rendering disk - Defaults to ' . env('DIST_DISK') . ' }
+ { path? : Path to a specific bundle to render - Default to / }
+ ';
+
+ parent::__construct();
+ }
+
/**
* Execute the console command.
*/
public function handle()
{
- if ($this->option('assets')) {
- $this->output->write('Building assets... ');
- Process::run('npm run build')->throw();
- $this->info('OK');
+ $this->showDisclaimer()
+ ->selectDisk()
+ ->renderAssets()
+ ->clearCache()
+ ->render()
+ ->deploy();
+ }
- $this->call('cache:clear');
+ /**
+ * Show a "disclaimer" for running dry-mode
+ */
+ private function showDisclaimer(): self
+ {
+ if (!$this->option('dry-run')) {
+ return $this;
}
- $path = '/';
- $bundles = Bundle::findBundles(Storage::disk(env('CONTENT_DISK')), $path, true);
- $progress = progress(label: 'Rendering... ', steps: count($bundles));
- $progress->start();
+ $this->newLine();
+ $this->warn('Running dry-mode: no modification will be done');
+ $this->newLine();
- foreach ($bundles as $bundle) {
- $result = $bundle->render();
+ return $this;
+ }
- foreach ($result as $path => $content) {
- if (!Str::contains($path, '.')) {
- $path = Str::finish($path, '/') . 'index.html';
- }
+ /**
+ * Select the disk we will be working on
+ */
+ private function selectDisk(): self
+ {
+ $sourceDisk = $this->option('source-disk') ?? env('CONTENT_DISK');
+ $targetDisk = $this->option('target-disk') ?? env('DIST_DISK');
- Storage::disk(env('DIST_DISK'))->put($path, $content);
+ $this->sourceDisk = Storage::disk($sourceDisk);
+ $this->targetDisk = Storage::disk($targetDisk);
+
+ $this->comment(
+ sprintf(
+ 'Using `%s` as source disk and `%s` as target disk for generated content',
+ $sourceDisk,
+ $targetDisk
+ )
+ );
+
+ return $this;
+ }
+
+ /**
+ * Build assets, and clear cache afterwise
+ */
+ private function renderAssets(): self
+ {
+ // Do not re-generate assets if we didn't explicitely asked for it
+ if (!$this->option('assets')) {
+ return $this;
+ }
+
+ $this->output->write('Building assets... ');
+
+ if (!$this->option('dry-run')) {
+ Process::run('npm run build')->throw();
+ }
+
+ $this->info('OK');
+
+ return $this;
+ }
+
+ /**
+ * Clear application cache
+ */
+ private function clearCache(): self
+ {
+ // Do not clear cache if we didn't explicitely asked for it
+ if (!$this->option('clear-cache') && !$this->option('assets')) {
+ return $this;
+ }
+
+ // For now, we need to clear the cache, otherwise rendered HTML will
+ // still reference old assets
+ $this->output->write('Clearing cache... ');
+
+ if (!$this->option('dry-run')) {
+ $this->call('cache:clear', ['--quiet']);
+ }
+
+ $this->info('OK');
+
+ return $this;
+ }
+
+ /**
+ * Collect a list of bundles to render
+ */
+ private function getBundles()
+ {
+ $path = $this->argument('path') ?? '/';
+ $comment = sprintf('Rendering %s', $path);
+
+ if ($this->option('recursive')) {
+ $comment .= ' and all sub-bundles';
+ }
+
+ $this->comment($comment);
+ $this->output->write('Collecting bundles... ');
+
+ if ($this->option('recursive')) {
+ $bundles = Bundle::findBundles($this->sourceDisk, $path, true);
+ } else {
+ $bundles = [new Bundle($path, $this->sourceDisk)];
+ }
+
+ $this->info('OK');
+
+ return $bundles;
+ }
+
+ /**
+ * Perform rendering
+ */
+ private function render(): self
+ {
+ $bundles = $this->getBundles();
+
+ progress(
+ label: 'Rendering... ',
+ steps: $bundles,
+ callback: fn (Bundle $bundle, $progress) => $this->handleBundle($bundle, $progress)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Handle specific bundle
+ */
+ private function handleBundle(Bundle $bundle, $progress)
+ {
+ $progress->label(sprintf('Rendering %s ...', $bundle->getPath()));
+
+ if ($this->option('dry-run')) {
+ return;
+ }
+
+ $progress->hint('Rendering the bundle');
+
+ $result = $bundle->render();
+
+ foreach ($result as $path => $content) {
+ if (!Str::contains($path, '.')) {
+ $path = Str::finish($path, '/') . 'index.html';
}
- $progress->advance();
- }
+ $progress->hint(sprintf('Storing %s', $path));
- $progress->finish();
-
- if (confirm('Ready to deploy?')) {
- $this->output->write('Deploying... ');
- $source = Str::finish(Storage::disk(env('DIST_DISK'))->path('/'), '/');
- $target = env('DEPLOY_TARGET');
-
- $command = sprintf('rsync -az -L --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r --chown=caddy:caddy --delete "%s" "%s"', $source, $target);
-
- Process::run($command)->throw();
- $this->info('OK');
+ $this->targetDisk->put($path, $content);
}
}
+
+ /**
+ * Deploy to remote server
+ */
+ private function deploy()
+ {
+ // Do not even ask if --no-deploy was used
+ if ($this->option('no-deploy')) {
+ return;
+ }
+
+ // Ask for confirmation
+ if (!confirm('Ready to deploy?')) {
+ $this->comment('OK, not deploying!');
+
+ return;
+ }
+
+ $source = Str::finish($this->targetDisk->path('/'), '/');
+ $target = env('DEPLOY_TARGET');
+ $command = __(env('DEPLOY_COMMAND'), [
+ 'source' => $source,
+ 'target' => $target,
+ ]);
+
+ $this->output->write(sprintf('Deploying using `%s` ... ', $command));
+
+ if (!$this->option('dry-run')) {
+ Process::run($command)->throw();
+ }
+
+ $this->info('OK');
+ }
}