From 81e14fbe568b144dac23177945762018fb62a495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Tue, 13 Jan 2026 19:38:33 +0100 Subject: [PATCH 1/2] Remove unecessary allow-contrib config in test --- tests/FlexTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/FlexTest.php b/tests/FlexTest.php index 1bba9deb..9840c955 100644 --- a/tests/FlexTest.php +++ b/tests/FlexTest.php @@ -70,7 +70,7 @@ public function testPostInstall() $package = new Package('dummy/dummy', '1.0.0', '1.0.0'); $recipe = new Recipe($package, 'dummy/dummy', 'install', $data['manifests']['dummy/dummy'], $data['locks']['dummy/dummy']); - $rootPackage = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]); + $rootPackage = $this->mockRootPackage(); $flex = $this->mockFlex($io, $rootPackage, $recipe, $data); $flex->record($this->mockPackageEvent($package)); $flex->install($this->mockFlexEvent()); @@ -110,7 +110,7 @@ public function testActivateLoadsClasses() { $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); - $package = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]); + $package = $this->mockRootPackage(); $package->method('getRequires')->willReturn([new Link('dummy', 'symfony/flex', class_exists(MatchAllConstraint::class) ? new MatchAllConstraint() : null)]); $composer = $this->mockComposer($this->mockLocker(), $package, Factory::createConfig($io)); @@ -194,7 +194,7 @@ public function testFetchRecipesOrder() ]; $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); - $rootPackage = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]); + $rootPackage = $this->mockRootPackage(); $flex = $this->mockFlex($io, $rootPackage, null, [ 'manifests' => array_reduce($packages, static function (array $manifests, array $packageInfo) { @@ -271,7 +271,7 @@ public function testFetchRecipesWithConflicts() ]; $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); - $rootPackage = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]); + $rootPackage = $this->mockRootPackage(); $downloader = $this->getMockBuilder(Downloader::class)->disableOriginalConstructor()->getMock(); $downloader->expects($this->exactly(2)) From 7bfeaef328e1f7ffd641d99467fb8ceb661be2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Tue, 13 Jan 2026 20:23:59 +0100 Subject: [PATCH 2/2] Add SYMFONY_ALLOW_CONTRIB variable --- src/Flex.php | 7 +++++- tests/FlexTest.php | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Flex.php b/src/Flex.php index fdaaf003..3e5b3bcd 100644 --- a/src/Flex.php +++ b/src/Flex.php @@ -386,7 +386,12 @@ public function install(Event $event) } $this->io->writeError(\sprintf('Symfony operations: %d recipe%s (%s)', \count($recipes), \count($recipes) > 1 ? 's' : '', $this->downloader->getSessionId())); - $installContribs = $this->composer->getPackage()->getExtra()['symfony']['allow-contrib'] ?? false; + if (false === $installContribs = getenv('SYMFONY_ALLOW_CONTRIB')) { + $installContribs = $this->composer->getPackage()->getExtra()['symfony']['allow-contrib'] ?? false; + } + if (! is_bool($installContribs)) { + $installContribs = filter_var($installContribs, FILTER_VALIDATE_BOOL); + } $manifest = null; $originalComposerJsonHash = $this->getComposerJsonHash(); $postInstallRecipes = []; diff --git a/tests/FlexTest.php b/tests/FlexTest.php index 9840c955..2fe62566 100644 --- a/tests/FlexTest.php +++ b/tests/FlexTest.php @@ -313,6 +313,61 @@ class_exists(LockArrayRepository::class) ? LockArrayRepository::class : Reposito $this->assertSame('2.3', $recipes['doctrine/doctrine-bundle']->getVersion()); } + public function testInstallWithSymfonyAllowContribEnvVar() + { + $data = [ + 'manifests' => [ + 'dummy/contrib-package' => [ + 'manifest' => [ + 'bundles' => [ + 'Dummy\\ContribBundle\\ContribBundle' => ['all'], + ], + ], + 'origin' => 'dummy/contrib-package:1.0@github.com/symfony/recipes-contrib:main', + 'is_contrib' => true, + ], + ], + 'locks' => [ + 'dummy/contrib-package' => [ + 'recipe' => [], + 'version' => '1.0', + ], + ], + ]; + + $package = new Package('dummy/contrib-package', '1.0.0', '1.0.0'); + + // SYMFONY_ALLOW_CONTRIB=1 should install contrib recipes even without config + putenv('SYMFONY_ALLOW_CONTRIB=1'); + $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); + $recipe = new Recipe($package, 'dummy/contrib-package', 'install', $data['manifests']['dummy/contrib-package'], $data['locks']['dummy/contrib-package']); + $rootPackage = $this->mockRootPackage(['symfony' => []]); + $flex = $this->mockFlex($io, $rootPackage, $recipe, $data); + $flex->record($this->mockPackageEvent($package)); + $flex->install($this->mockFlexEvent()); + + $output = $io->getOutput(); + $this->assertStringContainsString('Configuring dummy/contrib-package', $output); + $this->assertStringNotContainsString('IGNORING', $output); + + // SYMFONY_ALLOW_CONTRIB=0 should skip contrib recipes even with config allow-contrib=true + putenv('SYMFONY_ALLOW_CONTRIB=0'); + $io = new BufferIO('', OutputInterface::VERBOSITY_NORMAL); + $recipe = new Recipe($package, 'dummy/contrib-package', 'install', $data['manifests']['dummy/contrib-package'], $data['locks']['dummy/contrib-package']); + $rootPackage = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]); + // For this test, we expect the recipe NOT to be installed, so pass null as recipe to configurator + $flex = $this->mockFlex($io, $rootPackage, null, $data); + $flex->record($this->mockPackageEvent($package)); + $flex->install($this->mockFlexEvent()); + + $output = $io->getOutput(); + $this->assertStringContainsString('IGNORING', $output); + $this->assertStringNotContainsString('Configuring dummy/contrib-package', $output); + + // Cleanup + putenv('SYMFONY_ALLOW_CONTRIB'); + } + public function testInstallWithPackageJsonToSynchronizeSkipped() { $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE);