Initial commit

This commit is contained in:
Ismo Vuorinen
2022-10-17 09:42:32 +03:00
commit 78cca41be4
27 changed files with 9319 additions and 0 deletions

0
app/Commands/.gitkeep Normal file
View File

View File

@@ -0,0 +1,155 @@
<?php
namespace App\Commands;
use App\Dto\PackagistApiPackagePayload;
use Illuminate\Support\Facades\Http;
use LaravelZero\Framework\Commands\Command;
class CheckCommand extends Command {
protected $signature = 'check
{vendor : Package vendor (required)}
{package : Package name (required)}
{months=9 : How many months should we return for review (optional)}
';
protected $description = 'Check package branch usage';
private string $vendor = '';
private string $package = '';
private string $filter = '';
private int $total_branches = 0;
public function handle() : int {
$this->vendor = (string) $this->argument( 'vendor' );
$this->package = (string) $this->argument( 'package' );
$months = (int) $this->argument( 'months' );
$this->info( 'Checking: ' . sprintf( '%s/%s', $this->vendor, $this->package ) );
$this->info( 'Months: ' . $months );
$payload = Http::get( sprintf(
'https://packagist.org/packages/%s/%s.json',
$this->vendor,
$this->package
) );
$this->filter = now()->subMonths( $months )->day( 1 )->toDateString();
try {
$pkg = new PackagistApiPackagePayload( $payload->json() );
$this->info( 'Found the package. Type: ' . $pkg->type );
$versions = collect( $pkg->versions ?? [] )
->keys()
// Filter actual versions out.
->filter( fn( $version ) => \str_starts_with( $version, 'dev-' ) )
->sort();
$this->total_branches = $versions->count();
$this->info( sprintf(
'Package has %d branches. Starting to download statistics.',
$this->total_branches
) );
$statistics = collect( $versions )
->mapWithKeys( fn( $branch ) => $this->get_statistics( $branch ) )
->toArray();
$this->info( 'Downloaded statistics...' );
$this->output_table( $statistics );
$this->output_suggestions( $statistics );
}
catch ( \Exception $e ) {
$this->error( $e->getMessage(), $e );
}
return 0;
}
private function get_statistics( $branch ) : array {
$payload = Http::get( sprintf(
'https://packagist.org/packages/%s/%s/stats/%s.json?average=monthly&from=%s',
$this->vendor,
$this->package,
$branch,
$this->filter
) );
$data = collect( $payload->json() );
$labels = collect( $data->get( 'labels', [] ) )->toArray();
$values = collect( $data->get( 'values', [] ) )->flatten()->toArray();
$labels[] = 'Total';
$values[] = array_sum( $values );
return [ $branch => \array_combine( $labels, $values ) ];
}
private function output_table( array $statistics ) : void {
if ( empty( $statistics ) ) {
$this->info( 'No statistics found... Stopping.' );
exit( 0 );
}
$tableHeaders = [ '' => 'Branch' ];
$tableBranches = [];
foreach ( $statistics as $branch => $stats ) {
foreach ( $stats as $m => $v ) {
$tableHeaders[ $m ] = (string) $m;
$tableBranches[ $branch ][ $branch ] = $branch;
$tableBranches[ $branch ][ $m ] = (string) $v;
}
}
$this->line('');
$this->table( $tableHeaders, $tableBranches );
}
private function output_suggestions( array $statistics = [] ) : void {
$deletable = [];
if ( empty( $statistics ) ) {
$this->info( 'No statistics to give suggestions for. Quitting...' );
exit( 0 );
}
foreach ( $statistics as $k => $values ) {
if ( ! empty( $values['Total'] ) ) {
continue;
}
$deletable[ $k ] = $values['Total'];
}
if ( empty( $deletable ) ) {
$this->info( 'No suggestions available. Good job!' );
exit( 0 );
}
$keys = array_keys( $deletable );
$branches = collect( $keys )->mapWithKeys( function ( $branch ) {
return [
$branch => [
$branch,
sprintf(
'https://packagist.org/packages/%s/%s#%s',
$this->vendor,
$this->package,
$branch
),
],
];
} );
$this->line('');
$this->info( sprintf(
'Found %d branches (out of %d total) with no downloads since %s',
$branches->count(),
$this->total_branches,
$this->filter
) );
$this->table( [ 'Branch', 'URL' ], $branches );
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Commands;
use Illuminate\Console\Scheduling\Schedule;
use LaravelZero\Framework\Commands\Command;
use function Termwind\{render};
class InspireCommand extends Command
{
/**
* The signature of the command.
*
* @var string
*/
protected $signature = 'inspire {name=Artisan}';
/**
* The description of the command.
*
* @var string
*/
protected $description = 'Display an inspiring quote';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
render(<<<'HTML'
<div class="py-1 ml-2">
<div class="px-1 bg-blue-300 text-black">Laravel Zero</div>
<em class="ml-1">
Simplicity is the ultimate sophistication.
</em>
</div>
HTML);
}
/**
* Define the command's schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
public function schedule(Schedule $schedule)
{
// $schedule->command(static::class)->everyMinute();
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Dto;
use Spatie\DataTransferObject\DataTransferObject;
class GitHubApiBranch extends DataTransferObject {
public string $name;
public bool $protected;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Dto;
use Spatie\DataTransferObject\Attributes\MapFrom;
class PackagistApiPackagePayload extends \Spatie\DataTransferObject\DataTransferObject {
#[MapFrom('package.name')]
public string $name = '';
#[MapFrom('package.description')]
public string $description = '';
#[MapFrom('package.time')]
public string $time = '';
#[MapFrom('package.versions')]
public array $versions = [];
#[MapFrom('package.type')]
public string $type = '';
#[MapFrom('package.repository')]
public string $repository = '';
#[MapFrom('package.language')]
public string $language = '';
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Dto;
use Spatie\DataTransferObject\Attributes\MapFrom;
class PackagistApiStatsPayload extends \Spatie\DataTransferObject\DataTransferObject {
public array $labels;
#[MapFrom('values.[0]')]
public string $version;
#[MapFrom('values.[0][]')]
public array $values;
public string $average = 'monthly';
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Fetchers;
use Illuminate\Support\Facades\Http;
class GitHubRestApi {
public static function getBranches( string $vendor, string $package ) : array {
$pages = self::downloader( $vendor, $package );
$pages = \collect($pages)
->flatten(1)
->toArray();
return $pages;
}
public static function downloader( $vendor, $package ) : array {
$responses = [];
$continue = true;
$page = 1;
$gh_api = sprintf(
'https://api.github.com/repos/%s/%s/branches?per_page=100',
$vendor,
$package
);
while ( $continue ) {
$response = Http::get( $gh_api . '&page=' . $page );
if ( empty( $response ) ) {
$continue = false;
}
$responses[ $page ] = $response;
$page ++;
}
return $responses;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}