-
-
Notifications
You must be signed in to change notification settings - Fork 888
Add code coverage disable check to GitHub workflows #2701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 38 commits
469a361
cea12f1
70fc259
6e68380
679fc49
01c430a
7d26173
b575036
cf69d03
3e89e1d
a460044
62d4232
0c3219a
1e7ea13
e841044
793b317
063f1de
e385ba6
dcce073
b0c79d7
1e1aa45
50df8a3
f974bbf
1dc3a93
7467034
9dfacc7
57fa9a3
17aebf5
5b83566
624feb9
ffe620d
9e5460c
8712ed0
2c26f59
5b4f689
3b22792
c2ce9ca
b88a4c1
20f095e
7976d2e
d5afe35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,160 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
"""Code Coverage Disable Checker Script. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Methodology: | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Recursively analyzes TypeScript files in the specified directories or | ||||||||||||||||||||||||||||||||||||||||||||||||||
checks specific files | ||||||||||||||||||||||||||||||||||||||||||||||||||
to ensure they do not contain code coverage disable statements. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
This script enforces proper code coverage practices in the project. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
NOTE: | ||||||||||||||||||||||||||||||||||||||||||||||||||
This script complies with our python3 coding and documentation standards. | ||||||||||||||||||||||||||||||||||||||||||||||||||
It complies with: | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
1) Pylint | ||||||||||||||||||||||||||||||||||||||||||||||||||
2) Pydocstyle | ||||||||||||||||||||||||||||||||||||||||||||||||||
3) Pycodestyle | ||||||||||||||||||||||||||||||||||||||||||||||||||
4) Flake8 | ||||||||||||||||||||||||||||||||||||||||||||||||||
5) Python Black | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||||||||||||||||||
import re | ||||||||||||||||||||||||||||||||||||||||||||||||||
import argparse | ||||||||||||||||||||||||||||||||||||||||||||||||||
import sys | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
def has_code_coverage_disable(file_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
Check if a TypeScript file contains code coverage disable statements. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||
file_path (str): Path to the TypeScript file. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||
bool: True if code coverage disable statement is found, False | ||||||||||||||||||||||||||||||||||||||||||||||||||
otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
code_coverage_disable_pattern = re.compile( | ||||||||||||||||||||||||||||||||||||||||||||||||||
r"""//?\s*istanbul\s+ignore(?:\s+(?:next|-line))?[^\n]*| | ||||||||||||||||||||||||||||||||||||||||||||||||||
/\*\s*istanbul\s+ignore\s+(?:next|-line)\s*\*/""", | ||||||||||||||||||||||||||||||||||||||||||||||||||
re.IGNORECASE, | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||||||||||||||||||
with open(file_path, "r", encoding="utf-8") as file: | ||||||||||||||||||||||||||||||||||||||||||||||||||
content = file.read() | ||||||||||||||||||||||||||||||||||||||||||||||||||
return bool(code_coverage_disable_pattern.search(content)) | ||||||||||||||||||||||||||||||||||||||||||||||||||
except FileNotFoundError: | ||||||||||||||||||||||||||||||||||||||||||||||||||
print(f"File not found: {file_path}") | ||||||||||||||||||||||||||||||||||||||||||||||||||
return False | ||||||||||||||||||||||||||||||||||||||||||||||||||
except PermissionError: | ||||||||||||||||||||||||||||||||||||||||||||||||||
print(f"Permission denied: {file_path}") | ||||||||||||||||||||||||||||||||||||||||||||||||||
return False | ||||||||||||||||||||||||||||||||||||||||||||||||||
except (IOError, OSError) as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||
print(f"Error reading file {file_path}: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||
return False | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
def check_code_coverage(files_or_dirs): | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
Check TypeScript files for code coverage disable statements. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||
files_or_dirs (list): List of files or directories to check. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||
bool: True if code coverage disable statement is found, False | ||||||||||||||||||||||||||||||||||||||||||||||||||
otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
code_coverage_found = False | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
for item in files_or_dirs: | ||||||||||||||||||||||||||||||||||||||||||||||||||
if os.path.isdir(item): | ||||||||||||||||||||||||||||||||||||||||||||||||||
# If it's a directory, recursively walk through the files in it | ||||||||||||||||||||||||||||||||||||||||||||||||||
for root, _, files in os.walk(item): | ||||||||||||||||||||||||||||||||||||||||||||||||||
if "node_modules" in root: | ||||||||||||||||||||||||||||||||||||||||||||||||||
continue | ||||||||||||||||||||||||||||||||||||||||||||||||||
for file_name in files: | ||||||||||||||||||||||||||||||||||||||||||||||||||
if file_name.endswith(".tsx") or file_name.endswith(".ts"): | ||||||||||||||||||||||||||||||||||||||||||||||||||
file_path = os.path.join(root, file_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||
if has_code_coverage_disable(file_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||
print( | ||||||||||||||||||||||||||||||||||||||||||||||||||
f"""File {file_path} contains code coverage | ||||||||||||||||||||||||||||||||||||||||||||||||||
disable statement.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
code_coverage_found = True | ||||||||||||||||||||||||||||||||||||||||||||||||||
elif os.path.isfile(item): | ||||||||||||||||||||||||||||||||||||||||||||||||||
# If it's a file, check it directly | ||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
item.endswith(".tsx") | ||||||||||||||||||||||||||||||||||||||||||||||||||
or item.endswith(".ts") | ||||||||||||||||||||||||||||||||||||||||||||||||||
and not file_name.endswith(".test.tsx") | ||||||||||||||||||||||||||||||||||||||||||||||||||
and not file_name.endswith(".test.ts") | ||||||||||||||||||||||||||||||||||||||||||||||||||
and not file_name.endswith(".spec.tsx") | ||||||||||||||||||||||||||||||||||||||||||||||||||
and not file_name.endswith(".spec.ts") | ||||||||||||||||||||||||||||||||||||||||||||||||||
): | ||||||||||||||||||||||||||||||||||||||||||||||||||
if has_code_coverage_disable(item): | ||||||||||||||||||||||||||||||||||||||||||||||||||
print(f"""File {item} contains code coverage disable | ||||||||||||||||||||||||||||||||||||||||||||||||||
statement.""") | ||||||||||||||||||||||||||||||||||||||||||||||||||
code_coverage_found = True | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix undefined variable in file extension check. The Apply this diff: elif os.path.isfile(item):
# If it's a file, check it directly
if (
item.endswith(".tsx")
or item.endswith(".ts")
- and not file_name.endswith(".test.tsx")
- and not file_name.endswith(".test.ts")
- and not file_name.endswith(".spec.tsx")
- and not file_name.endswith(".spec.ts")
+ and not item.endswith(".test.tsx")
+ and not item.endswith(".test.ts")
+ and not item.endswith(".spec.tsx")
+ and not item.endswith(".spec.ts")
): 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.8.2)90-98: Use a single Combine (SIM102) |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return code_coverage_found | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
def arg_parser_resolver(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
"""Resolve the CLI arguments provided by the user. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||
result: Parsed argument object | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
parser = argparse.ArgumentParser() | ||||||||||||||||||||||||||||||||||||||||||||||||||
parser.add_argument( | ||||||||||||||||||||||||||||||||||||||||||||||||||
"--directory", | ||||||||||||||||||||||||||||||||||||||||||||||||||
type=str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
nargs="+", | ||||||||||||||||||||||||||||||||||||||||||||||||||
default=[os.getcwd()], | ||||||||||||||||||||||||||||||||||||||||||||||||||
help="""One or more directories to check for code coverage disable | ||||||||||||||||||||||||||||||||||||||||||||||||||
statements (default: current directory).""", | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
parser.add_argument( | ||||||||||||||||||||||||||||||||||||||||||||||||||
"--files", | ||||||||||||||||||||||||||||||||||||||||||||||||||
type=str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
nargs="+", | ||||||||||||||||||||||||||||||||||||||||||||||||||
default=[], | ||||||||||||||||||||||||||||||||||||||||||||||||||
help="""One or more files to check directly for code coverage disable | ||||||||||||||||||||||||||||||||||||||||||||||||||
statements (default: check directories).""", | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return parser.parse_args() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
def main(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
Execute the script's main functionality. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
This function serves as the entry point for the script. It performs | ||||||||||||||||||||||||||||||||||||||||||||||||||
the following tasks: | ||||||||||||||||||||||||||||||||||||||||||||||||||
1. Validates and retrieves the files or directories to check from | ||||||||||||||||||||||||||||||||||||||||||||||||||
command line arguments. | ||||||||||||||||||||||||||||||||||||||||||||||||||
2. Checks files or directories for code coverage disable statements. | ||||||||||||||||||||||||||||||||||||||||||||||||||
3. Provides informative messages based on the analysis. | ||||||||||||||||||||||||||||||||||||||||||||||||||
4. Exits with an error if code coverage disable statements are found. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Raises: | ||||||||||||||||||||||||||||||||||||||||||||||||||
SystemExit: If an error occurs during execution. | ||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
args = arg_parser_resolver() | ||||||||||||||||||||||||||||||||||||||||||||||||||
files_or_dirs = args.files if args.files else args.directory | ||||||||||||||||||||||||||||||||||||||||||||||||||
# Check code coverage in the specified files or directories | ||||||||||||||||||||||||||||||||||||||||||||||||||
code_coverage_found = check_code_coverage(files_or_dirs) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if code_coverage_found: | ||||||||||||||||||||||||||||||||||||||||||||||||||
print("Code coverage disable check failed. Exiting with error.") | ||||||||||||||||||||||||||||||||||||||||||||||||||
sys.exit(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
print("Code coverage disable check completed successfully.") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||||||||||||||||||
main() |
Uh oh!
There was an error while loading. Please reload this page.