diff --git a/.github/workflows/detection-testing.yml b/.github/workflows/detection-testing.yml index 80062fe601..2d0bc6ca44 100644 --- a/.github/workflows/detection-testing.yml +++ b/.github/workflows/detection-testing.yml @@ -287,8 +287,8 @@ jobs: name: DetectionFailureManifest path: | bin/docker_detection_tester/detection_failure_manifest.json - + #Always clean these up, they make the output messy - name: Clean up intermediate Files uses: geekyeggo/delete-artifact@v1 @@ -305,7 +305,34 @@ jobs: config_tests_7.json.results config_tests_8.json.results config_tests_9.json.results + + - name: Upload S3 Badge and Summary Artifacts for Nightly Scheduled Run + if: ${{ github.event_name == 'schedule' }} + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + aws-region: us-west-2 + run: | + cd bin/docker_detection_tester + python generate_detection_coverage_badge.py --input_summary_file summary_test_results.json --output_badge_file detection_coverage.svg --badge_string "Pass Rate" + + + #Upload artifact (summary test results) + aws s3 cp summary_test_results.json s3://security_content/reporting/summary_test_results.json + + # make the file public since it is not by default + aws s3api put-object-acl --bucket security-content --key summary_test_results.json --acl public-read + + + #Upload artifact (test results coverage badge) + aws s3 cp detection_coverage.svg s3://security_content/reporting/detection_coverage.svg + + # make the file public since it is not by default + aws s3api put-object-acl --bucket security-content --key detection_coverage.svg --acl public-read + diff --git a/bin/docker_detection_tester/generate_detection_coverage_badge.py b/bin/docker_detection_tester/generate_detection_coverage_badge.py new file mode 100644 index 0000000000..142e5b488c --- /dev/null +++ b/bin/docker_detection_tester/generate_detection_coverage_badge.py @@ -0,0 +1,65 @@ +import argparse +import json +import sys + +RAW_BADGE_SVG = ''' + + + + + + + + + + + + + + {} + {} + +''' + + +parser = argparse.ArgumentParser(description='Use a summary.json file to generate a test coverage badge') +parser.add_argument('-i', "--input_summary_file", type=argparse.FileType('r'), required = True, + help='Summary file to use to generate the pass percentage badge') +parser.add_argument('-o', "--output_badge_file", type=argparse.FileType('w'), required = True, + help='Name of the badge to output') +parser.add_argument('-s', "--badge_string", type=str, required = True, + help='Name of the badge to output') + + + +try: + results = parser.parse_args() +except Exception as e: + print(f"Error parsing arguments: {str(e)}") + exit(1) + +try: + summary_info = json.loads(results.input_summary_file.read()) +except Exception as e: + print(f"Error loading {results.input_summary_file.name} JSON file: {str(e)}") + sys.exit(1) + +if 'summary' not in summary_info: + print("Missing 'summary' key in {results.input_summary_file.name}") + sys.exit(1) +elif 'PASS_RATE' not in summary_info['summary'] or 'TESTS_PASSED' not in summary_info['summary']: + print(f"Missing PASS_RATE in 'summary' section of {results.input_summary_file.name}") + sys.exit(1) +pass_percent = 100 * summary_info['summary']['PASS_RATE'] + + +try: + results.output_badge_file.write(RAW_BADGE_SVG.format(results.badge_string, "{:2.1f}%".format(pass_percent))) +except Exception as e: + print(f"Error generating badge: {str(e)}") + sys.exit(1) + + +print("Badge {results.output_badge_file.name} successfully generated!") +sys.exit(0) +