Skip to content

Commit 5d111cf

Browse files
committed
using moox prompts for command, add multiselect for repository creating
1 parent 0bade7f commit 5d111cf

File tree

2 files changed

+62
-65
lines changed

2 files changed

+62
-65
lines changed

packages/monorepo/src/Commands/CreateMissingRepositoriesCommand.php

Lines changed: 61 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
use Moox\Monorepo\Contracts\GitHubClientInterface;
99
use Moox\Monorepo\DataTransferObjects\PackageInfo;
1010
use Moox\Monorepo\Services\DevlinkService;
11+
use function Moox\Prompts\multiselect;
12+
use function Moox\Prompts\progress;
13+
use function Moox\Prompts\table;
1114

1215
class CreateMissingRepositoriesCommand extends Command
1316
{
1417
protected $signature = 'monorepo:create-missing
1518
{--public : Only create missing public repositories}
1619
{--private : Only create missing private repositories}
1720
{--force : Skip confirmation prompts}
18-
{--interactive : Ask for confirmation before creating each repository}
1921
{--dry-run : Show what would be created without making changes}
2022
{--skip-devlink : Skip updating devlink configuration}';
2123

@@ -75,13 +77,17 @@ public function handle(): int
7577
return 0;
7678
}
7779

78-
// Ask for confirmation
80+
// Let user select which repositories to create
7981
if (! $this->option('force')) {
80-
if (! $this->confirm("Create {$missingPackages->count()} missing repositories?", true)) {
81-
$this->info('Operation cancelled.');
82+
$selectedPackages = $this->selectPackagesToCreate($missingPackages);
83+
84+
if ($selectedPackages->isEmpty()) {
85+
$this->info('No repositories selected. Operation cancelled.');
8286

8387
return 0;
8488
}
89+
90+
$missingPackages = $selectedPackages;
8591
}
8692

8793
// Create repositories
@@ -163,7 +169,7 @@ private function displayMissingPackages(Collection $missingPackages): void
163169
];
164170
})->toArray();
165171

166-
$this->table(
172+
table(
167173
['Package Name', 'Type', 'Stability', 'Description'],
168174
$tableData
169175
);
@@ -175,62 +181,62 @@ private function displayMissingPackages(Collection $missingPackages): void
175181
$this->line('');
176182
}
177183

