diff --git a/build.xml b/build.xml index c205462126e..6e1d3756dc1 100644 --- a/build.xml +++ b/build.xml @@ -117,7 +117,10 @@ - + + + + @@ -328,13 +331,6 @@ - - - - - - - diff --git a/build/scripts/phar-manifest.php b/build/scripts/phar-manifest.php index a794e6ba515..92169fdacd0 100755 --- a/build/scripts/phar-manifest.php +++ b/build/scripts/phar-manifest.php @@ -1,27 +1,140 @@ #!/usr/bin/env php &1'); + exit(1); +} + +$dependencies = dependencies(); +$version = version(); + +manifest($argv[1], $version, $dependencies); +sbom($argv[2], $version, $dependencies); + +function manifest(string $outputFilename, string $version, array $dependencies): void +{ + $buffer = 'phpunit/phpunit: ' . $version . "\n"; + + foreach ($dependencies as $dependency) { + $buffer .= $dependency['name'] . ': ' . $dependency['version']; + + if (!preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9.\\-:]*)?)?)?)?)$/', $dependency['version'])) { + $buffer .= '@' . $dependency['source']['reference']; + } + + $buffer .= "\n"; + } + + file_put_contents($outputFilename, $buffer); +} + +function sbom(string $outputFilename, string $version, array $dependencies): void +{ + $writer = new XMLWriter; + + $writer->openMemory(); + $writer->setIndent(true); + $writer->startDocument(); + + $writer->startElement('bom'); + $writer->writeAttribute('xmlns', 'https://cyclonedx.org/schema/bom/1.4'); + + $writer->startElement('components'); + + writeComponent( + $writer, + 'phpunit', + 'phpunit', + $version, + 'The PHP Unit Testing framework', + ['BSD-3-Clause'] + ); -if (\strpos($tag, '-') === false && \strpos($tag, 'No names found') === false) { - print $tag; -} else { - $branch = @\exec('git rev-parse --abbrev-ref HEAD'); - $hash = @\exec('git log -1 --format="%H"'); - print $branch . '@' . $hash; + foreach ($dependencies as $dependency) { + [$group, $name] = explode('/', $dependency['name']); + $dependencyVersion = $dependency['version']; + + if (!preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9.\\-:]*)?)?)?)?)$/', $dependencyVersion)) { + $dependencyVersion .= '@' . $dependency['source']['reference']; + } + + writeComponent( + $writer, + $group, + $name, + $dependencyVersion, + $dependency['description'], + $dependency['license'] + ); + } + + $writer->endElement(); + $writer->endElement(); + $writer->endDocument(); + + file_put_contents($outputFilename, $writer->outputMemory()); +} + +function dependencies(): array +{ + return json_decode( + file_get_contents( + __DIR__ . '/../../composer.lock' + ), + true + )['packages']; } -print "\n"; +function version(): string +{ + $tag = @exec('git describe --tags 2>&1'); -$lock = \json_decode(\file_get_contents(__DIR__ . '/../../composer.lock')); + if (strpos($tag, '-') === false && strpos($tag, 'No names found') === false) { + return $tag; + } -foreach ($lock->packages as $package) { - print $package->name . ': ' . $package->version; + $branch = @exec('git rev-parse --abbrev-ref HEAD'); + $hash = @exec('git log -1 --format="%H"'); - if (!\preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9\\.\\-:]*)?)?)?)?)$/', $package->version)) { - print '@' . $package->source->reference; + return $branch . '@' . $hash; +} + +function writeComponent(XMLWriter $writer, string $group, string $name, string $version, string $description, array $licenses): void +{ + $writer->startElement('component'); + $writer->writeAttribute('type', 'library'); + + $writer->writeElement('group', $group); + $writer->writeElement('name', $name); + $writer->writeElement('version', $version); + $writer->writeElement('description', $description); + + $writer->startElement('licenses'); + + foreach ($licenses as $license) { + $writer->startElement('license'); + $writer->writeElement('id', $license); + $writer->endElement(); } - print "\n"; + $writer->endElement(); + + $writer->writeElement( + 'purl', + sprintf( + 'pkg:composer/%s/%s@%s', + $group, + $name, + $version + ) + ); + + $writer->endElement(); } diff --git a/build/templates/binary-phar-autoload.php.in b/build/templates/binary-phar-autoload.php.in index 509f3ea914f..28c7694a243 100644 --- a/build/templates/binary-phar-autoload.php.in +++ b/build/templates/binary-phar-autoload.php.in @@ -52,7 +52,7 @@ if (__FILE__ === realpath($_SERVER['SCRIPT_NAME'])) { $execute = false; } -$options = getopt('', array('prepend:', 'manifest')); +$options = getopt('', array('prepend:', 'manifest', 'sbom')); if (isset($options['prepend'])) { require $options['prepend']; @@ -60,6 +60,8 @@ if (isset($options['prepend'])) { if (isset($options['manifest'])) { $printManifest = true; +} elseif (isset($options['sbom'])) { + $printSbom = true; } unset($options); @@ -98,6 +100,12 @@ if ($execute) { exit; } + if (isset($printSbom)) { + print file_get_contents(__PHPUNIT_PHAR_ROOT__ . '/sbom.xml'); + + exit; + } + unset($execute); PHPUnit\TextUI\Command::main(); diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index f90245bd1ba..b8aadb98972 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -2299,7 +2299,6 @@ private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot $excludeList->addClassNamePrefix('SebastianBergmann\Invoker'); $excludeList->addClassNamePrefix('SebastianBergmann\Template'); $excludeList->addClassNamePrefix('SebastianBergmann\Timer'); - $excludeList->addClassNamePrefix('Symfony'); $excludeList->addClassNamePrefix('Doctrine\Instantiator'); $excludeList->addClassNamePrefix('Prophecy'); $excludeList->addStaticAttribute(ComparatorFactory::class, 'instance');