From 7f537033e0248f80e7155e4dedf1d2993134db4c Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Fri, 17 May 2024 14:50:52 +1200 Subject: [PATCH 1/2] FIX Do not use random number for predictable int --- funcs_scripts.php | 20 +++++--------------- scripts/cms-any/dispatch-ci.php | 6 +++--- scripts/cms-any/keepalive.php | 6 +++--- scripts/cms-any/merge-ups.php | 6 +++--- scripts/cms-any/update-js.php | 4 ++-- tests/FuncsScriptsTest.php | 25 +++++++++++++------------ update_command.php | 1 + 7 files changed, 30 insertions(+), 38 deletions(-) diff --git a/funcs_scripts.php b/funcs_scripts.php index 979d8fe..e972f87 100644 --- a/funcs_scripts.php +++ b/funcs_scripts.php @@ -350,21 +350,11 @@ function human_cron(string $cron): string * between 1 and 28 * Note that this will return the exact same value every time it is called for a given filename in a given module */ -function predictable_random_int($max, $offset = 0): int +function predictable_random_int($scriptName, $max, $offset = 0): int { - global $MODULE_DIR; - $callingFile = debug_backtrace()[0]['file']; - // remove absolute path e.g. /home/myuser/... - $moduleStandardiserDir = basename(__DIR__); - $dirQuoted = preg_quote($moduleStandardiserDir); - // double $dirQuoted is for github actions CI where there which will have a directory strcture - // with /module-standardiser/module-standardiser/... - if (!preg_match("#/$dirQuoted/$dirQuoted/(.+)$#", $callingFile, $matches)) { - preg_match("#/$dirQuoted/(.+)$#", $callingFile, $matches); - } - $relativePath = $matches[1]; - $chars = str_split("$MODULE_DIR-$relativePath"); + $chars = str_split(module_name() . $scriptName); $codes = array_map(fn($c) => ord($c), $chars); - mt_srand(array_sum($codes)); - return mt_rand(0, $max) + $offset; + $sum = array_sum($codes); + $remainder = $sum % ($max + 1); + return $remainder + $offset; } diff --git a/scripts/cms-any/dispatch-ci.php b/scripts/cms-any/dispatch-ci.php index 41e2450..eb0ec48 100644 --- a/scripts/cms-any/dispatch-ci.php +++ b/scripts/cms-any/dispatch-ci.php @@ -1,13 +1,13 @@ assertSame(0, predictable_random_int(15)); - $this->assertSame(25, predictable_random_int(30)); - $this->assertSame(45, predictable_random_int(30, 20)); - $MODULE_DIR = 'donuts'; - $this->assertSame(13, predictable_random_int(15)); - // use eval to simulate calling from a different file - // it will suffix "(19) : eval()'d code" to the calling file in debug_backtrace() - $ret = null; - eval('$ret = predictable_random_int(15);'); - $this->assertSame(2, $ret); + global $GITHUB_REF; + // set $GITHUB_REF because by module_name() which is used by predictable_random_int() + $GITHUB_REF = 'myaccount/lorem'; + $this->assertSame(1, predictable_random_int('test-script', 15)); + // Setting a higher max does more than just add to the result, it's somewhat random + $this->assertSame(23, predictable_random_int('test-script', 30)); + // Setting an offset simply adds to the result of the same max as above + $this->assertSame(43, predictable_random_int('test-script', 30, 20)); + // Changing $GITHUB_REF will change the result + $GITHUB_REF = 'myaccount/donuts'; + $this->assertSame(15, predictable_random_int('test-script', 15)); + // Changing the script name will change the result + $this->assertSame(6, predictable_random_int('different-script', 15)); } } diff --git a/update_command.php b/update_command.php index da64500..e4ad904 100644 --- a/update_command.php +++ b/update_command.php @@ -47,6 +47,7 @@ $cloneUrl = $module['cloneUrl']; $MODULE_DIR = MODULES_DIR . "/$repo"; $GITHUB_REF = "$account/$repo"; + // clone repo // always clone the actual remote even when doing update-prs even though this is slower // reason is because we read origin in .git/config to workout the actual $account in From 8206cb1e0b19fc2d988b60f2ad90703c0405f10a Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Tue, 21 May 2024 15:56:58 +1200 Subject: [PATCH 2/2] FIX Various fixes for processing tooling, workflow and misc repos --- funcs_scripts.php | 71 ++++++++++++++++++++++++++++++++- funcs_utils.php | 3 +- scripts/cms-any/dispatch-ci.php | 4 ++ scripts/cms-any/merge-ups.php | 7 +++- scripts/cms-any/update-js.php | 2 +- scripts/cms5/phpstan.php | 2 +- update_command.php | 15 ++++--- 7 files changed, 92 insertions(+), 12 deletions(-) diff --git a/funcs_scripts.php b/funcs_scripts.php index e972f87..1fe20a6 100644 --- a/funcs_scripts.php +++ b/funcs_scripts.php @@ -150,6 +150,10 @@ function is_module() return false; } + if (is_gha_repository()) { + return false; + } + $contents = read_file('composer.json'); $json = json_decode($contents); if (is_null($json)) { @@ -158,7 +162,7 @@ function is_module() } // config isn't technically a Silverstripe CMS module, but we treat it like one. - if ($json->name === 'silverstripe/config') { + if (($json->name ?? '') === 'silverstripe/config') { return true; } @@ -238,6 +242,7 @@ function is_docs() /** * Determine if the module being processed is a gha-* repository e.g. gha-ci + * aka "WORKFLOW" * * Example usage: * is_gha_repository() @@ -254,6 +259,56 @@ function is_gha_repository() ); } +/** + * Determine if the module being processed is "TOOLING" + * + * Example usage: + * is_gha_repository() + */ +function is_tooling() +{ + global $GITHUB_REF; + return in_array( + $GITHUB_REF, + array_column( + MetaData::getAllRepositoryMetaData()[MetaData::CATEGORY_TOOLING], + 'github' + ) + ); +} + +/** + * Determine if the module being processed is "MISC" + * + * Example usage: + * is_gha_repository() + */ +function is_misc() +{ + global $GITHUB_REF; + return in_array( + $GITHUB_REF, + array_column( + MetaData::getAllRepositoryMetaData()[MetaData::CATEGORY_MISC], + 'github' + ) + ); +} + +/** + * Determine if the module being processed has a wildcard major version mapping + * in silverstripe/supported-modules repositories.json + * + * Example usage: + * has_wildcard_major_version_mapping() + */ +function has_wildcard_major_version_mapping() +{ + global $GITHUB_REF; + $repoData = MetaData::getMetaDataForRepository($GITHUB_REF); + return array_key_exists('*', $repoData['majorVersionMapping']); +} + /** * Return the module name without the account e.g. silverstripe/silverstripe-admin with return silverstripe-admin * @@ -358,3 +413,17 @@ function predictable_random_int($scriptName, $max, $offset = 0): int $remainder = $sum % ($max + 1); return $remainder + $offset; } + +/** + * Determine if the current branch is either 1 or 1.2 numeric style + * Can also be pulls//... style + */ +function current_branch_name_is_numeric_style() +{ + global $MODULE_DIR; + $currentBranch = cmd('git rev-parse --abbrev-ref HEAD', $MODULE_DIR); + if (preg_match('#^(pulls/)?([0-9]+)(\.[0-9]+)?(/|$)#', $currentBranch)) { + return true; + } + return false; +} diff --git a/funcs_utils.php b/funcs_utils.php index 5a92e13..1208e25 100644 --- a/funcs_utils.php +++ b/funcs_utils.php @@ -287,13 +287,14 @@ function current_branch_cms_major( return MetaData::HIGHEST_STABLE_CMS_MAJOR; } + $contents = ''; if ($composerJson) { $contents = $composerJson; } elseif (check_file_exists('composer.json')) { $contents = read_file('composer.json'); } $composerJson = json_decode($contents); - if (is_null($composerJson)) { + if (is_null($composerJson) && check_file_exists('composer.json')) { $lastError = json_last_error(); error("Could not parse from composer.json - last error was $lastError"); } diff --git a/scripts/cms-any/dispatch-ci.php b/scripts/cms-any/dispatch-ci.php index eb0ec48..a9afb3a 100644 --- a/scripts/cms-any/dispatch-ci.php +++ b/scripts/cms-any/dispatch-ci.php @@ -40,6 +40,10 @@ $dispatchCiPath = '.github/workflows/dispatch-ci.yml'; $ciPath = '.github/workflows/ci.yml'; $shouldHaveDispatchCi = (is_module() || is_composer_plugin()) && !is_docs() && !is_gha_repository(); +// If module non has_wildcard_major_version_mapping then dispatch-ci.yml should always be present +if (!has_wildcard_major_version_mapping()) { + $shouldHaveDispatchCi = true; +} if ($shouldHaveDispatchCi) { if (check_file_exists($ciPath)) { diff --git a/scripts/cms-any/merge-ups.php b/scripts/cms-any/merge-ups.php index ea6a49e..566d685 100644 --- a/scripts/cms-any/merge-ups.php +++ b/scripts/cms-any/merge-ups.php @@ -59,6 +59,9 @@ rename_file_if_exists('.github/workflows/merge-ups.yml', '.github/workflows/merge-up.yml'); } -if (!module_is_recipe() && !is_meta_repo()) { - write_file_even_if_exists('.github/workflows/merge-up.yml', $content); +if (current_branch_name_is_numeric_style() && !module_is_recipe()) { + write_file_even_if_exists('.github/workflows/merge-up.yml', $content); +} else { + // remove any merge-up.yml that was previously added though shouldn't be there + delete_file_if_exists('.github/workflows/merge-up.yml'); } diff --git a/scripts/cms-any/update-js.php b/scripts/cms-any/update-js.php index 26e5246..9577b08 100644 --- a/scripts/cms-any/update-js.php +++ b/scripts/cms-any/update-js.php @@ -34,6 +34,6 @@ uses: silverstripe/gha-update-js@v1 EOT; -if (check_file_exists('package.json')) { +if (check_file_exists('package.json') && check_file_exists('yarn.lock')) { write_file_even_if_exists('.github/workflows/update-js.yml', $content); } diff --git a/scripts/cms5/phpstan.php b/scripts/cms5/phpstan.php index d0758bc..4ee155e 100644 --- a/scripts/cms5/phpstan.php +++ b/scripts/cms5/phpstan.php @@ -1,7 +1,7 @@ getOption('update-prs')) { // checkout latest existing pr branch cmd('git fetch pr-remote', $MODULE_DIR); @@ -73,7 +75,7 @@ // example branch name: pulls/5/module-standardiser-1691550112 $allBranches = array_map('trim', $allBranches); $allBranches = array_filter($allBranches, function($branch) { - return preg_match('#^pr\-remote/pulls/[0-9\.]+/module\-standardiser\-[0-9]{10}$#', $branch); + return preg_match('#^pr\-remote/pulls/.+?/module\-standardiser\-[0-9]{10}$#', $branch); }); if (empty($allBranches)) { warning("Could not find an existing PR branch for $repo - skipping"); @@ -108,11 +110,12 @@ $defaultBranch = cmd($cmd, $MODULE_DIR); cmd("git checkout $defaultBranch", $MODULE_DIR); - if (is_meta_repo()) { - $branchToCheckout = $allBranches[0]; + $currentBranch = cmd('git rev-parse --abbrev-ref HEAD', $MODULE_DIR); + + // checkout the branch to run scripts over + if ($useDefaultBranch) { + $branchToCheckout = $currentBranch; } else { - // checkout the branch to run scripts over - $currentBranch = cmd('git rev-parse --abbrev-ref HEAD', $MODULE_DIR); // ensure that we're on a standard next-minor style branch if (!ctype_digit($currentBranch)) { $tmp = array_filter($allBranches, fn($branch) => ctype_digit($branch)); @@ -139,7 +142,7 @@ cmd("git checkout $branchToCheckout", $MODULE_DIR); // ensure that this branch actually supports the cmsMajor we're targetting - if ($branchOption !== 'github-default' && current_branch_cms_major() !== $cmsMajor) { + if (!$useDefaultBranch && $branchOption !== 'github-default' && current_branch_cms_major() !== $cmsMajor) { error("Branch $branchToCheckout does not support CMS major version $cmsMajor"); }