Adds Features per Fix tracking

This commit is contained in:
Jordan Brown
2017-09-08 11:27:53 -04:00
committed by CitadelStationBot
parent ce787e7726
commit 71e87d851c

View File

@@ -23,6 +23,12 @@
//This is required as otherwise somebody could trick the script into leaking the api key. //This is required as otherwise somebody could trick the script into leaking the api key.
$hookSecret = '08ajh0qj93209qj90jfq932j32r'; $hookSecret = '08ajh0qj93209qj90jfq932j32r';
$trackPRBalance = true; //set this to false to disable PR balance tracking
$prBalanceJson = ''; //Set this to the path you'd like the writable pr balance file to be stored, not setting it writes it to the working directory
$startingPRBalance = 3; //Starting balance for never before seen users
//team 133041: tgstation/commit-access
$maintainer_team_id = 133041; //org team id that is exempt from PR balance system, setting this to null will use anyone with write access to the repo. Get from https://api.github.com/orgs/:org/teams
//Api key for pushing changelogs. //Api key for pushing changelogs.
$apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c';
@@ -168,7 +174,7 @@ function tag_pr($payload, $opened) {
if(strpos($lowertitle, '[wip]') !== FALSE) if(strpos($lowertitle, '[wip]') !== FALSE)
$tags[] = 'Work In Progress'; $tags[] = 'Work In Progress';
$url = $payload['pull_request']['base']['repo']['url'] . '/issues/' . $payload['pull_request']['number'] . '/labels'; $url = $payload['pull_request']['issue_url'] . '/labels';
$existing_labels = file_get_contents($url, false, stream_context_create($scontext)); $existing_labels = file_get_contents($url, false, stream_context_create($scontext));
$existing_labels = json_decode($existing_labels, true); $existing_labels = json_decode($existing_labels, true);
@@ -195,6 +201,12 @@ function handle_pr($payload) {
switch ($payload["action"]) { switch ($payload["action"]) {
case 'opened': case 'opened':
tag_pr($payload, true); tag_pr($payload, true);
if(get_pr_code_friendliness($payload) < 0){
$balances = pr_balances();
$author = $payload['pull_request']['user']['login'];
if(isset($balances[$author]) && $balances[$author] < 0)
create_comment($payload, 'You currently have a negative Fix/Feature pull request delta of ' . $balances[$author] . '. Maintainers may close this PR at will. Fixing issues or improving the codebase will improve this score.');
}
break; break;
case 'edited': case 'edited':
case 'synchronize': case 'synchronize':
@@ -210,6 +222,11 @@ function handle_pr($payload) {
else { else {
$action = 'merged'; $action = 'merged';
checkchangelog($payload, true, true); checkchangelog($payload, true, true);
<<<<<<< HEAD
=======
update_pr_balance($payload);
$validated = TRUE; //pr merged events always get announced.
>>>>>>> af44a7a... Adds Features per Fix tracking (#29897)
} }
break; break;
default: default:
@@ -223,7 +240,116 @@ function handle_pr($payload) {
$msg = '['.$payload['pull_request']['base']['repo']['full_name'].'] Pull Request '.$action.' by '.htmlSpecialChars($payload['sender']['login']).': <a href="'.$payload['pull_request']['html_url'].'">'.htmlSpecialChars('#'.$payload['pull_request']['number'].' '.$payload['pull_request']['user']['login'].' - '.$payload['pull_request']['title']).'</a>'; $msg = '['.$payload['pull_request']['base']['repo']['full_name'].'] Pull Request '.$action.' by '.htmlSpecialChars($payload['sender']['login']).': <a href="'.$payload['pull_request']['html_url'].'">'.htmlSpecialChars('#'.$payload['pull_request']['number'].' '.$payload['pull_request']['user']['login'].' - '.$payload['pull_request']['title']).'</a>';
sendtoallservers('?announce='.urlencode($msg), $payload); sendtoallservers('?announce='.urlencode($msg), $payload);
}
//creates a comment on the payload issue
function create_comment($payload, $comment){
apisend($payload['pull_request']['comments_url'], 'POST', json_encode(array('body' => $comment)));
}
//returns the payload issue's labels as a flat array
function get_pr_labels_array($payload){
$url = $payload['pull_request']['issue_url'] . '/labels';
$issue = json_decode(apisend($url), true);
$result = array();
foreach($issue as $l)
$result[] = $l['name'];
return $result;
}
//helper for getting the path the the balance json file
function pr_balance_json_path(){
global $prBalanceJson;
return $prBalanceJson != '' ? $prBalanceJson : 'pr_balances.json';
}
//return the assoc array of login -> balance for prs
function pr_balances(){
$path = pr_balance_json_path();
if(file_exists($path))
return json_decode(file_get_contents($path), true);
else
return array();
}
//returns the difference in PR balance a pull request would cause
function get_pr_code_friendliness($payload, $oldbalance = null){
global $startingPRBalance;
if($oldbalance == null)
$oldbalance = $startingPRBalance;
$labels = get_pr_labels_array($payload);
//anything not in this list defaults to 0
$label_values = array(
'Fix' => 2,
'Refactor' => 2,
'Code Improvement' => 1,
'Priority: High' => 4,
'Priority: CRITICAL' => 5,
'Atmospherics' => 4,
'Logging' => 1,
'Feedback' => 1,
'Performance' => 3,
'Feature' => -1,
'Balance/Rebalance' => -1,
'Tweak' => -1,
'PRB: Reset' => $startingPRBalance - $oldbalance,
);
$affecting = 0;
$is_neutral = FALSE;
$found_something_positive = false;
foreach($labels as $l){
if($l == 'PRB: No Update') { //no effect on balance
$affecting = 0;
break;
}
else if(isset($label_values[$l])) {
$friendliness = $label_values[$l];
if($friendliness > 0)
$found_something_positive = true;
$affecting = $found_something_positive ? max($affecting, $friendliness) : $friendliness;
}
}
return $affecting;
}
function is_maintainer($payload, $author){
global $maintainer_team_id;
$repo_is_org = $payload['pull_request']['base']['repo']['owner']['type'] == 'Organization';
if($maintainer_team_id == null || !$repo_is_org) {
$collaburl = $payload['pull_request']['base']['repo']['collaborators_url'] . '/' . $author . '/permissions';
$perms = json_decode(apisend($collaburl), true);
$permlevel = $perms['permission'];
return $permlevel == 'admin' || $permlevel == 'write';
}
else {
$check_url = 'https://api.github.com/teams/' . $maintainer_team_id . '/memberships/' . $author;
$result = json_decode(apisend($check_url), true);
return isset($result['state']); //this field won't be here if they aren't a member
}
}
//payload is a merged pull request, updates the pr balances file with the correct positive or negative balance based on comments
function update_pr_balance($payload) {
global $startingPRBalance;
global $trackPRBalance;
if(!$trackPRBalance)
return;
$author = $payload['pull_request']['user']['login'];
if(is_maintainer($payload, $author)) //immune
return;
$balances = pr_balances();
if(!isset($balances[$author]))
$balances[$author] = $startingPRBalance;
$friendliness = get_pr_code_friendliness($payload, $balances[$author]);
$balances[$author] += $friendliness;
if($balances[$author] < 0 && $friendliness < 0)
create_comment($payload, 'Your Fix/Feature pull request delta is currently below zero (' . $balances[$author] . '). Maintainers may close future Feature/Tweak/Balance PRs. Fixing issues or helping to improve the codebase will raise this score.');
else if($balances[$author] >= 0 && ($balances[$author] - $friendliness) < 0)
create_comment($payload, 'Your Fix/Feature pull request delta is now above zero (' . $balances[$author] . '). Feel free to make Feature/Tweak/Balance PRs.');
$balances_file = fopen(pr_balance_json_path(), 'w');
fwrite($balances_file, json_encode($balances));
fclose($balances_file);
} }
function has_tree_been_edited($payload, $tree){ function has_tree_been_edited($payload, $tree){