diff --git a/action.yml b/action.yml index 2a19d00..712e493 100644 --- a/action.yml +++ b/action.yml @@ -2,6 +2,10 @@ name: Generate Matrix description: GitHub Action to create a dynamic Silverstripe CI matrix inputs: + composer_install: + type: boolean + required: false + default: false # extra jobs must be multi-line string, as there's no support for type: array for inputs extra_jobs: type: string @@ -113,6 +117,7 @@ runs: PARENT_BRANCH=$(git show-branch -a 2>/dev/null | { grep '\*' || :; } | { grep -v `git rev-parse --abbrev-ref HEAD` || :; } | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//') # create __inputs.yml touch __inputs.yml + echo "composer_install: ${{ inputs.composer_install }}" >> __inputs.yml echo "endtoend: ${{ inputs.endtoend }}" >> __inputs.yml echo "js: ${{ inputs.js }}" >> __inputs.yml echo "phpcoverage: ${{ inputs.phpcoverage }}" >> __inputs.yml diff --git a/job_creator.php b/job_creator.php index b3dbf7d..db8d83e 100644 --- a/job_creator.php +++ b/job_creator.php @@ -14,6 +14,8 @@ class JobCreator private ?string $composerPhpConstraint = ''; + private string $phpVersionOverride = ''; + /** * Get the correct version of silverstripe/installer to include for the given repository and branch */ @@ -76,6 +78,7 @@ public function createJob(int $phpIndex, array $opts): array 'db' => DB_MYSQL_57, 'composer_require_extra' => '', 'composer_args' => '', + 'composer_install' => false, 'name_suffix' => '', 'phpunit' => false, 'phpunit_suite' => 'all', @@ -166,6 +169,9 @@ private function isAllowedPhpVersion(string $phpVersion) private function getPhpVersion(int $phpIndex): string { + if ($this->phpVersionOverride) { + return $this->phpVersionOverride; + } $key = str_replace('.x-dev', '', $this->installerVersion); $repo = explode('/', $this->githubRepository)[1]; if (in_array($repo, NO_INSTALLER_LOCKSTEPPED_REPOS)) { @@ -297,11 +303,12 @@ private function parseBoolValue($value): bool private function createPhpunitJobs( array $matrix, + bool $composerInstall, bool $simpleMatrix, string $suite, array $run ): array { - if ($simpleMatrix) { + if ($simpleMatrix || $composerInstall) { $matrix['include'][] = $this->createJob(0, [ 'phpunit' => true, 'phpunit_suite' => $suite, @@ -343,6 +350,7 @@ private function doRunPhpCoverage(array $run): bool private function buildDynamicMatrix( array $matrix, array $run, + bool $composerInstall, bool $simpleMatrix ): array { if ($run['phpunit'] && (file_exists('phpunit.xml') || file_exists('phpunit.xml.dist'))) { @@ -356,11 +364,11 @@ private function buildDynamicMatrix( continue; } $suite = $testsuite->getAttribute('name'); - $matrix = $this->createPhpunitJobs($matrix, $simpleMatrix, $suite, $run); + $matrix = $this->createPhpunitJobs($matrix, $composerInstall, $simpleMatrix, $suite, $run); } // phpunit.xml has no defined testsuites, or only defaults a "Default" if (count($matrix['include']) == 0) { - $matrix = $this->createPhpunitJobs($matrix, $simpleMatrix, 'all', $run); + $matrix = $this->createPhpunitJobs($matrix, $composerInstall, $simpleMatrix, 'all', $run); } } // skip phpcs on silverstripe-installer which include sample file for use in projects @@ -371,7 +379,7 @@ private function buildDynamicMatrix( } // phpcoverage also runs unit tests if ($this->doRunPhpCoverage($run, $this->githubRepository)) { - if ($simpleMatrix || $this->getCmsMajor() !== '4') { + if ($simpleMatrix || $composerInstall || $this->getCmsMajor() !== '4') { $matrix['include'][] = $this->createJob(0, [ 'phpcoverage' => true ]); @@ -400,7 +408,7 @@ private function buildDynamicMatrix( $job['php'] = '7.4'; } $matrix['include'][] = $job; - if (!$simpleMatrix) { + if (!$simpleMatrix && !$composerInstall) { $matrix['include'][] = $this->createJob(3, [ 'db' => DB_MYSQL_80, 'endtoend' => true, @@ -457,6 +465,7 @@ public function createJson(string $yml): string $run = []; $extraJobs = []; + $composerInstall = false; $dynamicMatrix = true; $simpleMatrix = false; foreach ($inputs as $input => $value) { @@ -474,6 +483,8 @@ public function createJson(string $yml): string $value = []; } $extraJobs = $value; + } else if ($input === 'composer_install') { + $composerInstall = $this->parseBoolValue($value); } else if ($input === 'dynamic_matrix') { $dynamicMatrix = $this->parseBoolValue($value); } else if ($input === 'simple_matrix') { @@ -486,8 +497,15 @@ public function createJson(string $yml): string } $matrix = ['include' => []]; + if ($composerInstall) { + $json = json_decode(file_get_contents($this->composerJsonPath)); + if (isset($json->config->platform->php) && preg_match('#^[0-9\.]+$#', $json->config->platform->php)) { + $this->phpVersionOverride = $json->config->platform->php; + } + } + if ($dynamicMatrix) { - $matrix = $this->buildDynamicMatrix($matrix, $run, $simpleMatrix); + $matrix = $this->buildDynamicMatrix($matrix, $run, $composerInstall, $simpleMatrix); } // extra jobs diff --git a/tests/JobCreatorTest.php b/tests/JobCreatorTest.php index 711794e..f03a8e4 100644 --- a/tests/JobCreatorTest.php +++ b/tests/JobCreatorTest.php @@ -33,6 +33,7 @@ public function provideCreateJob(): array 'db' => DB_MYSQL_57, 'composer_require_extra' => '', 'composer_args' => '', + 'composer_install' => false, 'name_suffix' => '', 'phpunit' => true, 'phpunit_suite' => 'all', @@ -177,6 +178,7 @@ public function provideCreateJson(): array 'db' => DB_MYSQL_57, 'composer_require_extra' => '', 'composer_args' => '--prefer-lowest', + 'composer_install' => 'false', 'name_suffix' => '', 'phpunit' => 'true', 'phpunit_suite' => 'all', @@ -194,6 +196,7 @@ public function provideCreateJson(): array 'db' => DB_MYSQL_57_PDO, 'composer_require_extra' => '', 'composer_args' => '', + 'composer_install' => 'false', 'name_suffix' => '', 'phpunit' => 'true', 'phpunit_suite' => 'all', @@ -211,6 +214,7 @@ public function provideCreateJson(): array 'db' => DB_MYSQL_80, 'composer_require_extra' => '', 'composer_args' => '', + 'composer_install' => 'false', 'name_suffix' => '', 'phpunit' => 'true', 'phpunit_suite' => 'all', @@ -297,6 +301,7 @@ private function getGenericYml(): string phplinting: true phpunit: true simple_matrix: false + composer_install: false EOT; } @@ -372,6 +377,7 @@ public function provideGetInputsValid(): array 'phplinting' => true, 'phpunit' => true, 'simple_matrix' => false, + 'composer_install' => false, 'github_repository' => 'myaccount/silverstripe-versioned', 'github_my_ref'=> 'pulls/1.10/module-standards' ] @@ -652,4 +658,117 @@ public function provideGetInstallerVersionCMS5FromComposer(): array ['myaccount/silverstripe-somemodule', '3', ['silverstripe/framework' => '^5'], '5.x-dev'], ]; } + + /** + * @dataProvider provideComposerInstall + */ + public function testComposerInstall( + string $composerInstall, + string $configPlatformPhp, + string $frameworkVersion, + array $expected + ): void { + $yml = implode("\n", [ + str_replace('composer_install: false', 'composer_install: ' . $composerInstall, $this->getGenericYml()), + <<composerJsonPath = '__composer.json'; + $composer = new stdClass(); + $composer->require = new stdClass(); + $composer->require->{'silverstripe/framework'} = $frameworkVersion; + if ($configPlatformPhp) { + $composer->config = new stdClass(); + $composer->config->platform = new stdClass(); + $composer->config->platform->php = $configPlatformPhp; + } + file_put_contents('__composer.json', json_encode($composer, JSON_PRETTY_PRINT + JSON_UNESCAPED_SLASHES)); + $json = json_decode($creator->createJson($yml)); + $actual = array_map(function ($include) { + return $include->name; + }, $json->include); + $this->assertSame($expected, $actual); + } finally { + unlink('__composer.json'); + } + } + + public function provideComposerInstall(): array + { + return [ + 'composerinstall_nophpversion_framework4' => [ + 'true', + '', + '4.x-dev', + [ + '7.4 mysql57 phpunit all' + ] + ], + 'composerinstall_nophpversion_framework5' => [ + 'true', + '', + '5.x-dev', + [ + '8.1 mysql57 phpunit all' + ] + ], + 'composerinstall_definedphpversion_framework5' => [ + 'true', + '21.99', + '5.x-dev', + [ + '21.99 mysql57 phpunit all' + ] + ], + 'composerinstall_invalidphpversion_framework5' => [ + 'true', + 'fish', + '5.x-dev', + [ + '8.1 mysql57 phpunit all' + ] + ], + 'composerupgrade_nophpversion_framework4' => [ + 'false', + '', + '4.x-dev', + [ + '7.4 prf-low mysql57 phpunit all', + '8.0 mysql57pdo phpunit all', + '8.1 mysql80 phpunit all' + ] + ], + 'composerupgrade_nophpversion_framework5' => [ + 'false', + '', + '5.x-dev', + [ + '8.1 prf-low mysql57 phpunit all', + '8.1 mysql80 phpunit all' + ] + ], + 'composerupgrade_definedphpversion_framework5' => [ + 'false', + '21.99', + '5.x-dev', + [ + '8.1 prf-low mysql57 phpunit all', + '8.1 mysql80 phpunit all' + ] + ], + 'composerupgrade_invalidphpversion_framework5' => [ + 'false', + 'fish', + '5.x-dev', + [ + '8.1 prf-low mysql57 phpunit all', + '8.1 mysql80 phpunit all' + ] + ], + ]; + } }