filesystem = new Filesystem(); $this->workDir = sys_get_temp_dir().'/get-installer-bootstrap-command-test-'.bin2hex(random_bytes(6)); $this->filesystem->mkdir($this->workDir); } protected function tearDown(): void { $this->filesystem->remove($this->workDir); parent::tearDown(); } public function testCommandSynchronizesEveryMapping(): void { $firstRepositoryDir = $this->createRepository('first', [ 'install.sh' => "#!/usr/bin/env bash\nprintf 'first'\n", ]); $secondRepositoryDir = $this->createRepository('second', [ 'install.sh' => "#!/usr/bin/env bash\nprintf 'second'\n", ]); $firstMapping = $this->mapping('mcp/first/install.sh', $firstRepositoryDir); $secondMapping = $this->mapping('mcp/second/install.sh', $secondRepositoryDir); $this->entityManager->persist($firstMapping); $this->entityManager->persist($secondMapping); $this->entityManager->flush(); $application = new Application(static::$kernel); self::assertTrue($application->has('app:mappings:sync')); $commandTester = new CommandTester($application->find('app:mappings:sync')); $commandTester->execute([]); self::assertSame(0, $commandTester->getStatusCode()); self::assertStringContainsString('2 mapping(s) synchronized, 0 failed.', $commandTester->getDisplay()); $this->entityManager->clear(); $syncedFirstMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($firstMapping->getId()); $syncedSecondMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($secondMapping->getId()); self::assertInstanceOf(ScriptMapping::class, $syncedFirstMapping); self::assertInstanceOf(ScriptMapping::class, $syncedSecondMapping); self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedFirstMapping->getLastSyncStatus()); self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedSecondMapping->getLastSyncStatus()); } public function testCommandContinuesAfterMappingFailureAndReturnsFailure(): void { $failingRepositoryDir = $this->createRepository('failing', [ 'install.sh' => "#!/usr/bin/env bash\nprintf 'missing target'\n", ]); $workingRepositoryDir = $this->createRepository('working', [ 'install.sh' => "#!/usr/bin/env bash\nprintf 'working'\n", ]); $failingMapping = $this->mapping('mcp/a-failing/install.sh', $failingRepositoryDir) ->setRepositoryFilePath('missing.sh'); $workingMapping = $this->mapping('mcp/b-working/install.sh', $workingRepositoryDir); $this->entityManager->persist($failingMapping); $this->entityManager->persist($workingMapping); $this->entityManager->flush(); $application = new Application(static::$kernel); self::assertTrue($application->has('app:mappings:sync')); $commandTester = new CommandTester($application->find('app:mappings:sync')); $commandTester->execute([]); self::assertSame(1, $commandTester->getStatusCode()); self::assertStringContainsString('1 mapping(s) synchronized, 1 failed.', $commandTester->getDisplay()); $this->entityManager->clear(); $syncedFailingMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($failingMapping->getId()); $syncedWorkingMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($workingMapping->getId()); self::assertInstanceOf(ScriptMapping::class, $syncedFailingMapping); self::assertInstanceOf(ScriptMapping::class, $syncedWorkingMapping); self::assertSame(ScriptMapping::SYNC_STATUS_FAILED, $syncedFailingMapping->getLastSyncStatus()); self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedWorkingMapping->getLastSyncStatus()); } private function mapping(string $publicPath, string $repositoryDir): ScriptMapping { return (new ScriptMapping()) ->setPublicPath($publicPath) ->setRepositoryUrl($repositoryDir) ->setGitRef('main') ->setRepositoryFilePath('install.sh') ->setActive(true); } /** @param array $files */ private function createRepository(string $name, array $files): string { $repositoryDir = $this->workDir.'/'.$name; $this->filesystem->mkdir($repositoryDir); foreach ($files as $path => $content) { $fullPath = $repositoryDir.'/'.$path; $this->filesystem->mkdir(dirname($fullPath)); file_put_contents($fullPath, $content); } $this->runGit(['init'], $repositoryDir); $this->runGit(['config', 'user.email', 'tests@example.com'], $repositoryDir); $this->runGit(['config', 'user.name', 'Tests'], $repositoryDir); $this->runGit(['add', '.'], $repositoryDir); $this->runGit(['commit', '-m', 'Initial commit'], $repositoryDir); $this->runGit(['branch', '-M', 'main'], $repositoryDir); return $repositoryDir; } /** @param list $arguments */ private function runGit(array $arguments, string $cwd): void { (new Process(['git', ...$arguments], $cwd))->mustRun(); } }