Skip to content

Commit a4128c2

Browse files
committed
Add package distribution strategy field
1 parent 6329f22 commit a4128c2

10 files changed

Lines changed: 176 additions & 11 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20250609181654 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Add package distribution strategy';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql(<<<'SQL'
20+
ALTER TABLE package ADD distribution_strategy VARCHAR(255) DEFAULT NULL
21+
SQL);
22+
$this->addSql(<<<'SQL'
23+
UPDATE package SET distribution_strategy = 'dynamic'
24+
SQL);
25+
$this->addSql(<<<'SQL'
26+
ALTER TABLE package ALTER distribution_strategy TYPE VARCHAR(255)
27+
SQL);
28+
$this->addSql(<<<'SQL'
29+
ALTER TABLE package ALTER distribution_strategy SET NOT NULL
30+
SQL);
31+
}
32+
33+
public function down(Schema $schema): void
34+
{
35+
$this->addSql(<<<'SQL'
36+
ALTER TABLE package DROP distribution_strategy
37+
SQL);
38+
}
39+
}

src/Controller/ApiController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ public function packageDistribution(string $packageName, string $packageVersion,
112112
throw $this->createNotFoundException();
113113
}
114114

115+
if (!$package->getDistributionStrategy()->allowDynamic()) {
116+
throw $this->createNotFoundException();
117+
}
118+
115119
$this->messenger->dispatch(new UpdatePackage($package->getId()));
116120

117121
if (null === $version = $this->versionRepository->findOneBy(['package' => $package, 'normalizedVersion' => $packageVersion])) {

src/Doctrine/Entity/Package.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class Package extends TrackedEntity
6262
#[ORM\Column(nullable: true, enumType: PackageFetchStrategy::class)]
6363
private PackageFetchStrategy|string|null $fetchStrategy = null;
6464

65+
#[ORM\Column(enumType: PackageDistributionStrategy::class)]
66+
private PackageDistributionStrategy $distributionStrategy = PackageDistributionStrategy::Dynamic;
67+
6568
#[ORM\ManyToOne]
6669
private ?Registry $mirrorRegistry = null;
6770

@@ -269,6 +272,16 @@ public function setFetchStrategy(PackageFetchStrategy|string $fetchStrategy): vo
269272
$this->fetchStrategy = $fetchStrategy;
270273
}
271274

