Skip to content

Commit

Permalink
Support remote pkgs definition
Browse files Browse the repository at this point in the history
  • Loading branch information
huangzhhui committed Oct 4, 2022
1 parent 8d113be commit 63e28fe
Show file tree
Hide file tree
Showing 12 changed files with 470 additions and 82 deletions.
23 changes: 21 additions & 2 deletions src/app/DownloadHandler/AbstractDownloadHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use App\Config;
use App\Exception\NotSupportVersionsException;
use App\GithubClient;
use App\PkgDefinition\Definition;
use App\PkgDefinitionManager;
use GuzzleHttp\Client;
use GuzzleHttp\TransferStats;
use Hyperf\Context\Context;
Expand All @@ -39,16 +41,19 @@ abstract class AbstractDownloadHandler
#[Inject]
protected Config $config;

#[Inject]
protected PkgDefinitionManager $pkgsDefinitionManager;

protected string $runtimePath;

public function __construct()
{
$this->runtimePath = $this->config->getConfig('path.runtime', getenv('HOME') . '/.box');
}

abstract public function handle(string $repo, string $version, array $options = []): ?SplFileInfo;
abstract public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo;

abstract public function versions(string $repo, array $options = []): array;
abstract public function versions(string $pkgName, array $options = []): array;

protected function fetchDownloadUrlFromGithubRelease(string $assetName, string $fullRepo, string $version): ?string
{
Expand Down Expand Up @@ -161,4 +166,18 @@ protected function byteToKb(int $byte): int
{
return (int)ceil($byte / 1024);
}

protected function getDefinition(string $pkgName): ?Definition
{
return $this->pkgsDefinitionManager->getDefinition($pkgName);
}

protected function replaces(string $subject, array $replaces): string
{
foreach ($replaces as $search => $replace) {
$subject = str_replace('${{' . $search . '}}', $replace, $subject);
}
return $subject;
}

}
4 changes: 2 additions & 2 deletions src/app/DownloadHandler/BoxHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public function __construct()
$this->binName = $this->getAssetName();
}

public function handle(string $repo, string $version, array $options = []): ?SplFileInfo
public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo
{
$url = $this->fetchDownloadUrlFromGithubRelease($this->getAssetName(), $this->fullRepo, $version);
$savePath = Phar::running(false) ?: $this->runtimePath . '/';

return $this->download($url, $savePath, 0755, $this->binName);
}

public function versions(string $repo, array $options = []): array
public function versions(string $pkgName, array $options = []): array
{
return $this->fetchVersionsFromGithubRelease($this->fullRepo, $this->getAssetName());
}
Expand Down
37 changes: 23 additions & 14 deletions src/app/DownloadHandler/ComposerHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,61 @@
namespace App\DownloadHandler;

use App\Exception\NotSupportVersionsException;
use App\PkgDefinition\Definition;
use SplFileInfo;

class ComposerHandler extends AbstractDownloadHandler
{
protected string $fullRepo = 'composer/composer';

protected string $binName = 'composer.phar';

protected string $getComposerOrgBaseUrl = 'getcomposer.org';
protected string $fullRepo = 'composer/composer';

protected string $githubBaseUrl = 'github.com';

public function handle(string $repo, string $version, array $options = []): ?SplFileInfo
public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo
{
$definition = $this->getDefinition($pkgName);
if (! isset($options['source'])) {
$options['source'] = $this->getComposerOrgBaseUrl;
$options['source'] = $definition->getSources()->getSource('default')?->getUrl();
}
$url = match ($options['source']) {
$this->githubBaseUrl => $this->fetchDownloadUrlFromGithubRelease($this->binName, $this->fullRepo, $version),
default => $this->fetchDownloadUrlFromGetComposerOrg($version),
$this->githubBaseUrl => $this->fetchDownloadUrlFromGithubRelease($definition->getBin(), $definition->getRepo(), $version),
default => $this->fetchDownloadUrlFromGetComposerOrg($definition, $version),
};
return $this->download($url, $this->runtimePath . '/', 0755);
}

public function versions(string $repo, array $options = []): array
public function versions(string $pkgName, array $options = []): array
{
$definition = $this->getDefinition($pkgName);
if (! isset($options['source'])) {
$options['source'] = $this->getComposerOrgBaseUrl;
$options['source'] = $definition->getSources()->getSource('default')?->getUrl();
}
return match ($options['source']) {
$this->githubBaseUrl => $this->fetchVersionsFromGithubRelease($this->fullRepo),
default => throw new NotSupportVersionsException($repo),
$this->githubBaseUrl => $this->fetchVersionsFromGithubRelease($definition->getRepo()),
default => throw new NotSupportVersionsException($pkgName),
};
}

protected function fetchDownloadUrlFromGetComposerOrg(string $version): string
protected function fetchDownloadUrlFromGetComposerOrg(Definition $definition, string $version): string
{
if ($version === 'latest') {
$release = $this->githubClient->getRelease($this->fullRepo, $version);
$release = $this->githubClient->getRelease($definition->getRepo(), $version);
if (! isset($release['tag_name'])) {
throw new \RuntimeException('Cannot match the specified version from github releases.');
}
$specifiedVersion = $release['tag_name'];
} else {
$specifiedVersion = $version;
}
return 'https://' . $this->getComposerOrgBaseUrl . '/download/' . $specifiedVersion . '/' . $this->binName;
$url = $definition->getSources()?->getSource('getcomposer.org')?->getUrl();
if (! $url) {
throw new \RuntimeException('Cannot parse the download url by getcomposer.org.');
}
return $this->replaces($url, [
'version' => $specifiedVersion,
'bin' => $definition->getBin(),
]);
}

}
44 changes: 17 additions & 27 deletions src/app/DownloadHandler/DefaultHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,36 @@

