Skip to content

Commit

Permalink
Linter Test 1
Browse files Browse the repository at this point in the history
  • Loading branch information
onurulgen committed Feb 9, 2024
1 parent 173affa commit 8ceaf7a
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 1 deletion.
179 changes: 179 additions & 0 deletions .github/code_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import os
import argparse
from github import Github

# Input variables from Github action
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
PR_NUM = int(os.getenv('PR_NUMBER'))
WORK_DIR = os.getenv('GITHUB_WORKSPACE')
REPO_NAME = os.getenv('GITHUB_REPOSITORY')
SHA = os.getenv('GITHUB_SHA')
COMMENT_TITLE = os.getenv('COMMENT_TITLE')
ONLY_PR_CHANGES = os.getenv('REPORT_PR_CHANGES_ONLY')

# Max characters per comment - 65536
# Make some room for HTML tags and error message
MAX_CHAR_COUNT_REACHED = '!Maximum character count per GitHub comment has been reached! Not all warnings/errors has been parsed!'
COMMENT_MAX_SIZE = 65000
current_comment_length = 0

def is_part_of_pr_changes(file_path, issue_file_line, files_changed_in_pr):
if ONLY_PR_CHANGES == "false":
return True

file_name = file_path[file_path.rfind('/')+1:]
print(f"Looking for issue found in file={file_name} ...")
for file, (status, lines_changed_for_file) in files_changed_in_pr.items():
print(f"Changed file by this PR {file} with status {status} and changed lines {lines_changed_for_file}")
if file == file_name:
if status == "added":
return True

for (start, end) in lines_changed_for_file:
if issue_file_line >= start and issue_file_line <= end:
return True

return False

def get_lines_changed_from_patch(patch):
lines_changed = []
lines = patch.split('\n')

for line in lines:
# Example line @@ -43,6 +48,8 @@
# ------------ ^
if line.startswith("@@"):
# Example line @@ -43,6 +48,8 @@
# ----------------------^
idx_beg = line.index("+")

# Example line @@ -43,6 +48,8 @@
# ^--^
idx_end = line[idx_beg:].index(",")
line_begin = int(line[idx_beg + 1 : idx_beg + idx_end])

idx_beg = idx_beg + idx_end
idx_end = line[idx_beg + 1 : ].index("@@")

num_lines = int(line[idx_beg + 1 : idx_beg + idx_end])

lines_changed.append((line_begin, line_begin + num_lines))

return lines_changed

def setup_changed_files():
files_changed = dict()

g = Github(GITHUB_TOKEN)
repo = g.get_repo(REPO_NAME)
pull_request = repo.get_pull(PR_NUM)
num_changed_files = pull_request.changed_files
print(f"Changed files {num_changed_files}")
files = pull_request.get_files()
for file in files:
# additions # blob_url # changes # contents_url # deletions # filename
# patch # previous_filename # raw_url # sha # status
# print(f"File: additions={file.additions} blob_url={file.blob_url} changes={file.changes} contents_url={file.contents_url}"\
# f"deletions={file.deletions} filename={file.filename} patch={file.patch} previous_filename={file.previous_filename}"\
# f"raw_url={file.raw_url} sha={file.sha} status={file.status} ")

if file.patch is not None:
lines_changed_for_file = get_lines_changed_from_patch(file.patch)
files_changed[file.filename] = (file.status, lines_changed_for_file)

return files_changed

def check_for_char_limit(incoming_line):
global current_comment_length
return (current_comment_length + len(incoming_line)) <= COMMENT_MAX_SIZE

def get_file_line_end(file, file_line_start):
num_lines = sum(1 for line in open(WORK_DIR + file))
return min(file_line_start + 5, num_lines)

def create_comment_for_output(tool_output, prefix, files_changed_in_pr):
issues_found = 0
global current_comment_length
output_string = ''
for line in tool_output:
if line.startswith(prefix):
line = line.replace(prefix, "")
file_path_end_idx = line.index(':')
file_path = line[:file_path_end_idx]
line = line[file_path_end_idx+1:]
file_line_start = int(line[:line.index(':')])
file_line_end = get_file_line_end(file_path, file_line_start)
description = f"\n```diff\n!Line: {file_line_start} - {line[line.index(' ')+1:]}``` \n"

new_line = f'\n\nhttps://github.com/{REPO_NAME}/blob/{SHA}{file_path}#L{file_line_start}-L{file_line_end} {description} <br>\n'