275+
public function getDistributionStrategy(): PackageDistributionStrategy
276+
{
277+
return $this->distributionStrategy;
278+
}
279+
280+
public function setDistributionStrategy(PackageDistributionStrategy $distributionStrategy): void
281+
{
282+
$this->distributionStrategy = $distributionStrategy;
283+
}
284+
272285
public function getMirrorRegistry(): ?Registry
273286
{
274287
return $this->mirrorRegistry;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace CodedMonkey\Dirigent\Doctrine\Entity;
4+
5+
use Symfony\Contracts\Translation\TranslatableInterface;
6+
use Symfony\Contracts\Translation\TranslatorInterface;
7+
8+
enum PackageDistributionStrategy: string implements TranslatableInterface
9+
{
10+
case Disabled = 'none';
11+
case Dynamic = 'dynamic';
12+
case Automatic = 'auto';
13+
14+
public function trans(TranslatorInterface $translator, ?string $locale = null): string
15+
{
16+
return $translator->trans("package.distribution-strategy.{$this->value}");
17+
}
18+
19+
public function allowDynamic(): bool
20+
{
21+
return self::Disabled !== $this;
22+
}
23+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace CodedMonkey\Dirigent\Doctrine\EventListener;
4+
5+
use CodedMonkey\Dirigent\Doctrine\Entity\PackageDistributionStrategy;
6+
use CodedMonkey\Dirigent\Doctrine\Entity\Version;
7+
use CodedMonkey\Dirigent\Message\ResolveDistribution;
8+
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
9+
use Doctrine\ORM\Events;
10+
use Symfony\Component\Messenger\Envelope;
11+
use Symfony\Component\Messenger\MessageBusInterface;
12+
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;
13+
14+
#[AsEntityListener(Events::postPersist, entity: Version::class)]
15+
#[AsEntityListener(Events::postUpdate, entity: Version::class)]
16+
readonly class VersionListener
17+
{
18+
public function __construct(
19+
private MessageBusInterface $messenger,
20+
) {
21+
}
22+
23+
public function postPersist(Version $version): void
24+
{
25+
$this->resolveDistribution($version);
26+
}
27+
28+
public function postUpdate(Version $version): void
29+
{
30+
// todo only update if reference or type changed
31+
$this->resolveDistribution($version);
32+
}
33+
34+
private function resolveDistribution(Version $version): void
35+
{
36+
if (PackageDistributionStrategy::Automatic === $version->getPackage()->getDistributionStrategy()) {
37+
$message = Envelope::wrap(new ResolveDistribution($version->getId()))
38+
->with(new TransportNamesStamp('async'));
39+
$this->messenger->dispatch($message);
40+
}
41+
}
42+
}

src/Form/PackageFormType.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
use CodedMonkey\Dirigent\Doctrine\Entity\Credentials;
66
use CodedMonkey\Dirigent\Doctrine\Entity\Package;
7+
use CodedMonkey\Dirigent\Doctrine\Entity\PackageDistributionStrategy;
78
use CodedMonkey\Dirigent\Doctrine\Entity\PackageFetchStrategy;
89
use CodedMonkey\Dirigent\Doctrine\Entity\Registry;
910
use CodedMonkey\Dirigent\Doctrine\Repository\RegistryRepository;
1011
use CodedMonkey\Dirigent\Package\PackageVcsRepositoryValidator;
1112
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
13+
use Symfony\Component\DependencyInjection\Attribute\Autowire;
1214
use Symfony\Component\Form\AbstractType;
1315
use Symfony\Component\Form\Event\PostSetDataEvent;
1416
use Symfony\Component\Form\Event\SubmitEvent;
@@ -23,6 +25,8 @@ class PackageFormType extends AbstractType
2325
{
2426
public function __construct(
2527
private readonly PackageVcsRepositoryValidator $vcsRepositoryValidator,
28+
#[Autowire(param: 'dirigent.distributions.enabled')]
29+
private readonly bool $distributionsEnabled,
2630
) {
2731
}
2832

@@ -46,6 +50,14 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
4650
])
4751
->addEventListener(FormEvents::POST_SET_DATA, [$this, 'onPostSetData'])
4852
->addEventListener(FormEvents::SUBMIT, [$this, 'onSubmit']);
53+
54+
if ($this->distributionsEnabled) {
55+
$builder->add('distributionStrategy', EnumType::class, [
56+
'label' => 'Resolve distributions',
57+
'class' => PackageDistributionStrategy::class,
58+
'expanded' => true,
59+
]);
60+
}
4961
}
5062

5163
public function onPostSetData(PostSetDataEvent $event): void

src/Message/ResolveDistribution.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
{
1010
public function __construct(
1111
public int $versionId,
12-
public string $reference,
13-
public string $type,
12+
public ?string $reference = null,
13+
public ?string $type = null,
1414
) {
1515
}
1616
}

src/Package/PackageDistributionResolver.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ public function __construct(
3939
$this->distributionStoragePath = "$storagePath/distribution";
4040
}
4141

42-
public function exists(string $packageName, string $packageVersion, string $reference, string $type): bool
42+
public function exists(string $packageName, string $packageVersion, ?string $reference, ?string $type): bool
4343
{
44-
return $this->filesystem->exists($this->path($packageName, $packageVersion, $reference, $type));
44+
return null !== $reference && null !== $type && $this->filesystem->exists($this->path($packageName, $packageVersion, $reference, $type));
4545
}
4646

4747
public function path(string $packageName, string $packageVersion, string $reference, string $type): string
4848
{
4949
return "$this->distributionStoragePath/$packageName/$packageVersion-$reference.$type";
5050
}
5151

