Skip to content
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

Add code coverage disable check to GitHub workflows #2701

Open
wants to merge 34 commits into
base: develop-postgres
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
469a361
feat: add script to check for code coverage disable statements
Dec 21, 2024
cea12f1
Add code coverage disable check to GitHub workflows
Dec 21, 2024
70fc259
Merge branch 'develop-postgres' of https://github.com/PalisadoesFound…
Dec 22, 2024
6e68380
Formatted code_coverage_disable_check.py to comply with all coding an…
Dec 22, 2024
679fc49
add functionality in eslint_disable_check.py to run for mutliple dire…
Dec 22, 2024
01c430a
removed unnecessary comment
Dec 22, 2024
7d26173
Merge branch 'develop-postgres' into workflow
im-vedant Dec 22, 2024
b575036
excluded node_modules from eslint disable check
Dec 22, 2024
cf69d03
Merge branch 'develop-postgres' into workflow
im-vedant Dec 23, 2024
3e89e1d
Merge branch 'develop-postgres' into workflow
im-vedant Dec 23, 2024
a460044
Merge branch 'develop-postgres' of https://github.com/PalisadoesFound…
Dec 24, 2024
62d4232
removed all eslint disable statements and code coverage disable state…
Dec 24, 2024
0c3219a
Merge branch 'workflow' of https://github.com/im-vedant/talawa-admin …
Dec 24, 2024
1e7ea13
Revert "excluded node_modules from eslint disable check"
Dec 24, 2024
e841044
Revert "removed all eslint disable statements and code coverage disab…
Dec 24, 2024
793b317
excluded node_modules from eslint disable check
Dec 24, 2024
063f1de
code-coverage check runs for only changed files
Dec 25, 2024
e385ba6
add tj-actions
Dec 25, 2024
dcce073
add tj actions in check code coverage job
Dec 25, 2024
b0c79d7
Merge branch 'develop-postgres' into workflow
palisadoes Dec 25, 2024
1e1aa45
Merge branch 'develop-postgres' into workflow
im-vedant Dec 25, 2024
50df8a3
Merge branch 'develop-postgres' of https://github.com/PalisadoesFound…
Dec 26, 2024
f974bbf
Fix GitHub Actions workflow to identify and pass nearest changed dire…
Dec 26, 2024
1dc3a93
Merge branch 'workflow' of https://github.com/im-vedant/talawa-admin …
Dec 26, 2024
7467034
syntax correction
Dec 26, 2024
9dfacc7
minor fix
Dec 26, 2024
57fa9a3
minor fix
Dec 26, 2024
17aebf5
minor fix
Dec 26, 2024
5b83566
added repo root
Dec 26, 2024
624feb9
fix error
Dec 26, 2024
ffe620d
fix error
Dec 26, 2024
9e5460c
added support for checking .ts files for eslint-disable statements
Dec 26, 2024
8712ed0
added support for checking .ts files for code coverage disable statem…
Dec 26, 2024
2c26f59
Merge branch 'develop-postgres' of https://github.com/PalisadoesFound…
Dec 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions .github/workflows/code_coverage_disable_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
"""Code Coverage Disable Checker Script.

Methodology:

Recursively analyzes TypeScript files in the specified directories 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
im-vedant marked this conversation as resolved.
Show resolved Hide resolved
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(?:-next-line|-line)?
|/\*\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(directories):
"""
Recursively check TypeScript files for code coverage disable statements.

Args:
directories (list) : List of directories.

Returns:
bool: True if code coverage disable statement is found, False
otherwise.
"""
code_coverage_found = False

for directory in directories:
if not os.path.exists(directory):
print(
f"""Error: The specified directory '{directory}' does
not exist."""
)
sys.exit(1)
for root, _, files in os.walk(directory):
for file_name in files:
if (
file_name.endswith(".tsx")
and not file_name.endswith(".test.tsx")
im-vedant marked this conversation as resolved.
Show resolved Hide resolved
):
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

setup_path = os.path.join(directory, "setup.ts")
if (
os.path.exists(setup_path)
and has_code_coverage_disable(setup_path)
):
print(
f"""Setup file {setup_path} contains code coverage disable
statement."""
)
code_coverage_found = True

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).""",
)
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 directory to check from
command line arguments.
2. Recursively checks TypeScript files 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()

print(args.directory)

# Check code coverage in the specified directory
code_coverage_found = check_code_coverage(args.directory)

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()
88 changes: 59 additions & 29 deletions .github/workflows/eslint_disable_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@

Methodology:

Recursively analyzes TypeScript files in the 'src' directory and its subdirectories
as well as 'setup.ts' files to ensure they do not contain eslint-disable statements.
Recursively analyzes TypeScript files in the specified directory
to ensure they do not contain eslint-disable statements.

This script enforces code quality 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

