Skip to content

Commit d3476f5

Browse files
authored
Add support for suppression criteria (#25)
Adding support for custom `.codeguru-ignore.yml` with different criteria to suppress recommendations.
1 parent 560c539 commit d3476f5

21 files changed

+740
-184
lines changed

.codeguru-ignore.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: 1.0
2+
3+
ExcludeById:
4+
- 'security-764ea718423ce472134805f16e2616a36c3636fab21927453102041'
5+
6+
ExcludeTags:
7+
- 'maintainability'
8+
9+
excludeFiles:
10+
- "tst/**"
11+
- "test-data/**"

.github/workflows/cicd-demo.yml

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Demo of how to use a CodeGuru Reviewer CLI release in CICD.
2+
3+
on: [ push, pull_request, workflow_dispatch ]
4+
5+
permissions:
6+
id-token: write
7+
contents: read
8+
9+
jobs:
10+
RunDemo:
11+
name: Run CodeGuru Reviewer CLI in CICD
12+
runs-on: ubuntu-latest
13+
steps:
14+
# Setup Java 8 or higher.
15+
- name: Set up JDK 1.8
16+
uses: actions/setup-java@v1
17+
with:
18+
java-version: 1.8
19+
20+
# To configure this role, use this CDK example:
21+
# https://github.com/aws-samples/aws-codeguru-reviewer-cicd-cdk-sample
22+
- name: Configure AWS credentials
23+
uses: aws-actions/configure-aws-credentials@v1
24+
continue-on-error: true
25+
id: iam-role
26+
with:
27+
role-to-assume: arn:aws:iam::048169001733:role/GuruGitHubCICDRole
28+
aws-region: us-west-2
29+
30+
# Only continue if fetching the AWS credentials was successful.
31+
- uses: actions/checkout@v2
32+
if: steps.iam-role.outcome == 'success'
33+
with:
34+
fetch-depth: 0 # the fetch depth needs to be provided if we only want to check a certain commit range.
35+
- name: Build project
36+
if: steps.iam-role.outcome == 'success'
37+
run: ./gradlew clean installDist
38+
39+
# Download a release of the CodeGuru Reviewer CLI.
40+
- name: Download CodeGuru Reviewer CLI
41+
shell: bash
42+
env:
43+
VERSION: 0.1.0
44+
run: curl -OL "https://github.com/martinschaef/aws-codeguru-cli/releases/download/$VERSION/aws-codeguru-cli.zip"
45+
- run: unzip aws-codeguru-cli.zip
46+
47+
# Run CodeGuru Reviewer on the current project and use the --fail-on-recommendations option to fail
48+
# if any recommendations are reported.
49+
- name: Run Code Guru
50+
if: steps.iam-role.outcome == 'success'
51+
run: ./aws-codeguru-cli/bin/aws-codeguru-cli --region us-west-2 -r ./ -s ./src/main/java -b ./build/classes/java/main -c "${{ github.event.before }}:${{ github.event.after }}" --no-prompt --fail-on-recommendations

.github/workflows/guru-reviewer.yml

-52
This file was deleted.

.github/workflows/self-test-and-release.yml

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Created using https://github.com/aws-samples/aws-codeguru-reviewer-cicd-cdk-sample
1+
22
name: Self-test and release
33

44
on: [push, pull_request, workflow_dispatch]
55

66
permissions:
77
id-token: write
8-
contents: read
8+
contents: write # write permissions are needed to upload the release
99

1010
jobs:
1111
SelfTestPython:
@@ -141,7 +141,7 @@ jobs:
141141
if: steps.iam-role.outcome == 'success'
142142
shell: bash
143143
env:
144-
EXPECTED: 15
144+
EXPECTED: 16
145145
run: |
146146
[[ $(jq -r '.runs[0].results[].ruleId' code-guru/recommendations.sarif.json | wc -l) -eq $EXPECTED ]] || { echo "Expected $EXPECTED recommendations but got $(jq -r '.runs[0].results[].ruleId' code-guru/recommendations.sarif.json | wc -l)"; exit 1; }
147147
@@ -187,12 +187,10 @@ jobs:
187187
run: ./gradlew clean installDist distZip
188188

189189
- name: Get Release Version
190-
run: |
191-
echo "::set-output name=TAG_NAME::$(./gradlew properties -q | grep "version:" | awk '{print $2}')"
190+
run: echo "::set-output name=TAG_NAME::$(./gradlew properties -q | grep "version:" | awk '{print $2}')"
192191
id: version
193192

194193
- name: Release
195-
if: steps.iam-role.outcome == 'success'
196194
uses: softprops/action-gh-release@v1
197195
with:
198196
tag_name: ${{ steps.version.outputs.TAG_NAME }}

README.md

+84-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
# CodeGuru Reviewer CLI Wrapper
22
Simple CLI wrapper for CodeGuru reviewer that provides a one-line command to scan a local clone of a repository and
3-
receive results. This CLI wraps the [AWS CLI](https://aws.amazon.com/cli/) commands to communicated with
3+
receive results. This CLI wraps the [AWS CLI](https://aws.amazon.com/cli/) commands to communicate with
44
[AWS CodeGuru Reviewer](https://aws.amazon.com/codeguru/). Using CodeGuru Reviewer may generate metering fees
55
in your AWS account. See the [CodeGuru Reviewer pricing](https://aws.amazon.com/codeguru/pricing/) for details.
66

7+
### Table of Contents
8+
- [Installation](#installation)
9+
- [Using the CLI](#using-the-cli)
10+
- [Suppressing Recommendations](#suppressing-recommendations)
11+
- [Running from CI/CD](#running-from-cicd)
12+
- [Security](#security)
13+
- [License](#license)
14+
15+
## Installation
16+
717
### Prerequisites
818

9-
To run the CLI, we need to have a version of git, Java (e.g., [Amazon Corretto](https://aws.amazon.com/corretto/?filtered-posts.sort-by=item.additionalFields.createdDate&filtered-posts.sort-order=desc)) and the [AWS Command Line interface](https://aws.amazon.com/cli/) installed. Verify that both application are installed on our machine by running:
19+
To run the CLI, we need to have a version of git, Java (e.g., [Amazon Corretto](https://aws.amazon.com/corretto/?filtered-posts.sort-by=item.additionalFields.createdDate&filtered-posts.sort-order=desc))
20+
and the [AWS Command Line interface](https://aws.amazon.com/cli/) installed.
21+
Verify that both applications are installed on our machine by running:
1022

1123
```
1224
java -version
@@ -15,8 +27,11 @@ aws --version
1527
git --version
1628
```
1729

18-
We will also need working credentials on our machine to interact with our AWS account. Learn more about setting up credentials for AWS here: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html.
19-
The credentials must have at least the following permissions:
30+
We will also need working credentials on our machine to interact with our AWS account.
31+
Learn more about setting up credentials for AWS here: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html.
32+
33+
You can always use the CLI with *Admin* credentials but if you want to have a specific role to use the CLI, your
34+
credentials must have at least the following permissions:
2035

2136
```json
2237
{
@@ -55,17 +70,21 @@ The credentials must have at least the following permissions:
5570
```
5671

5772

58-
### Download the CLI and scan an Example
73+
## Using the CLI
5974

6075
You can download the [aws-codeguru-cli](https://github.com/aws/aws-codeguru-cli/releases/latest) from the releases section.
6176
Download the latest version and add it to your `PATH`:
6277
```
63-
curl -OL https://github.com/aws/aws-codeguru-cli/releases/download/0.0.1/aws-codeguru-cli.zip
78+
curl -OL https://github.com/aws/aws-codeguru-cli/releases/download/0.1.0/aws-codeguru-cli.zip
6479
unzip aws-codeguru-cli.zip
6580
export PATH=$PATH:./aws-codeguru-cli/bin
6681
```
6782

68-
Now, lets download an example project (requires Maven):
83+
84+
85+
### Scan an Example
86+
87+
Now, let's download an example project (requires Maven):
6988
```
7089
git clone https://github.com/aws-samples/amazon-codeguru-reviewer-sample-app
7190
cd amazon-codeguru-reviewer-sample-app
@@ -129,19 +148,71 @@ from not using a key to using a key, you need to delete the existing association
129148
then trigger a new scan with the CLI where you provide the key.
130149

131150

132-
### Running from CI/CD
151+
## Suppressing Recommendations
152+
153+
The CodeGuru Reviewer CLI searches for a file named `.codeguru-ignore.yml` where users can specify criteria
154+
based on which recommendations should be suppressed. Suppressed recommendations will not be returned by the CLI,
155+
but still show up in the AWS console.
156+
157+
The `.codeguru-ignore.yml` file can use any of the filter criteria shown below:
158+
159+
```yaml
160+
version: 1.0 # The Version field is mandatory. All other fields are optional.
161+
162+
# The CodeGuru Reviewer CLI produces a recommendations.json file which contains deterministic IDs for each
163+
# recommendation. This ID can be excluded so that this recommendation will not be reported in future runs of the
164+
# CLI.
165+
ExcludeById:
166+
- '4d2c43618a2dac129818bef77093730e84a4e139eef3f0166334657503ecd88d'
133167

134-
You can use this CLI to run CodeGuru from inside your CI/CD pipeline. See [this action](.github/workflows/self-test-and-release.yml#L30-L41) as an example. First, you need credentials for a role with the permissions mentioned above. If you already scanned
135-
the repository once with the CLI, the S3 bucket has been created, and the you do not need the `s3:CreateBucket*` permission anymore.
168+
# We can tell the CLI to exclude all recommendations below a certain severity. This can be useful in CI/CD integration.
169+
ExcludeBelowSeverity: 'HIGH'
136170

137-
Then you can run the CLI in non-interactive mode using the `--no-prompt` option. Further, you can specify a region and
138-
AWS profile using the `--region` and `--profile` options as needed:
171+
# We can exclude all recommendations that have a certain tag. Available Tags can be found here:
172+
# https://docs.aws.amazon.com/codeguru/detector-library/java/tags/
173+
# https://docs.aws.amazon.com/codeguru/detector-library/python/tags/
174+
ExcludeTags:
175+
- 'maintainability'
176+
177+
# We can also exclude recommendations by Detector ID. Detector IDs can be found here:
178+
# https://docs.aws.amazon.com/codeguru/detector-library
179+
ExcludeRecommendations:
180+
# Ignore all recommendations for a given Detector ID
181+
- detectorId: 'java/[email protected]'
182+
# Ignore all recommendations for a given Detector ID in a provided set of locations.
183+
# Locations can be written as Unix GLOB expressions using wildcard symbols.
184+
- detectorId: 'java/[email protected]'
185+
Locations:
186+
- 'src/main/java/com/folder01/*.java'
187+
188+
# Excludes all recommendations in the provided files. Files can be provided as Unix GLOB expressions.
189+
ExcludeFiles:
190+
- tst/**
191+
192+
```
193+
194+
Only the `version` field is mandatory in the `.codeguru-ignore.yml` file. All other entries are optional, and
195+
the CLI will understand any combination of those entries.
196+
197+
An example of such a configuration file can be found [here](https://github.com/aws/aws-codeguru-cli/blob/main/.codeguru-ignore.yml).
198+
199+
## Running from CI/CD
200+
201+
You can use this CLI to run CodeGuru from inside your CI/CD pipeline.
202+
See [this action](.github/workflows/cicd-demo.yml) as an example. To use the CLI in CI/CD, you need working credentials.
203+
You can use this [CDK template](https://github.com/aws-samples/aws-codeguru-reviewer-cicd-cdk-sample) to set up OIDC credentials for Github Actions.
204+
205+
Then you can run the CLI in non-interactive mode using the `--no-prompt` option, and use the option
206+
`--fail-on-recommendations` to return a non-zero exit code if recommendations are reported.
207+
You can specify a region and AWS profile using the `--region` and `--profile` options as needed:
139208
```
140-
aws-codeguru-cli --region [BUCKET REGION] --no-prompt -r ./ ...
209+
aws-codeguru-cli --region [BUCKET REGION] --no-prompt --fail-on-recommendations -r ./ ...
141210
```
142211
obtain the commit range works differently for different CI/CD providers. For example, GitHub provides the relevant
143212
commits via environment variables such as `${{ github.event.before }}` and `${{ github.event.after }}`.
144213

214+
An end-to-end example is provided in [this action](.github/workflows/cicd-demo.yml).
215+
145216
### Build from Source
146217

147218
To build the project, you need Java 8 or later. Checkout this repository and run:

aws-codeguru-reviewer.yml

-8
This file was deleted.

build.gradle

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ repositories {
2323

2424
defaultTasks 'clean', 'check', 'installDist'
2525

26-
version = '0.0.5'
26+
version = '0.1.0'
2727
jar.archiveName = "${jar.baseName}.${jar.extension}"
2828
distZip.archiveName = "${jar.baseName}.zip"
2929

@@ -39,6 +39,7 @@ dependencies {
3939

4040
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
4141
implementation 'com.fasterxml.jackson.core:jackson-core:2.13.0'
42+
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.0'
4243

4344
implementation 'com.beust:jcommander:1.81'
4445

src/main/java/com/amazonaws/gurureviewercli/Main.java

+23
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
import com.amazonaws.gurureviewercli.model.ErrorCodes;
3636
import com.amazonaws.gurureviewercli.model.GitMetaData;
3737
import com.amazonaws.gurureviewercli.model.ScanMetaData;
38+
import com.amazonaws.gurureviewercli.model.configfile.CustomConfiguration;
3839
import com.amazonaws.gurureviewercli.util.Log;
40+
import com.amazonaws.gurureviewercli.util.RecommendationPrinter;
41+
import com.amazonaws.gurureviewercli.util.RecommendationsFilter;
3942

4043
public class Main {
4144
private static final String REVIEWER_ENDPOINT_PATTERN = "https://codeguru-reviewer.%s.amazonaws.com";
@@ -60,6 +63,11 @@ public class Main {
6063
required = false)
6164
private boolean noPrompt;
6265

66+
@Parameter(names = {"--fail-on-recommendations"},
67+
description = "Return error code 5 if CodeGuru reports recommendations.",
68+
required = false)
69+
private boolean failOnRecommendations;
70+
6371
@Parameter(names = {"--root-dir", "-r"},
6472
description = "The root directory of the project that should be analyzed.",
6573
required = true)
@@ -140,6 +148,15 @@ public static void main(String[] argv) {
140148
}
141149
}
142150

151+
val customConfigFile = config.getRootDir().resolve(".codeguru-ignore.yml");
152+
if (customConfigFile.toFile().isFile()) {
153+
Log.info("Using customer provided config: " + customConfigFile.toAbsolutePath());
154+
int originalResultsCount = results.size();
155+
results = RecommendationsFilter.filterRecommendations(results,
156+
CustomConfiguration.load(customConfigFile));
157+
Log.info("%d recommendations were suppressed.", originalResultsCount - results.size());
158+
}
159+
143160
val outputPath = Paths.get(main.outputDir);
144161
if (!outputPath.toFile().exists()) {
145162
if (!outputPath.toFile().mkdirs()) {
@@ -148,6 +165,12 @@ public static void main(String[] argv) {
148165
}
149166
ResultsAdapter.saveResults(outputPath, results, scanMetaData);
150167
Log.info("Analysis finished.");
168+
if (main.failOnRecommendations && !results.isEmpty()) {
169+
RecommendationPrinter.print(results);
170+
Log.error("Exiting with code 5 because %d recommendations were found and --fail-on-recommendations"
171+
+ " is used.", results.size());
172+
System.exit(5);
173+
}
151174
} catch (GuruCliException e) {
152175
Log.error("%s: %s", e.getErrorCode(), e.getMessage());
153176
e.printStackTrace();

0 commit comments

Comments
 (0)