Skip to content

Commit 4a19a99

Browse files
authored
Merge pull request github#6115 from tamasvajk/feature/framework-coverage-comment-noise
Only post comment with framework coverage change if it changed or wasn't done before
2 parents c02c963 + 9d004ec commit 4a19a99

File tree

8 files changed

+254
-167
lines changed

8 files changed

+254
-167
lines changed

.github/workflows/csv-coverage-pr-artifacts.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,23 @@ jobs:
4949
gh release download --repo "github/codeql-cli-binaries" --pattern "codeql-linux64.zip"
5050
- name: Unzip CodeQL CLI
5151
run: unzip -d codeql-cli codeql-linux64.zip
52-
- name: Generate CSV files on merge and base of the PR
52+
- name: Generate CSV files on merge commit of the PR
5353
run: |
5454
echo "Running generator on merge"
5555
PATH="$PATH:codeql-cli/codeql" python merge/misc/scripts/library-coverage/generate-report.py ci merge merge
5656
mkdir out_merge
5757
cp framework-coverage-*.csv out_merge/
5858
cp framework-coverage-*.rst out_merge/
59-
59+
- name: Generate CSV files on base commit of the PR
60+
run: |
6061
echo "Running generator on base"
6162
PATH="$PATH:codeql-cli/codeql" python base/misc/scripts/library-coverage/generate-report.py ci base base
6263
mkdir out_base
6364
cp framework-coverage-*.csv out_base/
6465
cp framework-coverage-*.rst out_base/
66+
- name: Generate diff of coverage reports
67+
run: |
68+
python base/misc/scripts/library-coverage/compare-folders.py out_base out_merge comparison.md
6569
- name: Upload CSV package list
6670
uses: actions/upload-artifact@v2
6771
with:
@@ -76,6 +80,12 @@ jobs:
7680
path: |
7781
out_base/framework-coverage-*.csv
7882
out_base/framework-coverage-*.rst
83+
- name: Upload comparison results
84+
uses: actions/upload-artifact@v2
85+
with:
86+
name: comparison
87+
path: |
88+
comparison.md
7989
- name: Save PR number
8090
run: |
8191
mkdir -p pr

.github/workflows/csv-coverage-pr-comment.yml

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,9 @@ jobs:
2626
with:
2727
python-version: 3.8
2828

