Files
landing-api/app/Console/Commands/SyncRepositories.php
Josep Piguillem 3897113313 Initial commit: Pireon Admin — headless admin panel and public API
Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer
collective, backed by the Pireon OAuth identity server. The public site is a
separate, server-rendered application consuming /api/public/v1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 17:55:27 +02:00

99 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Jobs\SyncRepository;
use App\Models\Repository;
use App\Services\Git\GitException;
use App\Services\Git\GitManager;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
class SyncRepositories extends Command
{
protected $signature = 'repos:sync
{repository?* : Limit to these "owner/repo" names}
{--force : Sync even if refreshed recently}
{--sync : Run inline instead of dispatching to the queue}';
protected $description = 'Refresh repository stats and newcomer-friendly issues from their git provider';
public function handle(GitManager $git): int
{
$repositories = Repository::query()
->when(
$names = $this->argument('repository'),
fn ($q) => $q->whereIn('full_name', $names),
)
->unless(
$this->option('force') || $names,
// Skip anything refreshed recently so a manual sync is not
// immediately redone by the scheduled run.
fn ($q) => $q->where(fn ($sub) => $sub
->whereNull('last_synced_at')
->orWhere('last_synced_at', '<', now()->subMinutes((int) config('git.sync_ttl_minutes', 55)))),
)
->get();
if ($repositories->isEmpty()) {
$this->components->info('Nothing to sync.');
return self::SUCCESS;
}
// Running inline gives immediate, readable output — useful when
// setting things up or debugging a failing repository.
if ($this->option('sync')) {
return $this->runInline($git, $repositories);
}
$repositories->each(fn (Repository $repo) => SyncRepository::dispatch($repo));
$this->components->info("Queued {$repositories->count()} repositories for syncing.");
return self::SUCCESS;
}
/**
* @param Collection<int, Repository> $repositories
*/
protected function runInline(GitManager $git, $repositories): int
{
$failed = 0;
foreach ($repositories as $repository) {
try {
$synced = $git->sync($repository);
$this->components->twoColumnDetail(
$repository->full_name,
sprintf(
'<fg=green>%d★</> · %d issues · %s',
$synced->stars,
$synced->goodFirstIssues()->count(),
$synced->pushed_at?->diffForHumans() ?? 'never pushed',
),
);
} catch (GitException $e) {
$failed++;
$this->components->twoColumnDetail(
$repository->full_name,
'<fg=red>'.$e->getMessage().'</>',
);
}
}
if ($failed > 0) {
$this->newLine();
$this->components->warn("{$failed} repository(ies) failed to sync.");
return self::FAILURE;
}
return self::SUCCESS;
}
}