diff --git a/tests/AgentLoopReleaseSetVerifierTest.php b/tests/AgentLoopReleaseSetVerifierTest.php new file mode 100644 index 0000000..dd009b6 --- /dev/null +++ b/tests/AgentLoopReleaseSetVerifierTest.php @@ -0,0 +1,108 @@ + [ + 'agent_loop_release' => '0.16.5', + ], + ]); + self::writeJson($composerPath, [ + 'require' => [ + 'voku/agent-loop' => '0.16.5', + ], + 'require-dev' => [ + 'voku/agent-loop' => '0.16.4', + ], + ]); + + [$exitCode, $stdout, $stderr] = $this->execute([ + PHP_BINARY, + dirname(__DIR__) . '/tools/agent-loop/verify-release-set.php', + $issuePath, + $composerPath, + ]); + + self::assertSame(1, $exitCode, $stdout . $stderr); + self::assertSame('', $stdout); + self::assertStringContainsString( + 'must not declare the same package in both require and require-dev: voku/agent-loop', + $stderr, + ); + } finally { + foreach ([$issuePath, $composerPath] as $path) { + if (is_file($path) && !unlink($path)) { + throw new RuntimeException('Unable to remove test file: ' . $path); + } + } + if (is_dir($directory) && !rmdir($directory)) { + throw new RuntimeException('Unable to remove test directory: ' . $directory); + } + } + } + + /** + * @param array $data + */ + private static function writeJson(string $path, array $data): void + { + $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR); + if (file_put_contents($path, $json . "\n") === false) { + throw new RuntimeException('Unable to write test file: ' . $path); + } + } + + /** + * @param list $command + * + * @return array{0: int, 1: string, 2: string} + */ + private function execute(array $command): array + { + $pipes = []; + $process = proc_open( + $command, + [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], + $pipes, + ); + if (!is_resource($process)) { + throw new RuntimeException('Unable to start verifier process.'); + } + + fclose($pipes[0]); + $stdout = stream_get_contents($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + fclose($pipes[1]); + fclose($pipes[2]); + $exitCode = proc_close($process); + + return [ + $exitCode, + is_string($stdout) ? $stdout : '', + is_string($stderr) ? $stderr : '', + ]; + } +} diff --git a/tools/agent-loop/verify-release-set.php b/tools/agent-loop/verify-release-set.php index a5ad658..31f087e 100644 --- a/tools/agent-loop/verify-release-set.php +++ b/tools/agent-loop/verify-release-set.php @@ -29,6 +29,17 @@ $toolchain = requireArray($issue, 'toolchain', $argv[1]); $require = stringRequirements($composer['require'] ?? [], 'require', $argv[2]); $requireDev = stringRequirements($composer['require-dev'] ?? [], 'require-dev', $argv[2]); + + $duplicatePackages = array_keys(array_intersect_key($require, $requireDev)); + if ($duplicatePackages !== []) { + sort($duplicatePackages, SORT_STRING); + throw new \RuntimeException(sprintf( + '%s must not declare the same package in both require and require-dev: %s.', + $argv[2], + implode(', ', $duplicatePackages), + )); + } + $rootRequirements = $require + $requireDev; $expectedAgentLoop = requireString($toolchain, 'agent_loop_release', $argv[1]);