Skip to content

Commit 7bb67a5

Browse files
im-vedantim-vedantpalisadoes
authored
Add code coverage disable check to GitHub workflows (#2701)
* feat: add script to check for code coverage disable statements * Add code coverage disable check to GitHub workflows * Formatted code_coverage_disable_check.py to comply with all coding and documentation standards. * add functionality in eslint_disable_check.py to run for mutliple directories * removed unnecessary comment * excluded node_modules from eslint disable check * removed all eslint disable statements and code coverage disable statements * Revert "excluded node_modules from eslint disable check" This reverts commit b575036. * Revert "removed all eslint disable statements and code coverage disable statements" This reverts commit 62d4232. * excluded node_modules from eslint disable check * code-coverage check runs for only changed files * add tj-actions * add tj actions in check code coverage job * Fix GitHub Actions workflow to identify and pass nearest changed directories to Python script * syntax correction * minor fix * minor fix * minor fix * added repo root * fix error * fix error * added support for checking .ts files for eslint-disable statements * added support for checking .ts files for code coverage disable statements * minor change * Remove test files and ensured that python files follow coding standards * fixes bug * fix error * removed eslint disable command from check for linting errors in modified files step --------- Co-authored-by: im-vedant <[email protected]> Co-authored-by: Peter Harrison <[email protected]>
1 parent c9292d1 commit 7bb67a5

File tree

4 files changed

+260
-35
lines changed

4 files changed

+260
-35
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
"""Code Coverage Disable Checker Script.
2+
3+
Methodology:
4+
5+
Recursively analyzes TypeScript files in the specified directories or
6+
checks specific files
7+
to ensure they do not contain code coverage disable statements.
8+
9+
This script enforces proper code coverage practices in the project.
10+
11+
NOTE:
12+
This script complies with our python3 coding and documentation standards.
13+
It complies with:
14+
15+
1) Pylint
16+
2) Pydocstyle
17+
3) Pycodestyle
18+
4) Flake8
19+
5) Python Black
20+
21+
"""
22+
23+
import os
24+
import re
25+
import argparse
26+
import sys
27+
28+
29+
def has_code_coverage_disable(file_path):
30+
"""
31+
Check if a TypeScript file contains code coverage disable statements.
32+
33+
Args:
34+
file_path (str): Path to the TypeScript file.
35+
36+
Returns:
37+
bool: True if code coverage disable statement is found, False
38+
otherwise.
39+
"""
40+
code_coverage_disable_pattern = re.compile(
41+
r"""//?\s*istanbul\s+ignore(?:\s+(?:next|-line))?[^\n]*|
42+
/\*\s*istanbul\s+ignore\s+(?:next|-line)\s*\*/""",
43+
re.IGNORECASE,
44+
)
45+
try:
46+
with open(file_path, "r", encoding="utf-8") as file:
47+
content = file.read()
48+
return bool(code_coverage_disable_pattern.search(content))
49+
except FileNotFoundError:
50+
print(f"File not found: {file_path}")
51+
return False
52+
except PermissionError:
53+
print(f"Permission denied: {file_path}")
54+
return False
55+
except (IOError, OSError) as e:
56+
print(f"Error reading file {file_path}: {e}")
57+
return False
58+
59+
60+
def check_code_coverage(files_or_dirs):
61+
"""
62+
Check TypeScript files for code coverage disable statements.
63+
64+
Args:
65+
files_or_dirs (list): List of files or directories to check.
66+
67+
Returns:
68+
bool: True if code coverage disable statement is found, False
69+
otherwise.
70+
"""
71+
code_coverage_found = False
72+
73+
for item in files_or_dirs:
74+
if os.path.isdir(item):
75+
# If it's a directory, recursively walk through the files in it
76+
for root, _, files in os.walk(item):
77+
if "node_modules" in root:
78+
continue
79+
for file_name in files:
80+
if (
81+
file_name.endswith(".tsx")
82+
or file_name.endswith(".ts")
83+
and not file_name.endswith(".test.tsx")
84+
and not file_name.endswith(".test.ts")
85+
and not file_name.endswith(".spec.tsx")
86+
and not file_name.endswith(".spec.ts")
87+
):
88+
file_path = os.path.join(root, file_name)
89+
if has_code_coverage_disable(file_path):
90+
print(
91+
f"""File {file_path} contains code coverage
92+
disable statement."""
93+
)
94+
code_coverage_found = True
95+
elif os.path.isfile(item):
96+
# If it's a file, check it directly
97+
if (
98+
item.endswith(".tsx")
99+
or item.endswith(".ts")
100+
and not item.endswith(".test.tsx")
101+
and not item.endswith(".test.ts")
102+
and not item.endswith(".spec.tsx")
103+
and not item.endswith(".spec.ts")
104+
):
105+
if has_code_coverage_disable(item):
106+
print(
107+
f"""File {item} contains code coverage disable
108+
statement."""
109+
)
110+
code_coverage_found = True
111+
112+
return code_coverage_found
113+
114+
115+
def arg_parser_resolver():
116+
"""Resolve the CLI arguments provided by the user.
117+
118+
Returns:
119+
result: Parsed argument object
120+
"""
121+
parser = argparse.ArgumentParser()
122+
parser.add_argument(
123+
"--directory",
124+
type=str,
125+
nargs="+",
126+
default=[os.getcwd()],
127+
help="""One or more directories to check for code coverage disable
128+
statements (default: current directory).""",
129+
)
130+
parser.add_argument(
131+
"--files",
132+
type=str,
133+
nargs="+",
134+
default=[],
135+
help="""One or more files to check directly for code coverage disable
136+
statements (default: check directories).""",
137+
)
138+
return parser.parse_args()
139+
140+
141+
def main():
142+
"""
143+
Execute the script's main functionality.
144+
145+
This function serves as the entry point for the script. It performs
146+
the following tasks:
147+
1. Validates and retrieves the files or directories to check from
148+
command line arguments.
149+
2. Checks files or directories for code coverage disable statements.
150+
3. Provides informative messages based on the analysis.
151+
4. Exits with an error if code coverage disable statements are found.
152+
153+
Raises:
154+
SystemExit: If an error occurs during execution.
155+
"""
156+
args = arg_parser_resolver()
157+
files_or_dirs = args.files if args.files else args.directory
158+
# Check code coverage in the specified files or directories
159+
code_coverage_found = check_code_coverage(files_or_dirs)
160+
161+
if code_coverage_found:
162+
print("Code coverage disable check failed. Exiting with error.")
163+
sys.exit(1)
164+
165+
print("Code coverage disable check completed successfully.")
166+
167+
168+
if __name__ == "__main__":
169+
main()

.github/workflows/eslint_disable_check.py

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,29 @@
44
55
Methodology:
66
7-
Recursively analyzes TypeScript files in the 'src' directory and its subdirectories
8-
as well as 'setup.ts' files to ensure they do not contain eslint-disable statements.
7+
Recursively analyzes TypeScript files in the specified directory
8+
or checks specific files directly to ensure they do not contain
9+
eslint-disable statements.
910
1011
This script enforces code quality practices in the project.
1112
1213
NOTE:
13-
1414
This script complies with our python3 coding and documentation standards.
1515
It complies with:
1616
1717
1) Pylint
1818
2) Pydocstyle
1919
3) Pycodestyle
2020
4) Flake8
21+
5) Python Black
2122
2223
"""
23-
2424
import os
2525
import re
2626
import argparse
2727
import sys
2828

29+
2930
def has_eslint_disable(file_path):
3031
"""
3132
Check if a TypeScript file contains eslint-disable statements.
@@ -36,65 +37,98 @@ def has_eslint_disable(file_path):
3637
Returns:
3738
bool: True if eslint-disable statement is found, False otherwise.
3839
"""
39-
eslint_disable_pattern = re.compile(r'//\s*eslint-disable(?:-next-line|-line)?', re.IGNORECASE)
40-
40+
eslint_disable_pattern = re.compile(
41+
r"""\/\/\s*eslint-disable(?:-next-line
42+
|-line)?[^\n]*|\/\*\s*eslint-disable[^\*]*\*\/""",
43+
re.IGNORECASE,
44+
)
45+
4146
try:
42-
with open(file_path, 'r', encoding='utf-8') as file:
47+
with open(file_path, "r", encoding="utf-8") as file:
4348
content = file.read()
4449
return bool(eslint_disable_pattern.search(content))
45-
except Exception as e:
50+
except FileNotFoundError:
51+
print(f"File not found: {file_path}")
52+
return False
53+
except PermissionError:
54+
print(f"Permission denied: {file_path}")
55+
return False
56+
except (IOError, OSError) as e:
4657
print(f"Error reading file {file_path}: {e}")
4758
return False
4859

49-
def check_eslint(directory):
60+
61+
def check_eslint(files_or_directories):
5062
"""
51-
Recursively check TypeScript files for eslint-disable statements in the 'src' directory.
63+
Check TypeScript files for eslint-disable statements.
5264
5365
Args:
54-
directory (str): Path to the directory.
66+
files_or_directories (list): List of files or directories to check.
5567
5668
Returns:
5769
bool: True if eslint-disable statement is found, False otherwise.
5870
"""
5971
eslint_found = False
6072

61-
for root, dirs, files in os.walk(os.path.join(directory, 'src')):
62-
for file_name in files:
63-
if file_name.endswith('.tsx') and not file_name.endswith('.test.tsx'):
64-
file_path = os.path.join(root, file_name)
65-
if has_eslint_disable(file_path):
66-
print(f'File {file_path} contains eslint-disable statement.')
73+
for item in files_or_directories:
74+
if os.path.isfile(item):
75+
# If it's a file, directly check it
76+
if item.endswith(".ts") or item.endswith(".tsx"):
77+
if has_eslint_disable(item):
78+
print(f"File {item} contains eslint-disable statement.")
6779
eslint_found = True
68-
69-
setup_path = os.path.join(directory, 'setup.ts')
70-
if os.path.exists(setup_path) and has_eslint_disable(setup_path):
71-
print(f'Setup file {setup_path} contains eslint-disable statement.')
72-
eslint_found = True
80+
elif os.path.isdir(item):
81+
# If it's a directory, walk through it and check all
82+
# .ts and .tsx files
83+
for root, _, files in os.walk(item):
84+
if "node_modules" in root:
85+
continue
86+
for file_name in files:
87+
if file_name.endswith(".ts") or file_name.endswith(".tsx"):
88+
file_path = os.path.join(root, file_name)
89+
if has_eslint_disable(file_path):
90+
print(
91+
f"""File {file_path} contains eslint-disable
92+
statement."""
93+
)
94+
eslint_found = True
7395

7496
return eslint_found
7597

98+
7699
def arg_parser_resolver():
77100
"""Resolve the CLI arguments provided by the user.
78101
79102
Returns:
80103
result: Parsed argument object
81104
"""
82105
parser = argparse.ArgumentParser()
106+
parser.add_argument(
107+
"--files",
108+
type=str,
109+
nargs="+",
110+
default=[],
111+
help="""List of files to check for eslint disable
112+
statements (default: None).""",
113+
)
83114
parser.add_argument(
84115
"--directory",
85116
type=str,
86-
default=os.getcwd(),
87-
help="Path to the directory to check (default: current directory)"
117+
nargs="+",
118+
default=[os.getcwd()],
119+
help="""One or more directories to check for eslint disable
120+
statements (default: current directory).""",
88121
)
89122
return parser.parse_args()
90123

124+
91125
def main():
92126
"""
93127
Execute the script's main functionality.
94128
95129
This function serves as the entry point for the script. It performs
96130
the following tasks:
97-
1. Validates and retrieves the directory to check from
131+
1. Validates and retrieves the files and directories to check from
98132
command line arguments.
99133
2. Recursively checks TypeScript files for eslint-disable statements.
100134
3. Provides informative messages based on the analysis.
@@ -105,18 +139,17 @@ def main():
105139
"""
106140
args = arg_parser_resolver()
107141

108-
if not os.path.exists(args.directory):
109-
print(f"Error: The specified directory '{args.directory}' does not exist.")
110-
sys.exit(1)
111-
112-
# Check eslint in the specified directory
113-
eslint_found = check_eslint(args.directory)
142+
# Determine whether to check files or directories based on the arguments
143+
files_or_directories = args.files if args.files else args.directory
144+
# Check eslint in the specified files or directories
145+
eslint_found = check_eslint(files_or_directories)
114146

115147
if eslint_found:
116148
print("ESLint-disable check failed. Exiting with error.")
117149
sys.exit(1)
118150

119151
print("ESLint-disable check completed successfully.")
120152

153+
121154
if __name__ == "__main__":
122155
main()

0 commit comments

Comments
 (0)