52-
public function resolve(Version $version, string $reference, string $type, bool $async): bool
52+
public function resolve(Version $version, ?string $reference, ?string $type, bool $async): bool
5353
{
5454
$package = $version->getPackage();
5555
$packageName = $package->getName();
@@ -74,13 +74,13 @@ public function resolve(Version $version, string $reference, string $type, bool
7474
}
7575

7676
return match (true) {
77-
$this->buildDistributions && null === $version->getDist() => $this->build($version, $reference, $type),
78-
$this->mirrorDistributions && null !== $version->getDist() => $this->mirror($version, $reference, $type),
77+
$this->buildDistributions && null === $version->getDist() => $this->build($version, $reference ?? $version->getSourceReference(), $type ?? $version->getSourceType()),
78+
$this->mirrorDistributions && null !== $version->getDist() => $this->mirror($version, $reference ?? $version->getDistReference(), $type ?? $version->getDistType()),
7979
default => false,
8080
};
8181
}
8282

83-
private function build(Version $version, string $reference, string $type): bool
83+
private function build(Version $version, ?string $reference, ?string $type): bool
8484
{
8585
// Skip building of outdated references for now
8686
if ($reference !== $version->getSourceReference()) {
@@ -117,7 +117,7 @@ private function build(Version $version, string $reference, string $type): bool
117117
return true;
118118
}
119119

120-
private function mirror(Version $version, string $reference, string $type): bool
120+
private function mirror(Version $version, ?string $reference, ?string $type): bool
121121
{
122122
// Skip mirroring of outdated references for now
123123
if ($reference !== $version->getDistReference()) {

templates/dashboard/packages/edit.html.twig

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<div class="form-fieldset-header">
2222
<div class="form-fieldset-title">
2323
<span class="form-fieldset-title-content">
24-
Repository
24+
{{ 'Repository'|trans }}
2525
</span>
2626
</div>
2727
</div>
@@ -42,7 +42,7 @@
4242
<div class="form-fieldset-header">
4343
<div class="form-fieldset-title">
4444
<span class="form-fieldset-title-content">
45-
Mirroring
45+
{{ 'Mirroring'|trans }}
4646
</span>
4747
</div>
4848
</div>
@@ -59,5 +59,27 @@
5959
</div>
6060
</fieldset>
6161
</div>
62+
63+
{% if form.distributionStrategy is defined %}
64+
<div class="form-fieldset">
65+
<fieldset>
66+
<div class="form-fieldset-header">
67+
<div class="form-fieldset-title">
68+
<span class="form-fieldset-title-content">
69+
{{ 'Distributions'|trans }}
70+
</span>
71+
</div>
72+
</div>
73+
74+
<div class="form-fieldset-body">
75+
<div class="row">
76+
<div>
77+
{{ form_row(form.distributionStrategy) }}
78+
</div>
79+
</div>
80+
</div>
81+
</fieldset>
82+
</div>
83+
{% endif %}
6284
{{ form_end(form) }}
6385
{% endblock %}

translations/messages.en.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ Administration: Administration
44
Credits: Credits
55
Dashboard: Dashboard
66
Dependents: Dependents
7+
Distributions: Distributions
78
Documentation: Documentation
89
Implementations: Implementations
910
Info: Info
11+
Mirroring: Mirroring
1012
Packages: Packages
1113
Personal: Personal
1214
Providers: Providers
15+
Repository: Repository
1316
Sign out: Sign out
1417
Statistics: Statistics
1518
Suggesters: Suggesters
@@ -31,12 +34,15 @@ Description: Description
3134
Dynamic Update Delay: Dynamic update delay
3235
Email: Email
3336
Expires At: Expires at
37+
Fetch strategy: Fetch strategy
38+
Mirror registry: Mirror registry
3439
New password: New password
3540
Name: Name
3641
Package Mirroring: Package mirroring
3742
Password: Password
3843
Repeat new password: Repeat new password
3944
Repository url: Repository URL
45+
Resolve distributions: Resolve distributions
4046
Roles: Roles
4147
Token: Token
4248
Type: Type
@@ -72,6 +78,10 @@ credentials:
7278
gitlab-dt: GitLab deploy token
7379
gitlab-pat: GitLab personal access token
7480
package:
81+
distribution-strategy:
82+
auto: Resolve all distributions
83+
dynamic: Resolve distributions on request
84+
none: Never resolve distributions
7585
fetch-strategy:
7686
mirror: Fetch from mirror registry
7787
vcs: Fetch directly from VCS

0 commit comments

Comments
 (0)