feat: generate custom coverage config to omit legacy and external compoents (#9221)
* feat: generate custom coverage config to omit legacy and external components * lint * fix components config * also remove deactivated componenets * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
8d6505558b
commit
da4208dcc9
5 changed files with 232 additions and 2 deletions
36
scripts/generate_coverage_config.md
Normal file
36
scripts/generate_coverage_config.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Dynamic Coverage Configuration
|
||||
|
||||
This script generates a custom `.coveragerc` file for backend testing that excludes:
|
||||
|
||||
1. **Bundled components** - Components listed in `SIDEBAR_BUNDLES` from `src/frontend/src/utils/styleUtils.ts`
|
||||
2. **Legacy components** - Python files containing `legacy = True`
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Reads frontend config**: Parses `styleUtils.ts` to extract bundled component names
|
||||
2. **Scans backend files**: Finds all `.py` files in `src/backend/base/langflow/components/` with `legacy = True`
|
||||
3. **Generates .coveragerc**: Creates exclusion patterns for pytest-cov
|
||||
|
||||
## Usage
|
||||
|
||||
### Local development
|
||||
```bash
|
||||
# Generate config and run tests
|
||||
python3 scripts/generate_coverage_config.py
|
||||
cd src/backend && python -m pytest --cov=src/backend/base/langflow --cov-config=.coveragerc
|
||||
```
|
||||
|
||||
### CI Integration
|
||||
The script runs automatically in CI before backend tests via `.github/workflows/python_test.yml`.
|
||||
|
||||
## Files affected
|
||||
|
||||
- **Input**: `src/frontend/src/utils/styleUtils.ts` (SIDEBAR_BUNDLES)
|
||||
- **Input**: `src/backend/base/langflow/components/**/*.py` (legacy components)
|
||||
- **Output**: `src/backend/.coveragerc` (auto-generated, in .gitignore)
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Accurate coverage**: Focuses on actively maintained core code
|
||||
- **Dynamic updates**: Automatically adapts when bundles/legacy components change
|
||||
- **Codecov compatible**: Generated config works with both local testing and Codecov reporting
|
||||
168
scripts/generate_coverage_config.py
Executable file
168
scripts/generate_coverage_config.py
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Script to generate a custom .coveragerc file for backend testing.
|
||||
|
||||
This script:
|
||||
1. Reads SIDEBAR_BUNDLES from frontend styleUtils.ts to get bundled component names
|
||||
2. Scans backend components for files containing 'legacy = True'
|
||||
3. Generates a .coveragerc file that omits these paths from coverage reporting
|
||||
|
||||
Usage:
|
||||
python scripts/generate_coverage_config.py
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def extract_sidebar_bundles(frontend_path: Path) -> set[str]:
|
||||
"""Extract component names from SIDEBAR_BUNDLES in styleUtils.ts."""
|
||||
style_utils_path = frontend_path / "src/utils/styleUtils.ts"
|
||||
|
||||
if not style_utils_path.exists():
|
||||
print(f"Warning: styleUtils.ts not found at {style_utils_path}")
|
||||
return set()
|
||||
|
||||
bundle_names = set()
|
||||
|
||||
with style_utils_path.open(encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# Find SIDEBAR_BUNDLES array
|
||||
sidebar_match = re.search(r"export const SIDEBAR_BUNDLES = \[(.*?)\];", content, re.DOTALL)
|
||||
if not sidebar_match:
|
||||
print("Warning: SIDEBAR_BUNDLES not found in styleUtils.ts")
|
||||
return set()
|
||||
|
||||
bundles_content = sidebar_match.group(1)
|
||||
|
||||
# Extract name fields using regex
|
||||
name_matches = re.findall(r'name:\s*["\']([^"\']+)["\']', bundles_content)
|
||||
|
||||
for name in name_matches:
|
||||
bundle_names.add(name)
|
||||
|
||||
print(f"Found {len(bundle_names)} bundled components from SIDEBAR_BUNDLES")
|
||||
return bundle_names
|
||||
|
||||
|
||||
def find_legacy_components(backend_components_path: Path) -> set[str]:
|
||||
"""Find Python files containing 'legacy = True'."""
|
||||
legacy_files = set()
|
||||
|
||||
if not backend_components_path.exists():
|
||||
print(f"Warning: Backend components path not found: {backend_components_path}")
|
||||
return set()
|
||||
|
||||
# Walk through all Python files in components directory
|
||||
for py_file in backend_components_path.rglob("*.py"):
|
||||
try:
|
||||
with py_file.open(encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if file contains 'legacy = True'
|
||||
if re.search(r"\blegacy\s*=\s*True\b", content):
|
||||
# Get relative path from components directory
|
||||
rel_path = py_file.relative_to(backend_components_path)
|
||||
legacy_files.add(str(rel_path))
|
||||
|
||||
except (UnicodeDecodeError, PermissionError) as e:
|
||||
print(f"Warning: Could not read {py_file}: {e}")
|
||||
continue
|
||||
|
||||
print(f"Found {len(legacy_files)} legacy component files")
|
||||
return legacy_files
|
||||
|
||||
|
||||
def generate_coveragerc(bundle_names: set[str], legacy_files: set[str], output_path: Path):
|
||||
"""Generate .coveragerc file with omit patterns."""
|
||||
# Base coveragerc content
|
||||
config_content = """# Auto-generated .coveragerc file
|
||||
# Generated by scripts/generate_coverage_config.py
|
||||
# Do not edit manually - changes will be overwritten
|
||||
|
||||
[run]
|
||||
source = src/backend/base/langflow
|
||||
omit =
|
||||
# Test files
|
||||
*/tests/*
|
||||
*/test_*
|
||||
*/*test*
|
||||
|
||||
# Migration files
|
||||
*/alembic/*
|
||||
*/migrations/*
|
||||
|
||||
# Cache and build files
|
||||
*/__pycache__/*
|
||||
*/.*
|
||||
|
||||
# Init files (typically just imports)
|
||||
*/__init__.py
|
||||
|
||||
# Deactivate Components
|
||||
*/components/deactivated/*
|
||||
|
||||
"""
|
||||
|
||||
# Add bundled components to omit list
|
||||
if bundle_names:
|
||||
config_content += " # Bundled components from SIDEBAR_BUNDLES\n"
|
||||
for bundle_name in sorted(bundle_names):
|
||||
config_content += f" */components/{bundle_name}/*\n"
|
||||
config_content += "\n"
|
||||
|
||||
# Add legacy components to omit list
|
||||
if legacy_files:
|
||||
config_content += " # Legacy components (contain 'legacy = True')\n"
|
||||
for legacy_file in sorted(legacy_files):
|
||||
# Convert relative path to omit pattern
|
||||
omit_pattern = f" */components/{legacy_file}\n"
|
||||
config_content += omit_pattern
|
||||
|
||||
config_content += """
|
||||
# Note: [report] and [html] sections omitted for Codecov compatibility
|
||||
# Codecov handles its own reporting and ignores these sections
|
||||
"""
|
||||
|
||||
# Write the config file
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with output_path.open("w", encoding="utf-8") as f:
|
||||
f.write(config_content)
|
||||
|
||||
print(f"Generated .coveragerc at {output_path}")
|
||||
print(f" - Omitting {len(bundle_names)} bundled component directories")
|
||||
print(f" - Omitting {len(legacy_files)} legacy component files")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
# Determine project root (script is in scripts/ directory)
|
||||
script_dir = Path(__file__).parent
|
||||
project_root = script_dir.parent
|
||||
|
||||
# Paths
|
||||
frontend_path = project_root / "src" / "frontend"
|
||||
backend_components_path = project_root / "src" / "backend" / "base" / "langflow" / "components"
|
||||
output_path = project_root / "src" / "backend" / ".coveragerc"
|
||||
|
||||
print(f"Project root: {project_root}")
|
||||
print(f"Frontend path: {frontend_path}")
|
||||
print(f"Backend components path: {backend_components_path}")
|
||||
print(f"Output path: {output_path}")
|
||||
print()
|
||||
|
||||
# Extract bundled component names
|
||||
bundle_names = extract_sidebar_bundles(frontend_path)
|
||||
|
||||
# Find legacy components
|
||||
legacy_files = find_legacy_components(backend_components_path)
|
||||
|
||||
# Generate .coveragerc file
|
||||
generate_coveragerc(bundle_names, legacy_files, output_path)
|
||||
|
||||
print("\nDone! You can now run backend tests with coverage using:")
|
||||
print("cd src/backend && python -m pytest --cov=src/backend/base/langflow --cov-config=.coveragerc")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue