Skip to content

Commit

Permalink
Merge pull request #276 from vtsykun/feat/mirror-dist
Browse files Browse the repository at this point in the history
Support mirrors in composer repository metadata
  • Loading branch information
vtsykun authored Sep 14, 2024
2 parents f5f633c + a8e9c77 commit f5b0bdb
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 29 deletions.
2 changes: 1 addition & 1 deletion config/packages/packeton.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
packeton:
github_no_api: '%env(bool:GITHUB_NO_API)%'
rss_max_items: 30
archive: true
archive: ['mirror', 'replace']
anonymous_access: '%env(bool:PUBLIC_ACCESS)%'
anonymous_archive_access: '%env(bool:PUBLIC_ACCESS)%'
archive_options:
Expand Down
12 changes: 4 additions & 8 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ parameters:
use_forward: false
check_path: /login
failure_path: null

composer_home_dir: '%env(resolve:APP_COMPOSER_HOME)%'
mirror_repos_meta_dir: '%composer_home_dir%/proxy-meta'
mirror_repos_dist_dir: '%composer_home_dir%/proxy-dist'

package_name_regex: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+'
package_name_regex_v2: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.~-]+'
package_name_regex_v1: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.$-]+' # package$hash
Expand Down Expand Up @@ -103,7 +103,7 @@ services:
Packeton\Resolver\ControllerArgumentResolver:
tags:
- { name: controller.argument_value_resolver, priority: 105 }

Packeton\Service\AssetHashVersionStrategy:
arguments:
$publicDir: '%kernel.project_dir%/public'
Expand All @@ -114,16 +114,12 @@ services:
$isAnonymousAccess: '%anonymous_access%'
$isAnonymousArchiveAccess: '%anonymous_archive_access%'
$isAnonymousMirror: '%anonymous_mirror_access%'

Packeton\Model\UploadZipballStorage:
arguments:
$supportTypes: '%packeton_artifact_types%'
$tmpDir: '%packeton_artifact_storage%'

Packeton\Service\DistConfig:
arguments:
$config: '%packeton_archive_opts%'

Packeton\Package\InMemoryDumper:
arguments:
$config: '%packeton_dumper_opts%'
Expand Down
7 changes: 5 additions & 2 deletions src/Controller/ZipballController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Packeton\Package\RepTypes;
use Packeton\Service\DistManager;
use Packeton\Util\PacketonUtils;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand All @@ -30,7 +31,8 @@ public function __construct(
protected DistManager $dm,
protected UploadZipballStorage $storage,
protected ManagerRegistry $registry,
protected EventDispatcherInterface $dispatcher
protected EventDispatcherInterface $dispatcher,
protected LoggerInterface $logger,
) {
}

Expand Down Expand Up @@ -80,7 +82,7 @@ public function zipballList(Request $request): Response
#[Route(
'/zipball/{package}/{hash}',
name: 'download_dist_package',
requirements: ['package' => '%package_name_regex%', 'hash' => '[a-f0-9]{40}\.[a-z]+?'],
requirements: ['package' => '%package_name_regex%', 'hash' => '[a-f0-9]{40}(\.?[A-Za-z\.]+?)?'],
methods: ['GET']
)]
public function zipballAction(#[Vars('name')] Package $package, string $hash): Response
Expand All @@ -103,6 +105,7 @@ public function zipballAction(#[Vars('name')] Package $package, string $hash): R
$dist = $this->dm->getDist($reference, $package);
} catch (\Exception $e) {
$msg = $this->isGranted('ROLE_MAINTAINER') ? $e->getMessage() : null;
$this->logger->warning($e->getMessage(), ['e' => $e]);
return $this->createNotFound($msg);
}

Expand Down
18 changes: 16 additions & 2 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Packeton\Composer\MetadataFormat;
use Packeton\Integrations\Factory\OAuth2FactoryInterface;
use Packeton\Integrations\Model\AppUtils;
use Packeton\Service\DistConfig;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
Expand All @@ -30,6 +31,18 @@ public function getConfigTreeBuilder(): TreeBuilder
$treeBuilder = new TreeBuilder('packeton');
$rootNode = $treeBuilder->getRootNode();

$archiveNormalizer = static function(mixed $value): bool|array {
$allFlags = [DistConfig::FLAG_REPLACE, DistConfig::FLAG_MIRROR];
if ($value === true) {
return $allFlags;
}
$value = is_string($value) ? [$value] : $value;
if (is_array($value) && $diff = array_diff($value, $allFlags)) {
throw new \InvalidArgumentException(sprintf('packeton->archive support only [mirror, replace] options, but given %s', json_encode($diff)));
}
return is_array($value) ? $value : [];
};

$rootNode
->children()
->booleanNode('github_no_api')->end()
Expand Down Expand Up @@ -57,7 +70,8 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->booleanNode('health_check')->defaultTrue()->end()
->integerNode('max_import')->end()
->booleanNode('archive')
->variableNode('archive')
->beforeNormalization()->always()->then($archiveNormalizer)->end()
->defaultFalse()
->end()
->arrayNode('artifacts')
Expand Down Expand Up @@ -104,7 +118,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->validate()
->always(function ($values) {
if (($values['archive'] ?? false) && !isset($values['archive_options'])) {
throw new \InvalidArgumentException('archive_options is required if archive: true');
throw new \InvalidArgumentException('archive_options is required if packeton->archive is not false');
}

return $values;
Expand Down
6 changes: 4 additions & 2 deletions src/DependencyInjection/PacketonExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ public function load(array $configs, ContainerBuilder $container): void
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('packagist_web.rss_max_items', $config['rss_max_items']);
$container->setParameter('packeton_archive_all_opts', $config['archive_options'] ?? []);
$container->setParameter('packeton_archive_opts', true === $config['archive'] ? $container->getParameter('packeton_archive_all_opts') : []);

$archiveOptions = $config['archive_options'] ?? [];
$archiveOptions['flags'] = $config['archive'] ?? [];
$container->setParameter('packeton_archive_opts', $archiveOptions);

$container->setParameter('packeton_dumper_opts', $config['metadata'] ?? []);

Expand Down
8 changes: 8 additions & 0 deletions src/Package/InMemoryDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Packeton\Repository\PackageRepository;
use Packeton\Repository\VersionRepository;
use Packeton\Security\Acl\PackagesAclChecker;
use Packeton\Service\DistConfig;
use Packeton\Service\SubRepositoryHelper;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\User\UserInterface;
Expand All @@ -29,6 +30,7 @@ public function __construct(
private readonly PackagesAclChecker $checker,
private readonly RouterInterface $router,
private readonly SubRepositoryHelper $subRepositoryHelper,
private readonly DistConfig $distConfig,
?array $config = null,
) {
$this->infoMessage = $config['info_cmd_message'] ?? null;
Expand Down Expand Up @@ -103,6 +105,12 @@ private function dumpRootPackages(?UserInterface $user = null, ?int $apiVersion
$rootFile['metadata-changes-url'] = $this->router->generate('metadata_changes');
$rootFile['providers-url'] = $slug . '/p/%package%$%hash%.json';

if ($this->distConfig->mirrorEnabled()) {
$ref = '0000000000000000000000000000000000000000.zip';
$zipball = $this->router->generate('download_dist_package', ['package' => 'VND/PKG', 'hash' => $ref]);
$rootFile['mirrors'][] = ['dist-url' => \str_replace(['VND/PKG', $ref], ['%package%', '%reference%.%type%'], $zipball), 'preferred' => true];
}

$rootFile['metadata-url'] = $slug . '/p2/%package%.json';
if ($subRepo) {
$rootFile['_comment'] = "Subrepository {$subRepo->getSlug()}";
Expand Down
3 changes: 1 addition & 2 deletions src/Package/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -573,15 +573,14 @@ private function updateArchive(PackageInterface $data, Package $package): ?array
];
}

if ($this->distConfig->isEnable() === false) {
if (false === $this->distConfig->replaceEnabled()) {
if ($data->getDistUrl()) {
return [
'url' => $data->getDistUrl(),
'type' => $data->getDistType(),
'reference' => $data->getDistReference(),
];
}

return null;
}

Expand Down
31 changes: 20 additions & 11 deletions src/Service/DistConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@
namespace Packeton\Service;

use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class DistConfig
{
public const HOSTNAME_PLACEHOLDER = '__host_unset__';

private $config;
private $router;
public const FLAG_MIRROR = 'mirror';
public const FLAG_REPLACE = 'replace';

/**
* @param RouterInterface $router
* @param array $config
*/
public function __construct(RouterInterface $router, array $config)
{
$this->config = $config;
$this->router = $router;
public function __construct(
private readonly RouterInterface $router,
#[Autowire('%packeton_archive_opts%')]
private readonly array $config
) {
}

public function generateTargetDir(string $name)
Expand Down Expand Up @@ -138,12 +140,19 @@ public function generateRoute(string $name, string $reference, ?string $format =
return $hostName . $uri;
}

/**
* @return bool
*/
public function isEnable(): bool
public function archiveEnabled(): bool
{
return !empty($this->config['flags']);
}

public function mirrorEnabled(): bool
{
return in_array(self::FLAG_MIRROR, $this->config['flags'] ?? []);
}

public function replaceEnabled(): bool
{
return !empty($this->config);
return in_array(self::FLAG_REPLACE, $this->config['flags'] ?? []);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Service/DistManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function buildArchive(string $reference, Package $package, Version|string

public function isEnabled(): bool
{
return $this->config->isEnable();
return $this->config->archiveEnabled();
}

public function downloadUsingIntegration(string $reference, Package $package, ?string $versionName = null): string
Expand Down

0 comments on commit f5b0bdb

Please sign in to comment.