Skip to content

Commit 69e5e1e

Browse files
authored
Merge pull request #53 from CemrgDevelopers/development
Merge changes in the development branch
2 parents 73f9973 + 2b050da commit 69e5e1e

File tree

133 files changed

+225597
-4514
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+225597
-4514
lines changed

.github/code_analysis.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import argparse
2+
from github import Github
3+
import os
4+
5+
# Input variables from Github action
6+
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
7+
PR_NUM = int(os.getenv('PR_NUMBER'))
8+
WORK_DIR = os.getenv('GITHUB_WORKSPACE')
9+
REPO_NAME = os.getenv('GITHUB_REPOSITORY')
10+
SHA = os.getenv('GITHUB_SHA')
11+
COMMENT_TITLE = os.getenv('COMMENT_TITLE')
12+
ONLY_PR_CHANGES = os.getenv('REPORT_PR_CHANGES_ONLY')
13+
14+
# Max characters per comment - 65536
15+
# Make some room for HTML tags and error message
16+
MAX_CHAR_COUNT_REACHED = '!Maximum character count per GitHub comment has been reached! Not all warnings/errors has been parsed!'
17+
COMMENT_MAX_SIZE = 65000
18+
current_comment_length = 0
19+
20+
def is_part_of_pr_changes(file_path, issue_file_line, files_changed_in_pr):
21+
if ONLY_PR_CHANGES == "false":
22+
return True
23+
24+
file_name = file_path[file_path.rfind('/')+1:]
25+
print(f"Looking for issue found in file={file_name} ...")
26+
for file, (status, lines_changed_for_file) in files_changed_in_pr.items():
27+
print(f"Changed file by this PR {file} with status {status} and changed lines {lines_changed_for_file}")
28+
if file == file_name:
29+
if status == "added":
30+
return True
31+
32+
for (start, end) in lines_changed_for_file:
33+
if issue_file_line >= start and issue_file_line <= end:
34+
return True
35+
36+
return False
37+
38+
def get_lines_changed_from_patch(patch):
39+
lines_changed = []
40+
lines = patch.split('\n')
41+
42+
for line in lines:
43+
# Example line @@ -43,6 +48,8 @@
44+
# ------------ ^
45+
if line.startswith("@@"):
46+
# Example line @@ -43,6 +48,8 @@
47+
# ----------------------^
48+
idx_beg = line.index("+")
49+
50+
# Example line @@ -43,6 +48,8 @@
51+
# ^--^
52+
idx_end = line[idx_beg:].index(",")
53+
line_begin = int(line[idx_beg + 1 : idx_beg + idx_end])
54+
55+
idx_beg = idx_beg + idx_end
56+
idx_end = line[idx_beg + 1 : ].index("@@")
57+
58+
num_lines = int(line[idx_beg + 1 : idx_beg + idx_end])
59+
60+
lines_changed.append((line_begin, line_begin + num_lines))
61+
62+
return lines_changed
63+
64+
def setup_changed_files():
65+
files_changed = dict()
66+
67+
g = Github(GITHUB_TOKEN)
68+
repo = g.get_repo(REPO_NAME)
69+
pull_request = repo.get_pull(PR_NUM)
70+
num_changed_files = pull_request.changed_files
71+
print(f"Changed files {num_changed_files}")
72+
files = pull_request.get_files()
73+
for file in files:
74+
# additions # blob_url # changes # contents_url # deletions # filename
75+
# patch # previous_filename # raw_url # sha # status
76+
# print(f"File: additions={file.additions} blob_url={file.blob_url} changes={file.changes} contents_url={file.contents_url}"\
77+
# f"deletions={file.deletions} filename={file.filename} patch={file.patch} previous_filename={file.previous_filename}"\
78+
# f"raw_url={file.raw_url} sha={file.sha} status={file.status} ")
79+
80+
if file.patch is not None:
81+
lines_changed_for_file = get_lines_changed_from_patch(file.patch)
82+
files_changed[file.filename] = (file.status, lines_changed_for_file)
83+
84+
return files_changed
85+
86+
def check_for_char_limit(incoming_line):
87+
global current_comment_length
88+
return (current_comment_length + len(incoming_line)) <= COMMENT_MAX_SIZE
89+
90+
def get_file_line_end(file, file_line_start):
91+
num_lines = sum(1 for line in open(WORK_DIR + file))
92+
return min(file_line_start + 5, num_lines)
93+
94+
def create_comment_for_output(tool_output, prefix, files_changed_in_pr):
95+
issues_found = 0
96+
global current_comment_length
97+
output_string = ''
98+
for line in tool_output:
99+
if line.startswith(prefix):
100+
line = line.replace(prefix, "")
101+
file_path_end_idx = line.index(':')
102+
file_path = line[:file_path_end_idx]
103+
line = line[file_path_end_idx+1:]
104+
file_line_start = int(line[:line.index(':')])
105+
file_line_end = get_file_line_end(file_path, file_line_start)
106+
description = f"\n```diff\n!Line: {file_line_start} - {line[line.index(' ')+1:]}``` \n"
107+
108+
new_line = f'\n\nhttps://github.com/{REPO_NAME}/blob/{SHA}{file_path}#L{file_line_start}-L{file_line_end} {description} <br>\n'
109+
110+
if is_part_of_pr_changes(file_path, file_line_start, files_changed_in_pr):
111+
if check_for_char_limit(new_line):
112+
output_string += new_line
113+
current_comment_length += len(new_line)
114+
issues_found += 1
115+
else:
116+
current_comment_length = COMMENT_MAX_SIZE
117+
return output_string, issues_found
118+
119+
return output_string, issues_found
120+
121+
def read_files_and_parse_results(files_changed_in_pr):
122+
parser = argparse.ArgumentParser()
123+
parser.add_argument('-cc', '--cppcheck', help='Output file name for cppcheck', required=True)
124+
cppcheck_file_name = parser.parse_args().cppcheck
125+
126+
cppcheck_content = ''
127+
with open(cppcheck_file_name, 'r') as file:
128+
cppcheck_content = file.readlines()
129+
130+
line_prefix = f'{WORK_DIR}'
131+
132+
cppcheck_comment, cppcheck_issues_found = create_comment_for_output(cppcheck_content, line_prefix, files_changed_in_pr)
133+
134+
return cppcheck_comment, cppcheck_issues_found
135+
136+
def prepare_comment_body(cppcheck_comment, cppcheck_issues_found):
137+
138+
if cppcheck_issues_found == 0:
139+
full_comment_body = f'## <p align="center"><b> :white_check_mark: {COMMENT_TITLE} - no issues found! :white_check_mark: </b></p>'
140+
else:
141+
full_comment_body = f'## <p align="center"><b> :zap: {COMMENT_TITLE} :zap: </b></p> \n\n'
142+
143+
if len(cppcheck_comment) > 0:
144+
full_comment_body +=f'<details> <summary> <b> :red_circle: Cppcheck found'\
145+
f' {cppcheck_issues_found} {"issues" if cppcheck_issues_found > 1 else "issue"}! Click here to see details. </b> </summary> <br>'\
146+
f'{cppcheck_comment} </details><br>\n'
147+
148+
if current_comment_length == COMMENT_MAX_SIZE:
149+
full_comment_body += f'\n```diff\n{MAX_CHAR_COUNT_REACHED}\n```'
150+
151+
print(f'Repo={REPO_NAME} pr_num={PR_NUM} comment_title={COMMENT_TITLE}')
152+
153+
return full_comment_body
154+
155+
def create_or_edit_comment(comment_body):
156+
g = Github(GITHUB_TOKEN)
157+
repo = g.get_repo(REPO_NAME)
158+
pr = repo.get_pull(PR_NUM)
159+
160+
comments = pr.get_issue_comments()
161+
found_id = -1
162+
comment_to_edit = None
163+
for comment in comments:
164+
if (comment.user.login == 'github-actions[bot]') and (COMMENT_TITLE in comment.body):
165+
found_id = comment.id
166+
comment_to_edit = comment
167+
break
168+
169+
if found_id != -1:
170+
comment_to_edit.edit(body = comment_body)
171+
else:
172+
pr.create_issue_comment(body = comment_body)
173+
174+
175+
if __name__ == "__main__":
176+
files_changed_in_pr = setup_changed_files()
177+
cppcheck_comment, cppcheck_issues_found = read_files_and_parse_results(files_changed_in_pr)
178+
comment_body = prepare_comment_body(cppcheck_comment, cppcheck_issues_found)
179+
create_or_edit_comment(comment_body)

.github/codecov.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
coverage:
2+
ignore:
3+
- "CemrgApp/Modules/CemrgAppModule/test"

.github/workflows/analysis.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CemrgApp Code Analysis
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
Code-Analysis:
7+
runs-on: ubuntu-20.04
8+
steps:
9+
- name: Install missing packages
10+
run: |
11+
sudo apt update
12+
sudo apt install cppcheck -y
13+
pip3 install --upgrade setuptools
14+
pip3 install pygithub
15+
16+
- name: Install Qt
17+
run: |
18+
sudo pip3 install aqtinstall
19+
sudo aqt install --outputdir /Qt 5.12.10 linux desktop -m qtcharts qtnetworkauth qtpurchasing qtdatavis3d qtscript qtvirtualkeyboard qtwebengine qtwebglplugin
20+
21+
- name: Clone CemrgApp
22+
uses: actions/checkout@v2
23+
24+
- name: Code Analysis
25+
env:
26+
COMMENT_TITLE: Code Analysis Results
27+
PR_NUMBER: ${{ github.event.pull_request.number }}
28+
REPORT_PR_CHANGES_ONLY: false
29+
GITHUB_TOKEN: ${{ github.token }}
30+
run: |
31+
cppcheck --enable=warning,style,performance,portability --std=c++14 --language=c++ --force --quiet ${{ github.workspace }}/CemrgApp -I /Qt/5.12.10/gcc_64/include --output-file=analysis.txt
32+
python3 ${{ github.workspace }}/.github/code_analysis.py -cc analysis.txt

0 commit comments

Comments
 (0)