"""

Expand All @@ -26,6 +26,7 @@
import argparse
import sys


def has_eslint_disable(file_path):
"""
Check if a TypeScript file contains eslint-disable statements.
Expand All @@ -36,43 +37,73 @@ def has_eslint_disable(file_path):
Returns:
bool: True if eslint-disable statement is found, False otherwise.
"""
eslint_disable_pattern = re.compile(r'//\s*eslint-disable(?:-next-line|-line)?', re.IGNORECASE)

eslint_disable_pattern = re.compile(
r"""\/\/\s*eslint-disable(?:-next-line
|-line)?[^\n]*|\/\*\s*eslint-disable[^\*]*\*\/""",
re.IGNORECASE,
)
im-vedant marked this conversation as resolved.
Show resolved Hide resolved

try:
with open(file_path, 'r', encoding='utf-8') as file:
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
return bool(eslint_disable_pattern.search(content))
except Exception as e:
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_eslint(directory):

def check_eslint(directories):
"""
Recursively check TypeScript files for eslint-disable statements in the 'src' directory.
Recursively check TypeScript files for eslint-disable statements.

Args:
directory (str): Path to the directory.
directories (list): List of directories.

Returns:
bool: True if eslint-disable statement is found, False otherwise.
"""
eslint_found = False

for root, dirs, files in os.walk(os.path.join(directory, 'src')):
for file_name in files:
if file_name.endswith('.tsx') and not file_name.endswith('.test.tsx'):
file_path = os.path.join(root, file_name)
if has_eslint_disable(file_path):
print(f'File {file_path} contains eslint-disable statement.')
eslint_found = True

setup_path = os.path.join(directory, 'setup.ts')
if os.path.exists(setup_path) and has_eslint_disable(setup_path):
print(f'Setup file {setup_path} contains eslint-disable statement.')
eslint_found = True
for directory in directories:
if not os.path.exists(directory):
print(
f"""Error: The specified directory '{directory}' does not
exist."""
)
sys.exit(1)
for root, _, files in os.walk(directory):
if "node_modules" in root:
continue
for file_name in files:
if (
file_name.endswith(".tsx")
and not file_name.endswith(".test.tsx")
im-vedant marked this conversation as resolved.
Show resolved Hide resolved
):
file_path = os.path.join(root, file_name)
if has_eslint_disable(file_path):
print(
f"""File {file_path} contains eslint-disable
statement."""
)
eslint_found = True

setup_path = os.path.join(directory, "setup.ts")
if os.path.exists(setup_path) and has_eslint_disable(setup_path):
print(
f"""Setup file {setup_path} contains eslint-disable
statement."""
)
eslint_found = True

return eslint_found


def arg_parser_resolver():
"""Resolve the CLI arguments provided by the user.

Expand All @@ -83,11 +114,14 @@ def arg_parser_resolver():
parser.add_argument(
"--directory",
type=str,
default=os.getcwd(),
help="Path to the directory to check (default: current directory)"
nargs="+",
default=[os.getcwd()],
help="""One or more directories to check for eslint disable
statements (default: current directory).""",
)
return parser.parse_args()


def main():
"""
Execute the script's main functionality.
Expand All @@ -104,11 +138,6 @@ def main():
SystemExit: If an error occurs during execution.
"""
args = arg_parser_resolver()

if not os.path.exists(args.directory):
print(f"Error: The specified directory '{args.directory}' does not exist.")
sys.exit(1)

# Check eslint in the specified directory
eslint_found = check_eslint(args.directory)

Expand All @@ -118,5 +147,6 @@ def main():

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


if __name__ == "__main__":
main()
52 changes: 52 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,58 @@ jobs:
run: |
python .github/workflows/eslint_disable_check.py

Check-Code-Coverage-Disable:
name: Check for code coverage disable
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45

- name: Identify nearest changed directories
id: nearest_dirs
run: |
# Initialize an empty string to store the nearest directories
nearest_dirs=""

# Loop through each changed file to extract the nearest directory
for file in ${{ steps.changed-files.outputs.files }}
do
# Get the directory from the file path
folder=$(dirname "$file")

# Get the first level directory (top-level folder)
first_folder=$(echo $folder | cut -d'/' -f1)

# Add the folder to the nearest_dirs string if not already present
if [[ ! " $nearest_dirs " =~ " $first_folder " ]]; then
if [ -z "$nearest_dirs" ]; then
nearest_dirs="$first_folder"
else
nearest_dirs="$nearest_dirs,$first_folder"
fi
fi
done

# Output the nearest changed directories
echo "Nearest changed directories: $nearest_dirs"

# Set the nearest directories as a GitHub environment variable
echo "NEAREST_DIRS=$nearest_dirs" >> $GITHUB_ENV

im-vedant marked this conversation as resolved.
Show resolved Hide resolved
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.9

- name: Run Python script
run: |
# Access the nearest_dirs environment variable
python .github/workflows/code_coverage_disable_check.py --directory $NEAREST_DIRS

Test-Application:
im-vedant marked this conversation as resolved.
Show resolved Hide resolved
name: Test Application
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ const { setItem } = useLocalStorage();
*
* @returns The rendered routes and components of the application.
*/
// eslint-disable

// istanbul ignore next
function app(): JSX.Element {
/*const { updatePluginLinks, updateInstalled } = bindActionCreators(
actionCreators,
Expand Down
Loading