if is_part_of_pr_changes(file_path, file_line_start, files_changed_in_pr):
if check_for_char_limit(new_line):
output_string += new_line
current_comment_length += len(new_line)
issues_found += 1
else:
current_comment_length = COMMENT_MAX_SIZE
return output_string, issues_found

return output_string, issues_found

def read_files_and_parse_results(files_changed_in_pr):
parser = argparse.ArgumentParser()
parser.add_argument('-cc', '--cppcheck', help='Output file name for cppcheck', required=True)
cppcheck_file_name = parser.parse_args().cppcheck

cppcheck_content = ''
with open(cppcheck_file_name, 'r') as file:
cppcheck_content = file.readlines()

line_prefix = f'{WORK_DIR}'

cppcheck_comment, cppcheck_issues_found = create_comment_for_output(cppcheck_content, line_prefix, files_changed_in_pr)

return cppcheck_comment, cppcheck_issues_found

def prepare_comment_body(cppcheck_comment, cppcheck_issues_found):

if cppcheck_issues_found == 0:
full_comment_body = f'## <p align="center"><b> :white_check_mark: {COMMENT_TITLE} - no issues found! :white_check_mark: </b></p>'
else:
full_comment_body = f'## <p align="center"><b> :zap: {COMMENT_TITLE} :zap: </b></p> \n\n'

if len(cppcheck_comment) > 0:
full_comment_body +=f'<details> <summary> <b> :red_circle: Cppcheck found'\
f' {cppcheck_issues_found} {"issues" if cppcheck_issues_found > 1 else "issue"}! Click here to see details. </b> </summary> <br>'\
f'{cppcheck_comment} </details><br>\n'

if current_comment_length == COMMENT_MAX_SIZE:
full_comment_body += f'\n```diff\n{MAX_CHAR_COUNT_REACHED}\n```'

print(f'Repo={REPO_NAME} pr_num={PR_NUM} comment_title={COMMENT_TITLE}')

return full_comment_body

def create_or_edit_comment(comment_body):
g = Github(GITHUB_TOKEN)
repo = g.get_repo(REPO_NAME)
pr = repo.get_pull(PR_NUM)

comments = pr.get_issue_comments()
found_id = -1
comment_to_edit = None
for comment in comments:
if (comment.user.login == 'github-actions[bot]') and (COMMENT_TITLE in comment.body):
found_id = comment.id
comment_to_edit = comment
break

if found_id != -1:
comment_to_edit.edit(body = comment_body)
else:
pr.create_issue_comment(body = comment_body)


if __name__ == "__main__":
files_changed_in_pr = setup_changed_files()
cppcheck_comment, cppcheck_issues_found = read_files_and_parse_results(files_changed_in_pr)
comment_body = prepare_comment_body(cppcheck_comment, cppcheck_issues_found)
create_or_edit_comment(comment_body)
47 changes: 47 additions & 0 deletions .github/workflows/analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Code Analysis
on: [pull_request]
jobs:
Code-Analysis:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
sudo apt update && sudo apt install cppcheck -y
pip3 install --upgrade setuptools
pip3 install pygithub
- name: Install CUDA Toolkit
uses: Jimver/[email protected]
with:
method: network
use-github-cache: false
use-local-cache: false

- name: Configure NiftyReg
run: |
mkdir build
cd build
cmake -DCMAKE_C_COMPILER=gcc \
-DCMAKE_CXX_COMPILER=g++ \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_ALL_DEP=ON \
-DCHECK_GPU=OFF \
-DUSE_CUDA=ON \
-DUSE_OPENCL=ON \
-DUSE_SSE=ON \
-DUSE_OPENMP=ON \
-DBUILD_TESTING=OFF \
-DWITH_COVERAGE=OFF \
..
- name: Code Analysis
env:
COMMENT_TITLE: Code Analysis Results
PR_NUMBER: ${{ github.event.pull_request.number }}
REPORT_PR_CHANGES_ONLY: false
GITHUB_TOKEN: ${{ github.token }}
run: |
cppcheck -j 4 --enable=warning,style,performance,portability --project=build/compile_commands.json --output-file=analysis.txt
python3 ${{ github.workspace }}/.github/code_analysis.py -cc analysis.txt
2 changes: 1 addition & 1 deletion niftyreg_build_version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
423
424

0 comments on commit 8ceaf7a

Please sign in to comment.