Skip to content

Commit

Permalink
Merge pull request #51 from creative-commoners/pulls/main/fix-random-…
Browse files Browse the repository at this point in the history
…number

Various fixes required to get supported modules data to be correctly utilised
  • Loading branch information
GuySartorelli authored May 21, 2024
2 parents 7e78631 + 8206cb1 commit 6c2b613
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 49 deletions.
89 changes: 74 additions & 15 deletions funcs_scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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()
Expand All @@ -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
*
Expand Down Expand Up @@ -350,21 +405,25 @@ 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
{
$chars = str_split(module_name() . $scriptName);
$codes = array_map(fn($c) => ord($c), $chars);
$sum = array_sum($codes);
$remainder = $sum % ($max + 1);
return $remainder + $offset;
}

/**
* Determine if the current branch is either 1 or 1.2 numeric style
* Can also be pulls/<number>/... style
*/
function current_branch_name_is_numeric_style()
{
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);
$currentBranch = cmd('git rev-parse --abbrev-ref HEAD', $MODULE_DIR);
if (preg_match('#^(pulls/)?([0-9]+)(\.[0-9]+)?(/|$)#', $currentBranch)) {
return true;
}
$relativePath = $matches[1];
$chars = str_split("$MODULE_DIR-$relativePath");
$codes = array_map(fn($c) => ord($c), $chars);
mt_srand(array_sum($codes));
return mt_rand(0, $max) + $offset;
return false;
}
3 changes: 2 additions & 1 deletion funcs_utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
10 changes: 7 additions & 3 deletions scripts/cms-any/dispatch-ci.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?php

// run on two consecutive days of the week
$dayOfWeek = predictable_random_int(6);
$dayOfWeek = predictable_random_int('dispatch-ci', 6);
$nextDayOfWeek = $dayOfWeek === 6 ? 0 : $dayOfWeek + 1;
$runsOnDaysOfWeek = sprintf('%s,%s', $dayOfWeek, $nextDayOfWeek);
// run at a random hour of the day
$runOnHour = predictable_random_int(23);
$runOnHour = predictable_random_int('dispatch-ci', 23);
// run at a random minute of the hour rounded to 5 minutes
$runOnMinute = predictable_random_int(11) * 5;
$runOnMinute = predictable_random_int('dispatch-ci', 11) * 5;

$cron = "$runOnMinute $runOnHour * * $runsOnDaysOfWeek";
$humanCron = human_cron($cron);
Expand Down Expand Up @@ -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)) {
Expand Down
6 changes: 3 additions & 3 deletions scripts/cms-any/keepalive.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

// run on a day of the month up to the 28th
$runOnDay = predictable_random_int(27, 1);
$runOnDay = predictable_random_int('keepalive', 27, 1);
// run at a random hour of the day
$runOnHour = predictable_random_int(23);
$runOnHour = predictable_random_int('keepalive', 23);
// run at a random minute of the hour rounded to 5 minutes
$runOnMinute = predictable_random_int(11) * 5;
$runOnMinute = predictable_random_int('keepalive', 11) * 5;

$cron = "$runOnMinute $runOnHour $runOnDay * *";
$humanCron = human_cron($cron);
Expand Down
13 changes: 8 additions & 5 deletions scripts/cms-any/merge-ups.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

// run on a random day of the week
$runOnDay = predictable_random_int(6);
$runOnDay = predictable_random_int('merge-ups', 6);
// run at a random hour of the day
$runOnHour = predictable_random_int(23);
$runOnHour = predictable_random_int('merge-ups', 23);
// run at a random minute of the hour rounded to 5 minutes
$runOnMinute = predictable_random_int(11) * 5;
$runOnMinute = predictable_random_int('merge-ups', 11) * 5;

// If there's a CI workflow, offset mergeups from the CI run by 3 days
if (check_file_exists('.github/workflows/dispatch-ci.yml')) {
Expand Down Expand Up @@ -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');
}
6 changes: 3 additions & 3 deletions scripts/cms-any/update-js.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
$account = module_account();

// run at a random hour of the day
$runOnHour = predictable_random_int(23);
$runOnHour = predictable_random_int('update-js', 23);
// run at a random minute of the hour rounded to 5 minutes
$runOnMinute = predictable_random_int(11) * 5;
$runOnMinute = predictable_random_int('update-js', 11) * 5;
// run on a 1st of the month
$runOnDay = 1;

Expand Down Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion scripts/cms5/phpstan.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

// Only valid for non-theme modules
if (!is_module() || is_theme() || module_is_recipe()) {
if (!is_module() || is_theme() || module_is_recipe() || is_tooling()) {
return;
}

Expand Down
25 changes: 13 additions & 12 deletions tests/FuncsScriptsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ class FuncsScriptsTest extends TestCase
{
public function testPredictableRandomInt()
{
global $MODULE_DIR;
$MODULE_DIR = 'lorem';
$this->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));
}
}
16 changes: 10 additions & 6 deletions update_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -65,14 +66,16 @@
}
cmd("git remote add pr-remote $prOrigin", $MODULE_DIR);

$useDefaultBranch = has_wildcard_major_version_mapping();

if ($input->getOption('update-prs')) {
// checkout latest existing pr branch
cmd('git fetch pr-remote', $MODULE_DIR);
$allBranches = explode("\n", cmd('git branch -r', $MODULE_DIR));
// 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");
Expand Down Expand Up @@ -107,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));
Expand All @@ -138,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");
}

Expand Down

0 comments on commit 6c2b613

Please sign in to comment.