Skip to content

Commit

Permalink
NEW Update rulesets
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed May 22, 2024
1 parent b8961f2 commit ceac308
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 0 deletions.
9 changes: 9 additions & 0 deletions funcs_scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,12 @@ function current_branch_name_is_numeric_style()
}
return false;
}

/**
* Get the current branch name
*/
function current_branch_name()
{
global $MODULE_DIR;
return cmd('git rev-parse --abbrev-ref HEAD', $MODULE_DIR);
}
38 changes: 38 additions & 0 deletions funcs_utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,44 @@ function output_repos_with_labels_updated()
$io->writeln('');
}

/**
* Outputs a list of repos that that had rulesets updated
* If there was an error with a run (probably a secondary rate limit), this can be
* copy pasted into the --exclude option for the next run to continue from where you left off
*/
function output_repos_with_rulesets_created_or_updated()
{
if (running_unit_tests()) {
return;
}
global $REPOS_WITH_RULESETS_UPDATED;
$io = io();
$io->writeln('');
$io->writeln('Repos with rulesets created/updated (add to --exclude if you need to re-run):');
$io->writeln(implode(',', $REPOS_WITH_RULESETS_UPDATED));
$io->writeln('');
}

function create_ruleset($type, $additionalConditionsInclude = [])
{
$ruleset = file_get_contents("rulesets/$type-ruleset.json");
if (!$ruleset) {
error("Could not read ruleset for $type");
}
$json = json_decode($ruleset, true);
if ($type == 'branch') {
$json['name'] = BRANCH_RULESET_NAME;
} elseif ($type === 'tag') {
$json['name'] = TAG_RULESET_NAME;
} else {
error("Invalid ruleset type: $type");
}
foreach ($additionalConditionsInclude as $value) {
$json['conditions']['include'][] = $value;
}
return json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

/**
* Works out which branch in a module to checkout before running scripts on it
*
Expand Down
44 changes: 44 additions & 0 deletions rulesets/branch-ruleset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "<RULESET_NAME>",
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"refs/heads/[0-9]*"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "creation"
},
{
"type": "update"
},
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 2,
"dismiss_stale_reviews_on_push": true,
"require_code_owner_review": false,
"require_last_push_approval": true,
"required_review_thread_resolution": false
}
}
],
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "always"
}
]
}
34 changes: 34 additions & 0 deletions rulesets/tag-ruleset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "<RULESET_NAME>",
"target": "tag",
"enforcement": "active",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"~ALL"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "creation"
},
{
"type": "update"
}
],
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "always"
}
]
}
111 changes: 111 additions & 0 deletions rulesets_command.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

use SilverStripe\SupportedModules\MetaData;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;

$rulesetsCommand = function(InputInterface $input, OutputInterface $output): int {
// This is the code that is executed when running the 'rulesets' command

// variables
global $OUT, $REPOS_WITH_RULESETS_UPDATED;
$OUT = $output;

// validate system is ready
validate_system();

// setup directories
setup_directories($input, [DATA_DIR]);

// modules
$modules = [];
$repos = [];
$modulesCurrentMajor = filtered_modules(MetaData::HIGHEST_STABLE_CMS_MAJOR, $input);
$modulesPreviousMajor = filtered_modules(MetaData::HIGHEST_STABLE_CMS_MAJOR - 1, $input);
foreach ([$modulesCurrentMajor, $modulesPreviousMajor] as $modulesList) {
foreach ($modulesList as $module) {
$repo = $module['repo'];
$ghrepo = $module['ghrepo'];
if (in_array($repo, $repos) || in_array($ghrepo, LABELS_EXCLUDE_GHREPOS)) {
continue;
}
// Important! Only include modules on the "silverstripe" account
if (!preg_match('#^silverstripe/#', $repo)) {
continue;
}
$modules[] = $module;
$repos[] = $repo;
}
}

// sboyd
$modules = [
// ['account' => 'emteknetnz', 'repo' => 'test-thing'],
['account' => 'emteknetnz', 'repo' => 'tmp-docblock-annotator'],
];

$branchRuleset = file_get_contents('rulesets/branch-ruleset.json');
$tagRuleset = file_get_contents('rulesets/tag-ruleset.json');

// update rulesets
foreach ($modules as $module) {
$account = $module['account'];
$repo = $module['repo'];

// Fetch existing rulesets
$rulesets = github_api("https://api.github.com/repos/$account/$repo/rulesets");
$branchRulesetID = 0;
$tagRulesetID = 0;
foreach ($rulesets as $ruleset) {
$id = $ruleset['id'];
$name = $ruleset['name'];
if ($name === BRANCH_RULESET_NAME) {
$branchRulesetID = $id;
}
if ($name === TAG_RULESET_NAME) {
$tagRulesetID = $id;
}
}

// Get any additional branches to add
// Assumption is that if the current (default) branch is main/master, then the repo uses
// a non-numeric style branching system (e.g. main, master) and that needs to be protected
// [0-9]* branch protection will still be applied, on the chance that the repo is converted
// to uses a numeric style branch system in the future and we would want branch protection
// to start immediately on the new branches
$additionalConditionsInclude = [];
$currentBranch = current_branch_name();
if (in_array($currentBranch, ['main', 'master'])) {
$additionalConditionsInclude[] = "refs/heads/$currentBranch";
}

// Create rulesets
$branchRuleset = create_ruleset('branch', $additionalConditionsInclude);
$tagRuleset = create_ruleset('tag');

// Create new rule set
if (!$branchRulesetID) {
$url = "https://api.github.com/repos/$account/$repo/rulesets";
github_api($url, 'POST', $branchRuleset);
}
if (!$tagRulesetID) {
$url = "https://api.github.com/repos/$account/$repo/rulesets";
github_api($url, 'POST', $tagRuleset);
}

// Update existing ruleset - don't bother to check if the ruleset is the same
// this is a fairly quick update so no need to optimise this
if ($branchRulesetID) {
$url = "https://api.github.com/repos/$account/$repo/rulesets/$branchRulesetID";
github_api($url, 'PUT', $branchRuleset);
}
if ($tagRulesetID) {
$url = "https://api.github.com/repos/$account/$repo/rulesets/$tagRulesetID";
github_api($url, 'PUT', $tagRuleset);
}
$REPOS_WITH_RULESETS_UPDATED[] = $repo;
}
output_repos_with_rulesets_created_or_updated();
return Command::SUCCESS;
};
12 changes: 12 additions & 0 deletions run.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
include 'funcs_utils.php';
include 'update_command.php';
include 'labels_command.php';
include 'rulesets_command.php';

use SilverStripe\SupportedModules\MetaData;
use Symfony\Component\Console\Application;
Expand All @@ -19,13 +20,16 @@
const TOOL_URL = 'https://github.com/silverstripe/module-standardiser';
const PR_TITLE = 'MNT Run module-standardiser';
const PR_DESCRIPTION = 'This pull-request was created automatically by [module-standardiser](' . TOOL_URL . ')';
const BRANCH_RULESET_NAME = 'Silverstripe branch ruleset';
const TAG_RULESET_NAME = 'Silverstripe tag ruleset';

// global variables
$MODULE_DIR = '';
$GITHUB_REF = '';
$PRS_CREATED = [];
$REPOS_WITH_PRS_CREATED = [];
$REPOS_WITH_LABELS_UPDATED = [];
$REPOS_WITH_RULESETS_UPDATED = [];
$OUT = null;

// options
Expand Down Expand Up @@ -102,6 +106,14 @@
->addOption(...$optionNoDelete)
->setCode($labelsCommand);

$app->register('rulesets')
->setDescription('Script to set rulesets on all repos only on the silverstripe account')
->addOption(...$optionOnly)
->addOption(...$optionExclude)
->addOption(...$optionDryRun)
->addOption(...$optionNoDelete)
->setCode($rulesetsCommand);

try {
$app->run();
} catch (Error|Exception $e) {
Expand Down

0 comments on commit ceac308

Please sign in to comment.