diff --git a/github-api.php b/github-api.php index e18995e18..0250d985f 100644 --- a/github-api.php +++ b/github-api.php @@ -2215,6 +2215,22 @@ function vipgoci_github_pr_review_submit( return; } + /* + * Reverse results before starting processing, + * so that results are shown in correct order + * after posting. + */ + + foreach ( + array_keys( + $results['issues'] + ) as $pr_number + ) { + $results['issues'][ $pr_number ] = array_reverse( + $results['issues'][ $pr_number ] + ); + } + foreach ( // The $results array is keyed by Pull-Request number array_keys( diff --git a/misc.php b/misc.php index 9e0bf1002..66b2ab45b 100644 --- a/misc.php +++ b/misc.php @@ -993,6 +993,74 @@ function vipgoci_issues_filter_duplicate( $file_issues_arr ) { return $file_issues_arr_new; } +/* + * Sort results to be submitted to GitHub according to + * severity of issues -- if configured to do so: + */ +function vipgoci_results_sort_by_severity( + $options, + &$results +) { + + if ( true !== $options['results-comments-sort'] ) { + return; + } + + vipgoci_log( + 'Sorting issues in results according to severity before submission', + array( + ) + ); + + + foreach( + array_keys( + $results['issues'] + ) as $pr_number + ) { + $current_pr_results = &$results['issues'][ $pr_number ]; + + /* + * Temporarily add severity + * column so we can sort using that. + */ + foreach( + array_keys( $current_pr_results ) as + $current_pr_result_item_key + ) { + $current_pr_results[ $current_pr_result_item_key ][ 'severity'] = + $current_pr_results[ $current_pr_result_item_key ]['issue']['severity']; + } + + /* + * Do the actual sorting. + */ + $severity_column = array_column( + $current_pr_results, + 'severity' + ); + + array_multisort( + $severity_column, + SORT_DESC, + $current_pr_results + ); + + /* + * Remove severity column + * afterwards. + */ + foreach( + array_keys( $current_pr_results ) as + $current_pr_result_item_key + ) { + unset( + $current_pr_results[ $current_pr_result_item_key ][ 'severity'] + ); + } + } +} + /* * Add pagebreak to a Markdown-style comment diff --git a/tests/ResultsSortBySeverityTest.php b/tests/ResultsSortBySeverityTest.php new file mode 100644 index 000000000..7c62b6ab6 --- /dev/null +++ b/tests/ResultsSortBySeverityTest.php @@ -0,0 +1,324 @@ +results = array( + 'issues' => array( + 24 => array( + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function other_foo()", + "source" => "RandomStandard.OtherSniff.random_function", + "severity" => 100, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 3, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 3, + "fixable" => false, + "type" => "INFO", + "line" => 3, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 2, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 40, + "fixable" => false, + "type" => "INFO", + "line" => 2, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 101, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 37, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + ), + + 7 => array( + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 7, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function testfoo()", + "source" => "RandomStandard.RandomSniff.test_function", + "severity" => 200, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function myfoo()", + "source" => "RandomStandard.RandomSniff.myfoo_function", + "severity" => 377, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + ), + ) + ); + } + + protected function tearDown() { + $this->options = null; + $this->results = null; + } + + /** + * @covers ::vipgoci_results_sort_by_severity + */ + public function testSortingNotConfigured() { + $this->options['results-comments-sort'] = false; + $this->results_before = $this->results; + + vipgoci_unittests_output_suppress(); + + vipgoci_results_sort_by_severity( + $this->options, + $this->results + ); + + vipgoci_unittests_output_unsuppress(); + + $this->assertNotEmpty( + $this->results_before + ); + + // Not configured to sort, should remain unchanged + $this->assertEquals( + $this->results_before, + $this->results + ); + } + + /** + * @covers ::vipgoci_results_sort_by_severity + */ + public function testSortingCorrect1() { + $this->options['results-comments-sort'] = true; + + vipgoci_unittests_output_suppress(); + + vipgoci_results_sort_by_severity( + $this->options, + $this->results + ); + + vipgoci_unittests_output_unsuppress(); + + // Configured to sort, should be changed + $this->assertEquals( + array( + 'issues' => array( + 24 => array( + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 101, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function other_foo()", + "source" => "RandomStandard.OtherSniff.random_function", + "severity" => 100, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 2, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 40, + "fixable" => false, + "type" => "INFO", + "line" => 2, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 37, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile1.php", + "file_line" => 3, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 3, + "fixable" => false, + "type" => "INFO", + "line" => 3, + "column" => 1, + "level" => "INFO" + ) + ), + ), + + 7 => array( + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function myfoo()", + "source" => "RandomStandard.RandomSniff.myfoo_function", + "severity" => 377, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function testfoo()", + "source" => "RandomStandard.RandomSniff.test_function", + "severity" => 200, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + array( + "type" => "phpcs", + "file_name" => "testfile2.php", + "file_line" => 100, + "issue" => array( + "message" => "Incorrect usage of function foo()", + "source" => "RandomStandard.RandomSniff.random_function", + "severity" => 7, + "fixable" => false, + "type" => "INFO", + "line" => 100, + "column" => 1, + "level" => "INFO" + ) + ), + ), + ) + ), + + $this->results + ); + } + + +} diff --git a/vip-go-ci.php b/vip-go-ci.php index 3b40c0ee3..facf97f40 100755 --- a/vip-go-ci.php +++ b/vip-go-ci.php @@ -139,6 +139,7 @@ function vipgoci_run() { 'repo-name:', 'commit:', 'token:', + 'results-comments-sort:', 'review-comments-max:', 'review-comments-total-max:', 'review-comments-ignore:', @@ -245,6 +246,8 @@ function vipgoci_run() { "\t" . '--repo-name=STRING Specify name of the repository' . PHP_EOL . "\t" . '--commit=STRING Specify the exact commit to scan (SHA)' . PHP_EOL . "\t" . '--token=STRING The access-token to use to communicate with GitHub' . PHP_EOL . + "\t" . '--results-comments-sort=BOOL Sort issues found according to severity, from high ' . PHP_EOL . + "\t" . ' to low, before submitting to GitHub. Not sorted by default.' . PHP_EOL . "\t" . '--review-comments-max=NUMBER Maximum number of inline comments to submit' . PHP_EOL . "\t" . ' to GitHub in one review. If the number of ' . PHP_EOL . "\t" . ' comments exceed this number, additional reviews ' . PHP_EOL . @@ -736,6 +739,7 @@ function vipgoci_run() { vipgoci_option_bool_handle( $options, 'dismissed-reviews-repost-comments', 'true' ); + vipgoci_option_bool_handle( $options, 'results-comments-sort', false ); if ( ( false === $options['lint'] ) && @@ -1630,6 +1634,16 @@ function vipgoci_run() { $prs_events_dismissed_by_team ); + /* + * Sort issues by severity level, so that + * highest severity is first. + */ + + vipgoci_results_sort_by_severity( + $options, + $results + ); + /* * Remove ignorable comments from $results. */