Skip to content

Commit

Permalink
feat: adding freeze and unfreeze commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaile committed May 15, 2024
1 parent c9c259c commit 8dcd245
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,23 @@ Repository syncs are dispatched by the scheduler daily. If you want to manually
```bash
php artisan repository:sync cool_repository
```

### Freezing repositories

To freeze a repository, you can use the `php artisan repository:freeze {repository_name}` command.

```bash
php artisan repository:freeze cool_repository
```

Parcel will prompt for the repository name if not provided.

### Unfreezing repositories

To unfreeze a repository, you can use the `php artisan repository:unfreeze {repository_name}` command.

```bash
php artisan repository:unfreeze cool_repository
```

Parcel will prompt for the repository name if not provided.
70 changes: 70 additions & 0 deletions app/Console/Commands/FreezeRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace App\Console\Commands;

use App\Models\Repository;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use Illuminate\Database\Eloquent\ModelNotFoundException;

use function Laravel\Prompts\select;

class FreezeRepository extends Command implements PromptsForMissingInput
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'repository:freeze {repository} {directory?}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Freeze specified repository';

/**
* Execute the console command.
*/
public function handle(): int
{
$repoName = $this->argument('repository');
try {
$repository = Repository::where('name', $repoName)->firstOrFail();
} catch (ModelNotFoundException) {
$this->error("Repository '$repoName' not found.");
return self::FAILURE;
}
if ($repository->freeze != null) {
$this->error("Repository '$repository->name' is already frozen.");
return self::FAILURE;
}
if (is_null($this->argument('directory'))) {
$directory = basename($repository->getStablePath());
} else {
$directory = $this->argument('directory');
}
$this->info("Freezing repository '$repository->name' to '$directory'...");
$repository->freeze = $directory;
$repository->save();
return self::SUCCESS;
}

/**
* Prompt for missing input arguments using the returned questions.
*
* @return array<string, string>
*/
protected function promptForMissingArgumentsUsing(): array
{
return [
'repository' => fn () => select(
label: 'Choose repository to freeze',
options: Repository::pluck('name'),
required: true,
),
];
}
}
64 changes: 64 additions & 0 deletions app/Console/Commands/UnFreezeRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace App\Console\Commands;

use App\Models\Repository;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use function Laravel\Prompts\select;

class UnFreezeRepository extends Command implements PromptsForMissingInput
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'repository:unfreeze {repository}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Unfreeze a frozen repository.';

/**
* Execute the console command.
*/
public function handle(): int
{
$repoName = $this->argument('repository');
try {
$repository = Repository::where('name', $repoName)->firstOrFail();
} catch (ModelNotFoundException) {
$this->error("Repository '$repoName' not found.");
return self::FAILURE;
}
if ($repository->freeze == null) {
$this->error("Repository '$repository->name' is not frozen.");
return self::FAILURE;
}
$this->info("Unfreezing repository '$repository->name'...");
$repository->freeze = null;
$repository->save();
return self::SUCCESS;
}

/**
* Prompt for missing input arguments using the returned questions.
*
* @return array<string, string>
*/
protected function promptForMissingArgumentsUsing(): array
{
return [
'repository' => fn () => select(
label: 'Choose repository to unfreeze',
options: Repository::pluck('name'),
required: true,
),
];
}
}
95 changes: 95 additions & 0 deletions tests/Feature/FreezeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use App\Models\Repository;
use Illuminate\Support\Facades\Storage;

use function Pest\Laravel\artisan;

it('returns frozen directory', function () {
Storage::fake();
$repository = Repository::factory()->create([
Expand All @@ -17,3 +19,96 @@
expect($repository->getStablePath())
->toBe($snapshotPath.'/frozen');
});

it('can freeze repository with interactive choice', function () {
$repository = Repository::factory()->create([
'delay' => 7,
]);
$directories = [
now()->subDays(8)->toAtomString(),
now()->subDays(6)->toAtomString(),
now()->subDays(5)->toAtomString(),
now()->subDays(4)->toAtomString(),
'cool_custom_directory',
];
Storage::fake();
foreach ($directories as $directory) {
Storage::createDirectory($repository->snapshotDir().'/'.$directory);
}
artisan('repository:freeze')
->expectsChoice('Choose repository to freeze', $repository->name, [$repository->name])
->expectsOutput("Freezing repository '$repository->name' to '$directories[1]'...")
->assertSuccessful();
$repository->refresh();
expect($repository->freeze)
->toBe($directories[1])
->and($repository->getStablePath())
->toBe($repository->snapshotDir().'/'.$directories[1]);
});

it('cannot freeze not existing directory')
->artisan('repository:freeze', ['repository' => 'wrong_repo'])
->expectsOutput("Repository 'wrong_repo' not found.")
->assertFailed();

it('cannot freeze already frozen repository', function () {
$repository = Repository::factory()->freeze()->create();
artisan('repository:freeze', ['repository' => $repository->name])
->expectsOutput("Repository '$repository->name' is already frozen.")
->assertFailed();
});

it('can freeze repository with custom directory', function () {
$repository = Repository::factory()->create([
'delay' => 7,
]);
Storage::fake();
$directories = [
now()->subDays(8)->toAtomString(),
now()->subDays(6)->toAtomString(),
now()->subDays(5)->toAtomString(),
now()->subDays(4)->toAtomString(),
'cool_custom_directory',
];
foreach ($directories as $directory) {
Storage::createDirectory($repository->snapshotDir().'/'.$directory);
}
artisan('repository:freeze', ['repository' => $repository->name, 'directory' => $directories[4]])
->expectsOutput("Freezing repository '$repository->name' to '$directories[4]'...")
->assertSuccessful();
$repository->refresh();
});

it('cannot unfroze not existing repository')
->artisan('repository:unfreeze', ['repository' => 'wrong_repo'])
->expectsOutput("Repository 'wrong_repo' not found.")
->assertFailed();

it('cannot unfreeze not frozen repository', function () {
$repository = Repository::factory()->create();
artisan('repository:unfreeze', ['repository' => $repository->name])
->expectsOutput("Repository '$repository->name' is not frozen.")
->assertFailed();
});


it('can unfreeze repository with interactive choice', function () {
$repository = Repository::factory()->freeze()->create();
artisan('repository:unfreeze')
->expectsChoice('Choose repository to unfreeze', $repository->name, [$repository->name])
->expectsOutput("Unfreezing repository '$repository->name'...")
->assertSuccessful();
$repository->refresh();
expect($repository->freeze)
->toBeNull();
});

it('can unfreeze repository', function () {
$repository = Repository::factory()->freeze()->create();
artisan('repository:unfreeze', ['repository' => $repository->name])
->expectsOutput("Unfreezing repository '$repository->name'...")
->assertSuccessful();
$repository->refresh();
expect($repository->freeze)
->toBeNull();
});

0 comments on commit 8dcd245

Please sign in to comment.