Skip to content

Commit 30a80ee

Browse files
authored
Fix disableDefaultWorkers() edge case where user-added workers were incorrectly removed (#102)
1 parent 0a74cec commit 30a80ee

File tree

8 files changed

+141
-23
lines changed

8 files changed

+141
-23
lines changed

config/config.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@
5555
__DIR__ . '/../packages/Release/ReleaseWorker',
5656
]);
5757

58-
// Always register default workers here. They will be removed by
59-
// RemoveDefaultWorkersCompilerPass if user called disableDefaultWorkers()
60-
$services->set(TagVersionReleaseWorker::class);
61-
$services->set(PushTagReleaseWorker::class);
58+
// Register default workers with a special tag to identify them.
59+
// RemoveDefaultWorkersCompilerPass will remove services with this tag
60+
// if user called disableDefaultWorkers(), but preserve user-registered workers.
61+
$services->set(TagVersionReleaseWorker::class)
62+
->tag('monorepo.default_worker');
63+
$services->set(PushTagReleaseWorker::class)
64+
->tag('monorepo.default_worker');
6265

6366
$services->load('Symplify\MonorepoBuilder\\', __DIR__ . '/../src')
6467
->exclude([
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\MonorepoBuilder\Tests\Release\DisableDefaultWorkers;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use ReflectionClass;
9+
use Symplify\MonorepoBuilder\Config\MBConfig;
10+
use Symplify\MonorepoBuilder\Kernel\MonorepoBuilderKernel;
11+
use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushTagReleaseWorker;
12+
use Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker;
13+
14+
/**
15+
* Tests for MBConfig::disableDefaultWorkers() functionality.
16+
*
17+
* @see https://github.com/symplify/monorepo-builder/issues/95
18+
*/
19+
final class DisableDefaultWorkersTest extends TestCase
20+
{
21+
protected function setUp(): void
22+
{
23+
// Reset static state before each test
24+
$this->resetMBConfigState();
25+
}
26+
27+
protected function tearDown(): void
28+
{
29+
// Clean up static state after each test
30+
$this->resetMBConfigState();
31+
}
32+
33+
/**
34+
* Scenario 1: Default behavior - workers should be registered
35+
*/
36+
public function testDefaultWorkersAreRegisteredByDefault(): void
37+
{
38+
$monorepoBuilderKernel = new MonorepoBuilderKernel();
39+
$container = $monorepoBuilderKernel->createFromConfigs([__DIR__ . '/config/default_behavior.php']);
40+
41+
$this->assertTrue($container->has(TagVersionReleaseWorker::class));
42+
$this->assertTrue($container->has(PushTagReleaseWorker::class));
43+
}
44+
45+
/**
46+
* Scenario 2: disableDefaultWorkers() removes both default workers
47+
*/
48+
public function testDisableDefaultWorkersRemovesBothWorkers(): void
49+
{
50+
$monorepoBuilderKernel = new MonorepoBuilderKernel();
51+
$container = $monorepoBuilderKernel->createFromConfigs([__DIR__ . '/config/disable_default_workers.php']);
52+
53+
$this->assertFalse($container->has(TagVersionReleaseWorker::class));
54+
$this->assertFalse($container->has(PushTagReleaseWorker::class));
55+
}
56+
57+
/**
58+
* Scenario 3: disableDefaultWorkers() + manually add worker preserves user's worker
59+
*/
60+
public function testDisableDefaultWorkersPreservesUserAddedWorker(): void
61+
{
62+
$monorepoBuilderKernel = new MonorepoBuilderKernel();
63+
$container = $monorepoBuilderKernel->createFromConfigs([__DIR__ . '/config/disable_and_add_custom.php']);
64+
65+
// User explicitly added TagVersionReleaseWorker, so it should be preserved
66+
$this->assertTrue($container->has(TagVersionReleaseWorker::class));
67+
// User did not add PushTagReleaseWorker, so it should be removed
68+
$this->assertFalse($container->has(PushTagReleaseWorker::class));
69+
}
70+
71+
private function resetMBConfigState(): void
72+
{
73+
$reflectionClass = new ReflectionClass(MBConfig::class);
74+
$reflectionProperty = $reflectionClass->getProperty('disableDefaultWorkers');
75+
$reflectionProperty->setValue(null, false);
76+
}
77+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symplify\MonorepoBuilder\Config\MBConfig;
6+
7+
return static function (MBConfig $mbConfig): void {
8+
// Default behavior - don't disable default workers
9+
$mbConfig->defaultBranch('main');
10+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symplify\MonorepoBuilder\Config\MBConfig;
6+
use Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker;
7+
8+
return static function (MBConfig $mbConfig): void {
9+
// Disable default workers
10+
MBConfig::disableDefaultWorkers();
11+
12+
// But user explicitly wants TagVersionReleaseWorker
13+
// This should be preserved because user registration replaces the tagged default
14+
$mbConfig->workers([
15+
TagVersionReleaseWorker::class,
16+
]);
17+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Symplify\MonorepoBuilder\Config\MBConfig;
6+
7+
return static function (MBConfig $mbConfig): void {
8+
// Disable default workers - both should be removed
9+
MBConfig::disableDefaultWorkers();
10+
};

src-deps/autowire-array-parameter/src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44

55
namespace Symplify\AutowireArrayParameter\DependencyInjection\CompilerPass;
66

7-
use Symfony\Component\Config\Loader\LoaderInterface;
8-
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
9-
use Symfony\Component\HttpKernel\KernelInterface;
107
use Nette\Utils\Strings;
118
use ReflectionClass;
129
use ReflectionMethod;
10+
use Symfony\Component\Config\Loader\LoaderInterface;
1311
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1412
use Symfony\Component\DependencyInjection\ContainerBuilder;
1513
use Symfony\Component\DependencyInjection\Definition;
1614
use Symfony\Component\DependencyInjection\Reference;
15+
use Symfony\Component\HttpKernel\KernelInterface;
16+
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
1717
use Symplify\AutowireArrayParameter\DependencyInjection\DefinitionFinder;
1818
use Symplify\AutowireArrayParameter\DocBlock\ParamTypeDocBlockResolver;
1919
use Symplify\AutowireArrayParameter\Skipper\ParameterSkipper;

src-deps/autowire-array-parameter/src/Skipper/ParameterSkipper.php

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

55
namespace Symplify\AutowireArrayParameter\Skipper;
66

7-
use Symfony\Component\Config\Loader\LoaderInterface;
8-
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
97
use ReflectionMethod;
108
use ReflectionNamedType;
119
use ReflectionParameter;
1210
use ReflectionType;
11+
use Symfony\Component\Config\Loader\LoaderInterface;
1312
use Symfony\Component\DependencyInjection\Definition;
13+
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
1414
use Symplify\AutowireArrayParameter\TypeResolver\ParameterTypeResolver;
1515

1616
final class ParameterSkipper

src/DependencyInjection/CompilerPass/RemoveDefaultWorkersCompilerPass.php

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,35 @@
77
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
88
use Symfony\Component\DependencyInjection\ContainerBuilder;
99
use Symplify\MonorepoBuilder\Config\MBConfig;
10-
use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushTagReleaseWorker;
11-
use Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker;
1210

1311
/**
1412
* Removes default release workers from the container if MBConfig::disableDefaultWorkers() was called.
15-
* This needs to happen in a compiler pass rather than during config loading because:
16-
* 1. Default config is loaded before user config (to allow parameter overriding)
17-
* 2. User config calls disableDefaultWorkers() after default config has already registered workers
18-
* 3. Compiler passes run after all configs are loaded, so they can see the final state
13+
*
14+
* This uses a tag-based approach to distinguish between:
15+
* - Default workers registered by config/config.php (tagged with 'monorepo.default_worker')
16+
* - User-registered workers (no tag, or re-registered without the tag)
17+
*
18+
* When user calls disableDefaultWorkers() and then manually registers a worker
19+
* (even one with the same class as a default worker), only the tagged default
20+
* definition is removed, preserving the user's explicit registration.
1921
*/
2022
final readonly class RemoveDefaultWorkersCompilerPass implements CompilerPassInterface
2123
{
24+
private const DEFAULT_WORKER_TAG = 'monorepo.default_worker';
25+
2226
public function process(ContainerBuilder $containerBuilder): void
2327
{
2428
// Check if user disabled default workers in their config
2529
if (! MBConfig::isDisableDefaultWorkers()) {
2630
return;
2731
}
2832

29-
// Remove the default workers from the container
30-
$defaultWorkers = [
31-
TagVersionReleaseWorker::class,
32-
PushTagReleaseWorker::class,
33-
];
33+
// Find and remove only services tagged as default workers
34+
$taggedServices = $containerBuilder->findTaggedServiceIds(self::DEFAULT_WORKER_TAG);
3435

35-
foreach ($defaultWorkers as $defaultWorker) {
36-
if ($containerBuilder->hasDefinition($defaultWorker)) {
37-
$containerBuilder->removeDefinition($defaultWorker);
36+
foreach (array_keys($taggedServices) as $serviceId) {
37+
if ($containerBuilder->hasDefinition($serviceId)) {
38+
$containerBuilder->removeDefinition($serviceId);
3839
}
3940
}
4041
}

0 commit comments

Comments
 (0)