184+
private function selectPackagesToCreate(Collection $missingPackages): Collection
185+
{
186+
// Build choice options with package details and create a mapping
187+
$choiceToPackage = [];
188+
$choices = $missingPackages->map(function ($package) use (&$choiceToPackage) {
189+
$type = $package->visibility === 'public' ? '🔓' : '🔒';
190+
$description = $package->description ? ' - ' . substr($package->description, 0, 50) : '';
191+
$choice = "{$type} {$package->name} ({$package->visibility}){$description}";
192+
193+
// Store mapping for easy lookup
194+
$choiceToPackage[$choice] = $package;
195+
196+
return $choice;
197+
})->toArray();
198+
199+
// Add "Select all" option at the beginning
200+
$selectAllOption = '✅ Select all';
201+
array_unshift($choices, $selectAllOption);
202+
203+
$selected = multiselect(
204+
label: 'Which repositories would you like to create?',
205+
options: $choices,
206+
default: [],
207+
required: false,
208+
hint: 'Use SPACE to select, ENTER to confirm'
209+
);
210+
211+
// If "Select all" was chosen, return all packages
212+
if (in_array($selectAllOption, $selected)) {
213+
return $missingPackages;
214+
}
215+
216+
// Map selected choices back to packages using the mapping
217+
$selectedPackages = collect($selected)
218+
->map(function ($choice) use ($choiceToPackage) {
219+
return $choiceToPackage[$choice] ?? null;
220+
})
221+
->filter();
222+
223+
return $selectedPackages;
224+
}
225+
178226
private function createRepositories(Collection $missingPackages, string $organization): int
179227
{
180228
$this->info('🚀 Creating missing repositories...');
181229
$this->line('');
182230

183231
$created = 0;
184232
$failed = 0;
185-
$skipped = 0;
186233
$devlinkUpdated = 0;
187234

188-
if ($this->option('interactive')) {
189-
// Interactive mode - ask for each repository
190-
foreach ($missingPackages as $index => $package) {
191-
$this->line('Repository '.($index + 1).'/'.$missingPackages->count().": {$package->name}");
192-
$this->line(" Type: {$package->visibility}");
193-
$this->line(" Stability: {$package->stability}");
194-
$this->line(' Description: '.($package->description ?: ''));
195-
196-
if ($this->confirm("Create repository for {$package->name}?", true)) {
197-
try {
198-
$this->createSingleRepository($package, $organization);
199-
$created++;
200-
$this->info(" ✅ Created: {$package->name}");
201-
202-
// Update devlink configuration
203-
if (! $this->option('skip-devlink')) {
204-
try {
205-
$this->updateDevlinkConfig($package);
206-
$devlinkUpdated++;
207-
$this->info(" 🔗 Added to devlink config: {$package->name}");
208-
} catch (\Exception $e) {
209-
$this->warn(" ⚠️ Failed to update devlink config for {$package->name}: {$e->getMessage()}");
210-
}
211-
}
212-
213-
// Small delay to avoid rate limiting
214-
usleep(100000); // 0.1 seconds
215-
} catch (\Exception $e) {
216-
$failed++;
217-
$this->error(" ❌ Failed to create {$package->name}: {$e->getMessage()}");
218-
}
219-
} else {
220-
$skipped++;
221-
$this->line(" ⏭️ Skipped: {$package->name}");
222-
}
223-
224-
$this->line('');
225-
}
226-
} else {
227-
// Batch mode with progress bar
228-
$progressBar = $this->output->createProgressBar($missingPackages->count());
229-
$progressBar->start();
230-
231-
foreach ($missingPackages as $package) {
232-
$progressBar->advance();
233-
235+
// Use Prompts progress bar
236+
progress(
237+
label: 'Creating repositories...',
238+
steps: $missingPackages,
239+
callback: function ($package) use ($organization, &$created, &$failed, &$devlinkUpdated) {
234240
try {
235241
$this->createSingleRepository($package, $organization);
236242
$created++;
@@ -253,11 +259,9 @@ private function createRepositories(Collection $missingPackages, string $organiz
253259
$this->line('');
254260
$this->error("Failed to create repository for {$package->name}: {$e->getMessage()}");
255261
}
256-
}
257-
258-
$progressBar->finish();
259-
$this->line('');
260-
}
262+
},
263+
hint: 'Creating repositories and updating devlink config'
264+
);
261265

262266
$this->line('');
263267

@@ -274,18 +278,11 @@ private function createRepositories(Collection $missingPackages, string $organiz
274278
$this->warn("⚠️ Failed to create {$failed} repositories");
275279
}
276280

277-
if ($skipped > 0) {
278-
$this->line("⏭️ Skipped {$skipped} repositories");
279-
}
280-
281281
$this->line('');
282282
$this->info('📊 Summary:');
283283
$this->line("Total packages processed: {$missingPackages->count()}");
284284
$this->line("Repositories created: {$created}");
285285
$this->line("Devlink config updated: {$devlinkUpdated}");
286-
if ($skipped > 0) {
287-
$this->line("Repositories skipped: {$skipped}");
288-
}
289286
$this->line("Failed creations: {$failed}");
290287

291288
if ($created > 0) {

packages/prompts/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "moox/prompts",
3-
"description": " Prompts is a package that provides CLI-compatible prompts for Laravel Artisan Commands with identical API to Laravel Prompts. Supports all prompt types",
3+
"description": "Prompts is a package that provides CLI-compatible prompts for Laravel Artisan Commands with identical API to Laravel Prompts. Supports all prompt types",
44
"keywords": [
55
"Moox",
66
"Laravel",

0 commit comments

Comments
 (0)