29-
# download artifacts from the PR job:
30-
31-
- name: Download artifact - MERGE
29+
- name: Check coverage difference file and comment
3230
env:
3331
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3432
RUN_ID: ${{ github.event.workflow_run.id }}
3533
run: |
36-
gh run download --name "csv-framework-coverage-merge" --dir "out_merge" "$RUN_ID"
37-
38-
- name: Download artifact - BASE
39-
env:
40-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41-
RUN_ID: ${{ github.event.workflow_run.id }}
42-
run: |
43-
gh run download --name "csv-framework-coverage-base" --dir "out_base" "$RUN_ID"
44-
45-
- name: Download artifact - PR
46-
env:
47-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48-
RUN_ID: ${{ github.event.workflow_run.id }}
49-
run: |
50-
gh run download --name "pr" --dir "pr" "$RUN_ID"
51-
52-
- name: Check coverage files
53-
env:
54-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55-
RUN_ID: ${{ github.event.workflow_run.id }}
56-
run: |
57-
PR=$(cat "pr/NR")
58-
python misc/scripts/library-coverage/compare-files-comment-pr.py \
59-
out_base out_merge comparison.md "$GITHUB_REPOSITORY" "$PR" "$RUN_ID"
60-
- name: Upload comparison results
61-
uses: actions/upload-artifact@v2
62-
with:
63-
name: comparison
64-
path: |
65-
comparison.md
34+
python misc/scripts/library-coverage/comment-pr.py "$GITHUB_REPOSITORY" "$RUN_ID"
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import sys
2+
import os
3+
import utils
4+
import shutil
5+
import json
6+
import filecmp
7+
8+
"""
9+
This script compares the generated CSV coverage files with the ones in the codebase.
10+
"""
11+
12+
artifacts_workflow_name = "Check framework coverage changes"
13+
comparison_artifact_name = "comparison"
14+
comparison_artifact_file_name = "comparison.md"
15+
16+
17+
comment_first_line = ":warning: The head of this PR and the base branch were compared for differences in the framework coverage reports. "
18+
19+
20+
def get_comment_text(output_file, repo, run_id):
21+
size = os.path.getsize(output_file)
22+
if size == 0:
23+
print("No difference in the coverage reports")
24+
return
25+
26+
comment = comment_first_line + \
27+
f"The generated reports are available in the [artifacts of this workflow run](https://github.com/{repo}/actions/runs/{run_id}). " + \
28+
"The differences will be picked up by the nightly job after the PR gets merged. "
29+
30+
if size < 2000:
31+
print("There's a small change in the CSV framework coverage reports")
32+
comment += "The following differences were found: \n\n"
33+
with open(output_file, 'r') as file:
34+
comment += file.read()
35+
else:
36+
print("There's a large change in the CSV framework coverage reports")
37+
comment += f"The differences can be found in the {comparison_artifact_name} artifact of this workflow run](https://github.com/{repo}/actions/runs/{run_id})."
38+
39+
return comment
40+
41+
42+
def comment_pr(repo, run_id):
43+
"""
44+
Generates coverage diff produced by the changes in the current PR. If the diff is not empty, then post it as a comment.
45+
If a workflow run produces the same diff as the directly preceeding one, then don't post a comment.
46+
"""
47+
48+
# Store diff for current run
49+
current_diff_folder = "current_diff"
50+
utils.download_artifact(repo, comparison_artifact_name,
51+
current_diff_folder, run_id)
52+
53+
utils.download_artifact(repo, "pr", "pr", run_id)
54+
55+
try:
56+
with open("pr/NR") as file:
57+
pr_number = int(file.read())
58+
finally:
59+
if os.path.isdir("pr"):
60+
shutil.rmtree("pr")
61+
62+
# Try storing diff for previous run:
63+
prev_run_id = 0
64+
try:
65+
prev_run_id = get_previous_run_id(repo, run_id, pr_number)
66+
prev_diff_folder = "prev_diff"
67+
utils.download_artifact(repo, comparison_artifact_name,
68+
prev_diff_folder, prev_run_id)
69+
70+
if filecmp.cmp(f"{current_diff_folder}/{comparison_artifact_file_name}", f"{prev_diff_folder}/{comparison_artifact_file_name}", shallow=False):
71+
print(
72+
f"Previous run {prev_run_id} resulted in the same diff, so not commenting again.")
73+
return
74+
else:
75+
print(f"Diff of previous run {prev_run_id} differs, commenting.")
76+
except Exception:
77+
# this is not mecessarily a failure, it can also mean that there was no previous run yet.
78+
print("Couldn't generate diff for previous run:", sys.exc_info()[1])
79+
80+
comment = get_comment_text(
81+
f"{current_diff_folder}/{comparison_artifact_file_name}", repo, run_id)
82+
83+
if comment == None:
84+
if prev_run_id == 0:
85+
print("Nothing to comment.")
86+
return
87+
print("Previous run found, and current run removes coverage change.")
88+
comment = comment_first_line + \
89+
"A recent commit removed the previously reported differences."
90+
post_comment(comment, repo, pr_number)
91+
92+
93+
def post_comment(comment, repo, pr_number):
94+
print(f"Posting comment to PR #{pr_number}")
95+
utils.subprocess_run(["gh", "pr", "comment", str(pr_number),
96+
"--repo", repo, "--body", comment])
97+
98+
99+
def get_previous_run_id(repo, run_id, pr_number):
100+
"""
101+
Gets the previous run id for a given workflow run, considering that the previous workflow run needs to come from the same PR.
102+
"""
103+
104+
# Get branch and repo from run:
105+
this_run = utils.subprocess_check_output(
106+
["gh", "api", "-X", "GET", f"repos/{repo}/actions/runs/{run_id}", "--jq", "{ head_branch: .head_branch, head_repository: .head_repository.full_name }"])
107+
108+
this_run = json.loads(this_run)
109+
pr_branch = this_run["head_branch"]
110+
pr_repo = this_run["head_repository"]
111+
112+
# Get all previous runs that match branch, repo and workflow name:
113+
ids = utils.subprocess_check_output(["gh", "api", "-X", "GET", f"repos/{repo}/actions/runs", "-f", "event=pull_request", "-f", "status=success", "-f", "name=\"" + artifacts_workflow_name + "\"", "--jq",
114+
f"[.workflow_runs.[] | select(.head_branch==\"{pr_branch}\" and .head_repository.full_name==\"{pr_repo}\") | {{ created_at: .created_at, run_id: .id}}] | sort_by(.created_at) | reverse | [.[].run_id]"])
115+
116+
ids = json.loads(ids)
117+
if ids[0] != int(run_id):
118+
raise Exception(
119+
f"Expected to find {run_id} in the list of matching runs.")
120+
121+
for previous_run_id in ids[1:]:
122+
utils.download_artifact(repo, "pr", "prev_run_pr", previous_run_id)
123+
124+
try:
125+
with open("prev_run_pr/NR") as file:
126+
prev_pr_number = int(file.read())
127+
print(f"PR number: {prev_pr_number}")
128+
finally:
129+
if os.path.isdir("prev_run_pr"):
130+
shutil.rmtree("prev_run_pr")
131+
132+
# the previous run needs to be coming from the same PR:
133+
if pr_number == prev_pr_number:
134+
return int(previous_run_id)
135+
136+
raise Exception("Couldn't find previous run.")
137+
138+
139+
repo = sys.argv[1]
140+
run_id = sys.argv[2]
141+
142+
comment_pr(repo, run_id)

misc/scripts/library-coverage/compare-files-comment-pr.py

Lines changed: 0 additions & 129 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
import compare
3+
4+
5+
folder1 = sys.argv[1]
6+
folder2 = sys.argv[2]
7+
diff_file = sys.argv[3]
8+
9+
compare.compare_folders(folder1, folder2, diff_file)

0 commit comments

Comments
 (0)