From e794d2f5f086dbbc00dea7d1710209ef1ae41cce Mon Sep 17 00:00:00 2001 From: gdh Date: Thu, 21 Jun 2018 13:29:04 +0000 Subject: [PATCH] Enhancing auto-approve: Allow specfication of label Also, remove label if the Pull-Request was previously approved, but is not any more. Do not attempt to add label if it is already there. Added commandline parameter for label-specification. --- auto-approval.php | 124 +++++++++++++++++++++++++++++++---------- github-api.php | 137 +++++++++++++++++++++++++++++++++++++++++++++- vip-go-ci.php | 52 +++++++++++------- 3 files changed, 264 insertions(+), 49 deletions(-) diff --git a/auto-approval.php b/auto-approval.php index cee4ac15e..f48a01484 100644 --- a/auto-approval.php +++ b/auto-approval.php @@ -82,14 +82,26 @@ function vipgoci_auto_approval( $options ) { } + /* + * Get label associated, but + * only our auto-approved one + */ + $pr_label = vipgoci_github_labels_get( + $options['repo-owner'], + $options['repo-name'], + $options['token'], + (int) $pr_item->number, + $options['autoapprove-label'] + ); + if ( false == $did_foreach ) { vipgoci_log( 'No action taken with Pull-Request #' . (int) $pr_item->number . ' ' . 'since no files were found', - array( - 'files_seen' => $files_seen, - ) + array( + 'files_seen' => $files_seen, + ) ); } @@ -103,13 +115,42 @@ function vipgoci_auto_approval( $options ) { 'as it contains ' . "\n\t" . 'file-types which are not ' . 'automatically approvable', - array( - 'autoapprove-filetypes' => - $options['autoapprove-filetypes'], + array( + 'autoapprove-filetypes' => + $options['autoapprove-filetypes'], - 'files_seen' => $files_seen, + 'files_seen' => $files_seen, ) ); + + + if ( false === $pr_label ) { + vipgoci_log( + 'Will not attempt to remove label ' . + 'from issue as it does not ' . + 'exist', + array( + 'repo_owner' => $options['repo-owner'], + 'repo_name' => $options['repo-name'], + 'pr_number' => $pr_item->number, + 'label_name' => $options['autoapprove-label'], + ) + ); + } + + else { + /* + * Remove auto-approve label + */ + vipgoci_github_label_remove_from_pr( + $options['repo-owner'], + $options['repo-name'], + $options['token'], + (int) $pr_item->number, + $pr_label->name, + $options['dry-run'] + ); + } } else if ( @@ -124,30 +165,31 @@ function vipgoci_auto_approval( $options ) { 'as it alters or creates ' . "\n\t" . 'only file-types that can be ' . 'automatically approved', - array( - 'repo_owner' - => $options['repo-owner'], + array( + 'repo_owner' + => $options['repo-owner'], - 'repo_name' - => $options['repo-name'], + 'repo_name' + => $options['repo-name'], - 'commit_id' - => $options['commit'], + 'commit_id' + => $options['commit'], - 'dry_run' - => $options['dry-run'], + 'dry_run' + => $options['dry-run'], - 'autoapprove-filetypes' => - $options['autoapprove-filetypes'], + 'autoapprove-filetypes' => + $options['autoapprove-filetypes'], - 'files_seen' => $files_seen, + 'files_seen' => $files_seen, ) ); /* * Actually approve, if not in dry-mode. - * Also add a label to the Pull-Request. + * Also add a label to the Pull-Request + * if applicable. */ vipgoci_github_approve_pr( $options['repo-owner'], @@ -159,14 +201,40 @@ function vipgoci_auto_approval( $options ) { $options['dry-run'] ); - vipgoci_github_label_add_to_pr( - $options['repo-owner'], - $options['repo-name'], - $options['token'], - $pr_item->number, - '[Status] VIP Auto Approved', - $options['dry-run'] - ); + + /* + * Add label to Pull-Request, but + * only if it is not associated already. + * If it is already associated, just log + * that fact. + */ + if ( false === $pr_label ) { + vipgoci_github_label_add_to_pr( + $options['repo-owner'], + $options['repo-name'], + $options['token'], + $pr_item->number, + $options['autoapprove-label'], + $options['dry-run'] + ); + } + + else { + vipgoci_log( + 'Will not add label to issue, ' . + 'as it already exists', + array( + 'repo_owner' => + $options['repo-owner'], + 'repo_name' => + $options['repo-name'], + 'pr_number' => + $pr_item->number, + 'label_name' => + $options['autoapprove-label'], + ) + ); + } } unset( $files_seen ); diff --git a/github-api.php b/github-api.php index 1a51eef59..910edac78 100644 --- a/github-api.php +++ b/github-api.php @@ -290,7 +290,8 @@ function vipgoci_github_post_url( ( ( true === $http_delete ) && - ( intval( $resp_headers['status'][0] ) !== 204 ) + ( intval( $resp_headers['status'][0] ) !== 204 ) && + ( intval( $resp_headers['status'][0] ) !== 200 ) ) ) { /* @@ -1463,7 +1464,7 @@ function vipgoci_github_pr_review_submit( count( $github_postfields['comments'] ) > $github_review_comments_max ) { - // Append a comment that there will be more reviews + // Append a comment that there will be more reviews $github_postfields['body'] .= "\n\r" . 'Posting will continue in further review(s)'; @@ -1984,6 +1985,7 @@ function vipgoci_github_authenticated_user_get( $github_token ) { return $current_user_info; } + /* * Add a particular label to a specific * Pull-Request (or issue). @@ -2030,3 +2032,134 @@ function vipgoci_github_label_add_to_pr( $github_token ); } + +/* + * Fetch labels associated with a + * particular issue/Pull-Request. + */ +function vipgoci_github_labels_get( + $repo_owner, + $repo_name, + $github_token, + $pr_number, + $label_to_look_for = null +) { + vipgoci_log( + 'Getting labels associated with GitHub issue', + array( + 'repo_owner' => $repo_owner, + 'repo_name' => $repo_name, + 'pr_number' => $pr_number, + ) + ); + /* + * Check first if we have + * got the information cached + */ + $cache_id = array( + __FUNCTION__, $repo_owner, $repo_name, + $github_token, $pr_number, $label_to_look_for + ); + + $cached_data = vipgoci_cache( $cache_id ); + + + /* + * If there is nothing cached, fetch it + * from GitHub. + */ + if ( false === $cached_data ) { + $github_url = + 'https://api.github.com/' . + 'repos/' . + rawurlencode( $repo_owner ) . '/' . + rawurlencode( $repo_name ) . '/' . + 'issues/' . + rawurlencode( $pr_number ) . '/' . + 'labels'; + + $data = vipgoci_github_fetch_url( + $github_url, + $github_token + ); + + $data = json_decode( $data ); + + vipgoci_cache( $cache_id, $data ); + } + + else { + $data = $cached_data; + } + + /* + * We got something -- validate it. + */ + + if ( empty( $data ) ) { + return false; + } + + else if ( ( ! empty( $data ) ) && ( null !== $label_to_look_for ) ) { + /* + * Decoding of data succeeded, + * look for any labels and return + * them specifically + */ + foreach( $data as $data_item ) { + if ( $data_item->name === $label_to_look_for ) { + return $data_item; + } + } + + return false; + } + + return $data; +} + + +/* + * Remove a particular label from a specific + * Pull-Request (or issue). + */ +function vipgoci_github_label_remove_from_pr( + $repo_owner, + $repo_name, + $github_token, + $pr_number, + $label_name, + $dry_run +) { + vipgoci_log( + ( $dry_run === true ? 'Would remove ' : 'Removing ' ) . + 'label from GitHub issue', + array( + 'repo_owner' => $repo_owner, + 'repo_name' => $repo_name, + 'pr_number' => $pr_number, + 'label_name' => $label_name, + ) + ); + + if ( true === $dry_run ) { + return; + } + + $github_url = + 'https://api.github.com/' . + 'repos/' . + rawurlencode( $repo_owner ) . '/' . + rawurlencode( $repo_name ) . '/' . + 'issues/' . + rawurlencode( $pr_number ) . '/' . + 'labels/' . + rawurlencode( $label_name ); + + vipgoci_github_post_url( + $github_url, + array(), + $github_token, + true // DELETE request will be sent + ); +} diff --git a/vip-go-ci.php b/vip-go-ci.php index c9ed11d1d..3033116f7 100755 --- a/vip-go-ci.php +++ b/vip-go-ci.php @@ -291,13 +291,14 @@ function vipgoci_run() { 'phpcs-path:', 'phpcs-standard:', 'phpcs-severity:', - 'autoapprove-filetypes:', 'php-path:', 'local-git-repo:', 'skip-folders:', 'lint:', 'phpcs:', 'autoapprove:', + 'autoapprove-filetypes:', + 'autoapprove-label:', 'help', 'debug-level:', ) @@ -316,6 +317,9 @@ function vipgoci_run() { "\t" . 'Options --repo-owner, --repo-name, --commit, --token, --local-git-repo are ' . PHP_EOL . "\t" . 'mandatory, while others are optional.' . PHP_EOL . PHP_EOL . + "\t" . 'Note that if option --autoapprove is specified, --autoapprove-filetypes and ' . PHP_EOL . + "\t" . '--autoapprove-label need to be specified as well.' . PHP_EOL . + PHP_EOL . "\t" . '--repo-owner=STRING Specify repository owner, can be an organization' . PHP_EOL . "\t" . '--repo-name=STRING Specify name of the repository' . PHP_EOL . "\t" . '--commit=STRING Specify the exact commit to scan (SHA)' . PHP_EOL . @@ -332,6 +336,7 @@ function vipgoci_run() { "\t" . ' altering only files of certain types' . PHP_EOL . "\t" . '--autoapprove-filetypes=STRING Specify what file-types can be auto-' . PHP_EOL . "\t" . ' approved. PHP files cannot be specified' . PHP_EOL . + "\t" . '--autoapprove-label=STRING String to use for labels when auto-approving' . PHP_EOL . "\t" . '--php-path=FILE Full path to PHP, if not specified the' . PHP_EOL . "\t" . ' default in $PATH will be used instead' . PHP_EOL . "\t" . '--branches-ignore=STRING,... What branches to ignore -- useful to make sure' . PHP_EOL . @@ -480,7 +485,7 @@ function vipgoci_run() { /* - * Should we auto-approve Pull-Requests + * Should we auto-approve Pull-Requests when * only altering certain file-types? */ @@ -493,35 +498,44 @@ function vipgoci_run() { 'php' ); + /* + * Do some sanity-checking on the parameters + */ + $options['autoapprove-filetypes'] = array_map( 'strtolower', $options['autoapprove-filetypes'] ); + if ( empty( $options['autoapprove-label'] ) ) { + $options['autoapprove-label'] = false; + } + + else { + $options['autoapprove-label'] = trim( + $options['autoapprove-label'] + ); + } + - /* - * Do some sanity-checking on the parameters - */ if ( ( true === $options['autoapprove'] ) && - ( empty( $options['autoapprove-filetypes'] ) ) + ( + ( empty( $options['autoapprove-filetypes'] ) ) || + ( false === $options['autoapprove-label'] ) + ) ) { - vipgoci_log( - 'Skipping auto-approval as no file-types ' . - 'are specified', - array( - 'autoapprove' => - $options['autoapprove'], - - 'autoapprove-filetypes' => - $options['autoapprove-filetypes'], - ) + vipgoci_sysexit( + 'To be able to auto-approve, file-types to approve ' . + 'must be specified, as well as a label; see --help ' . + 'for information', + array(), + VIPGOCI_EXIT_USAGE_ERROR ); - - $options['autoapprove'] = false; } - else if ( + + if ( ( true === $options['autoapprove'] ) && ( in_array( 'php', $options['autoapprove-filetypes'], true ) ) ) {