class DefaultHandler extends AbstractDownloadHandler
{
protected array $definitions = [
'php-cs-fixer' => [
'repo' => 'FriendsOfPHP/PHP-CS-Fixer',
'bin' => 'php-cs-fixer.phar',
],
'phpunit' => [
'url' => 'https://phar.phpunit.de/phpunit-${{version}}.phar',
'latest' => '9',
'bin' => 'phpunit.phar',
],
];

public function handle(string $repo, string $version, array $options = []): ?SplFileInfo
public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo
{
if (! isset($this->definitions[$repo])) {
$definition = $this->getDefinition($pkgName);
if (! $definition) {
throw new \RuntimeException('The package not found');
}
$definition = $this->definitions[$repo];
if (isset($definition['repo'])) {
$url = $this->fetchDownloadUrlFromGithubRelease($definition['bin'], $definition['repo'], $version);
} elseif (isset($definition['url'])) {
if ($version === 'latest' && isset($definition['latest'])) {
$version = $definition['latest'];
if ($definition->getRepo()) {
$url = $this->fetchDownloadUrlFromGithubRelease($definition->getBin(), $definition->getRepo(), $version);
} elseif ($definition->getUrl()) {
if ($version === 'latest' && $definition->getLatest()) {
$version = $definition->getLatest();
}
$url = str_replace('${{version}}', $version, $definition['url']);
$url = str_replace('${{version}}', $version, $definition->getUrl());
} else {
throw new \RuntimeException('The definition of package is invalid');
}
return $this->download($url, $this->runtimePath . '/', 0755, $definition['bin']);
return $this->download($url, $this->runtimePath . '/', 0755, $definition->getBin());
}

public function versions(string $repo, array $options = []): array
public function versions(string $pkgName, array $options = []): array
{
if (! isset($this->definitions[$repo])) {
$definition = $this->getDefinition($pkgName);
if (! $definition) {
throw new \RuntimeException('The package not found');
}
$definition = $this->definitions[$repo];
if (! isset($definition['repo'])) {
throw new NotSupportVersionsException($repo);
if (! $definition->getRepo()) {
throw new NotSupportVersionsException($pkgName);
}
return $this->fetchVersionsFromGithubRelease($definition['repo'], $definition['bin']);
return $this->fetchVersionsFromGithubRelease($definition->getRepo(), $definition->getBin());
}

}
4 changes: 2 additions & 2 deletions src/app/DownloadHandler/MicroHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ class MicroHandler extends PhpHandler
#[Inject]
protected Client $httpClient;

public function handle(string $repo, string $version, array $options = []): ?SplFileInfo
public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo
{
$version = $this->prehandleVersion($version);
try {
$response = $this->getArtifact($version, 'micro');
$response = $this->getArtifact($this->getDefinition($pkgName), $version, 'micro');
if ($response->getStatusCode() !== 302 || ! $response->getHeaderLine('Location')) {
throw new \RuntimeException('Download failed, cannot retrieve the download url from artifact.');
}
Expand Down
45 changes: 10 additions & 35 deletions src/app/DownloadHandler/PhpHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace App\DownloadHandler;

use App\PkgDefinition\Definition;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Di\Annotation\Inject;
Expand All @@ -23,27 +24,11 @@ class PhpHandler extends AbstractDownloadHandler
#[Inject]
protected Client $httpClient;

protected string $repo = 'dixyes/lwmbs';

protected array $jobs
= [
'Darwin.x86_64' => '2969003447',
'Darwin.arm64' => '2969003447',
'Linux.x86_64' => '2961452571',
'Linux.aarch64' => '2961452571',
];

protected array $matchRules
= [
'Darwin' => '${{prefix}}_${{php-version}}_${{arch}}',
'Linux' => '${{prefix}}_static_${{php-version}}_musl_${{arch}}',
];

public function handle(string $repo, string $version, array $options = []): ?SplFileInfo
public function handle(string $pkgName, string $version, array $options = []): ?SplFileInfo
{
$version = $this->prehandleVersion($version);
try {
$response = $this->getArtifact($version, 'cli');
$response = $this->getArtifact($this->getDefinition($pkgName), $version, 'cli');
if ($response->getStatusCode() !== 302 || ! $response->getHeaderLine('Location')) {
throw new \RuntimeException('Download failed, cannot retrieve the download url from artifact.');
}
Expand Down Expand Up @@ -97,7 +82,7 @@ protected function prehandleVersion(string $version): string
/**
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function getArtifact(string $version, string $prefix): ResponseInterface
protected function getArtifact(Definition $definition, string $version, string $prefix): ResponseInterface
{
$githubToken = $this->githubClient->getGithubToken();
if (! $githubToken) {
Expand All @@ -106,8 +91,8 @@ protected function getArtifact(string $version, string $prefix): ResponseInterfa
$os = PHP_OS_FAMILY;
$arch = php_uname('m');
$key = $os . '.' . $arch;
$response = $this->githubClient->getActionsArtifacts($this->repo, $this->jobs[$key]);
$searchKey = $this->buildSearchKey($os, $prefix, $version, $arch);
$response = $this->githubClient->getActionsArtifacts($definition->getRepo(), $definition->getJobs()?->getJob($key)?->getJobId());
$searchKey = $this->buildSearchKey($definition, $key, $prefix, $version, $arch);
$artifact = $this->matchArtifact($response['artifacts'] ?? [], $searchKey);
if (! isset($artifact['archive_download_url'])) {
throw new \RuntimeException('Does not match any artifact.');
Expand All @@ -121,33 +106,23 @@ protected function getArtifact(string $version, string $prefix): ResponseInterfa
]);
}

protected function buildSearchKey(string $os, string $prefix, string $version, string $arch): string
protected function buildSearchKey(Definition $definition, string $key, string $prefix, string $version, string $arch): string
{
return $this->replaces($this->matchRules[$os], [
return $this->replaces($definition->getJobArtifactMatchRule()[$key], [
'prefix' => $prefix,
'php-version' => $version,
'arch' => $arch,
]);
}

protected function replaces(string $subject, array $replaces): string
{
foreach ($replaces as $search => $replace) {
$subject = str_replace('${{' . $search . '}}', $replace, $subject);
}
return $subject;
}

protected function isBinExists(string $string): bool
{
$result = shell_exec(sprintf("which %s", escapeshellarg($string)));
return ! empty($result) && ! str_contains($result, 'not found');
}

public function versions(string $repo, array $options = []): array
public function versions(string $pkgName, array $options = []): array
{
return [
'8.1', '8.0'
];
return $this->getDefinition($pkgName)->getVersions();
}
}
Loading

0 comments on commit 63e28fe

Please sign in to comment.