From 46063841c4494d69736e44df06c83e039daaeab1 Mon Sep 17 00:00:00 2001 From: Paul Radt Date: Mon, 12 May 2025 14:21:17 +0200 Subject: [PATCH 1/4] Add option to reload configuration, for e.g. when used in a multi tenancy environment and the command is called from another command and the config has been changed. --- src/Commands/BackupCommand.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index 3ddeb225..228d35e0 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -15,7 +15,7 @@ class BackupCommand extends BaseCommand implements Isolatable { use Retryable; - protected $signature = 'backup:run {--filename=} {--only-db} {--db-name=*} {--only-files} {--only-to-disk=} {--disable-notifications} {--timeout=} {--tries=}'; + protected $signature = 'backup:run {--filename=} {--only-db} {--db-name=*} {--only-files} {--only-to-disk=} {--disable-notifications} {--timeout=} {--tries=} {--reload-config}'; protected $description = 'Run the backup.'; @@ -34,6 +34,10 @@ public function handle(): int set_time_limit((int) $this->option('timeout')); } + if ($this->option('reload-config')) { + $this->config = Config::fromArray(config('backup')); + } + try { $this->guardAgainstInvalidOptions(); From 23fd746fb040c6a36721fe6dd30199a38afa6ba1 Mon Sep 17 00:00:00 2001 From: Paul Radt Date: Tue, 12 Aug 2025 11:40:45 +0200 Subject: [PATCH 2/4] - Renamed option and added option to specify configuration name - Added test - Added documentation --- docs/cleaning-up-old-backups/overview.md | 5 +++++ docs/taking-backups/overview.md | 8 +++++++- src/Commands/BackupCommand.php | 10 ++++----- src/Commands/CleanupCommand.php | 6 +++++- tests/Commands/BackupCommandTest.php | 26 ++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/docs/cleaning-up-old-backups/overview.md b/docs/cleaning-up-old-backups/overview.md index 183eef56..19dcd671 100644 --- a/docs/cleaning-up-old-backups/overview.md +++ b/docs/cleaning-up-old-backups/overview.md @@ -11,6 +11,11 @@ You can clean up your backups by running: php artisan backup:clean ``` +If you want to clean a backup with a specific configuration with a specific configuration, run: +```bash +php artisan backup:clean --config=backup +``` + We'll tell you right off the bat that the package by default will never delete the latest backup regardless of its size or age. ## Determining which backups should be deleted diff --git a/docs/taking-backups/overview.md b/docs/taking-backups/overview.md index d656694f..afc2cf17 100644 --- a/docs/taking-backups/overview.md +++ b/docs/taking-backups/overview.md @@ -104,7 +104,13 @@ This section of the configuration determines which files and databases will be b The specified databases will be dumped and, together with the selected files, zipped. The zip file will be named`/.zip`. The more files you need to backup, the bigger the zip will become. Make sure there's enough free space on your disk to create the zip file. After the source zip file has been copied to all destinations, it will be deleted. - + +If you want to backup with a specific configuration (in this example 'backup'), or reload it runtime (for e.g. when you make runtime changes for multiple tenants backup), run: + +```bash +php artisan backup:run --config=backup +``` + ### Determining the destination of the backup The zipped backup can be copied to one or more filesystems. This section of the configuration is where you specify those destination filesystems. diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index 228d35e0..b17217ca 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -15,7 +15,7 @@ class BackupCommand extends BaseCommand implements Isolatable { use Retryable; - protected $signature = 'backup:run {--filename=} {--only-db} {--db-name=*} {--only-files} {--only-to-disk=} {--disable-notifications} {--timeout=} {--tries=} {--reload-config}'; + protected $signature = 'backup:run {--filename=} {--only-db} {--db-name=*} {--only-files} {--only-to-disk=} {--disable-notifications} {--timeout=} {--tries=} {--config=}'; protected $description = 'Run the backup.'; @@ -34,8 +34,8 @@ public function handle(): int set_time_limit((int) $this->option('timeout')); } - if ($this->option('reload-config')) { - $this->config = Config::fromArray(config('backup')); + if ($this->option('config')) { + $this->config = Config::fromArray(config($this->option('config') ?? 'backup')); } try { @@ -96,8 +96,8 @@ public function handle(): int if (! $disableNotifications) { event( $exception instanceof BackupFailed - ? new BackupHasFailed($exception->getPrevious(), $exception->backupDestination) - : new BackupHasFailed($exception) + ? new BackupHasFailed($exception->getPrevious(), $exception->backupDestination) + : new BackupHasFailed($exception) ); } diff --git a/src/Commands/CleanupCommand.php b/src/Commands/CleanupCommand.php index be4b5332..76f1b0f7 100644 --- a/src/Commands/CleanupCommand.php +++ b/src/Commands/CleanupCommand.php @@ -16,7 +16,7 @@ class CleanupCommand extends BaseCommand implements Isolatable use Retryable; /** @var string */ - protected $signature = 'backup:clean {--disable-notifications} {--tries=}'; + protected $signature = 'backup:clean {--disable-notifications} {--tries=} {--config=}'; /** @var string */ protected $description = 'Remove all backups older than specified number of days in config.'; @@ -36,6 +36,10 @@ public function handle(): int $this->setTries('cleanup'); + if ($this->option('config')) { + $this->config = Config::fromArray(config($this->option('config') ?? 'backup')); + } + try { $backupDestinations = BackupDestinationFactory::createFromArray($this->config); diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php index a51564ae..92878f2c 100644 --- a/tests/Commands/BackupCommandTest.php +++ b/tests/Commands/BackupCommandTest.php @@ -514,3 +514,29 @@ Storage::disk('local')->assertExists($this->expectedZipPath); }); + +it('can backup with runtime changed configuration', function () { + $this->date = Carbon::create('2025', 8, 1, 10, 1, 1); + Carbon::setTestNow($this->date); + + config()->set('backup.backup.destination.filename_prefix', 'prefix1_'); + $this->expectedZipPath = 'mysite/prefix1_2025-08-01-10-01-01.zip'; + $this->artisan('backup:run', ['--only-files' => true])->assertExitCode(0); + + Storage::disk('local')->assertExists($this->expectedZipPath); + Storage::disk('secondLocal')->assertExists($this->expectedZipPath); + + // Now change the configuration + config()->set('backup.backup.destination.filename_prefix', 'prefix2_'); + $this->expectedZipPath = 'mysite/prefix2_2025-08-01-10-01-01.zip'; + + // Run again without the config option, files should not exist + $this->artisan('backup:run', ['--only-files' => true])->assertExitCode(0); + Storage::disk('local')->assertMissing($this->expectedZipPath); + Storage::disk('secondLocal')->assertMissing($this->expectedZipPath); + + // Run again with specified configuration, backup should be created + $this->artisan('backup:run', ['--only-files' => true, '--config' => 'backup'])->assertExitCode(0); + Storage::disk('local')->assertExists($this->expectedZipPath); + Storage::disk('secondLocal')->assertExists($this->expectedZipPath); +}); From 7d4d5c721b481553182f6b0e51d0da4b73829a4e Mon Sep 17 00:00:00 2001 From: Paul Radt Date: Mon, 18 Aug 2025 15:05:25 +0200 Subject: [PATCH 3/4] Add example for using config option from console command --- docs/taking-backups/overview.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/taking-backups/overview.md b/docs/taking-backups/overview.md index afc2cf17..709e8a8a 100644 --- a/docs/taking-backups/overview.md +++ b/docs/taking-backups/overview.md @@ -111,6 +111,17 @@ If you want to backup with a specific configuration (in this example 'backup'), php artisan backup:run --config=backup ``` +Possible situations where you might want to do this are for e.g., when you want to backup multiple tenants at the same time from a console command: +```php + +$tenants = ['tenant1', 'tenant2']; + +foreach ($tenants as $tenant) { + config(['backup.backup.destination.filename_prefix' => $tenant.'_']); + $this->call('backup:run', ['--timeout' => 120, '--config' => 'backup']); +} +``` + ### Determining the destination of the backup The zipped backup can be copied to one or more filesystems. This section of the configuration is where you specify those destination filesystems. From feb3e956aa119c1aeac6e5de8ad91d4a1ebf6039 Mon Sep 17 00:00:00 2001 From: Paul Radt Date: Mon, 25 Aug 2025 08:57:03 +0200 Subject: [PATCH 4/4] Update documentation --- docs/taking-backups/overview.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/taking-backups/overview.md b/docs/taking-backups/overview.md index 709e8a8a..e2d76565 100644 --- a/docs/taking-backups/overview.md +++ b/docs/taking-backups/overview.md @@ -105,23 +105,31 @@ The specified databases will be dumped and, together with the selected files, zi The more files you need to backup, the bigger the zip will become. Make sure there's enough free space on your disk to create the zip file. After the source zip file has been copied to all destinations, it will be deleted. -If you want to backup with a specific configuration (in this example 'backup'), or reload it runtime (for e.g. when you make runtime changes for multiple tenants backup), run: +### Running backups with a specific configuration +If you want to back up different areas of your Laravel application separately – for example with different schedules, database connections, filesystem disks, or cleanup settings – you can create custom backup configuration files. -```bash -php artisan backup:run --config=backup -``` +#### Example: +Additional config files placed in the config/ directory: -Possible situations where you might want to do this are for e.g., when you want to backup multiple tenants at the same time from a console command: -```php +- config/backup_database.php +- config/backup_invoices.php +- config/backup_uploads.php -$tenants = ['tenant1', 'tenant2']; +You can then run backups and cleanup commands individually: -foreach ($tenants as $tenant) { - config(['backup.backup.destination.filename_prefix' => $tenant.'_']); - $this->call('backup:run', ['--timeout' => 120, '--config' => 'backup']); -} +```bash +php artisan backup:run --config=backup_database +php artisan backup:clean --config=backup_database + +php artisan backup:run --config=backup_invoices +php artisan backup:clean --config=backup_invoices + +php artisan backup:run --config=backup_uploads +php artisan backup:clean --config=backup_uploads ``` +This allows full flexibility in scheduling, retention, and target destinations for each backup scope. + ### Determining the destination of the backup The zipped backup can be copied to one or more filesystems. This section of the configuration is where you specify those destination filesystems.