Validate Dependencies #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate Dependencies | |
| on: | |
| push: | |
| branches: [master, main] | |
| pull_request: | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.10' | |
| - name: Install Poetry and dependencies | |
| run: | | |
| pip install poetry toml | |
| # Option 1: Poetry lock file validation | |
| - name: Check pyproject.toml validity | |
| run: poetry check | |
| - name: Verify lock file is up to date | |
| run: poetry check --lock | |
| # Option 4: Multi-package validation | |
| - name: Validate all package metadata | |
| run: | | |
| for pkg_dir in packages/*/; do | |
| if [ -f "$pkg_dir/pyproject.toml" ]; then | |
| echo "Validating $(basename $pkg_dir)..." | |
| cd "$pkg_dir" | |
| poetry check || exit 1 | |
| cd ../.. | |
| fi | |
| done | |
| # Approach B: Name/path validation + Approach C: Orphaned references | |
| - name: Validate dependency consistency (name/path matching + orphaned refs) | |
| run: | | |
| python << 'EOF' | |
| import toml | |
| import os | |
| import re | |
| errors = [] | |
| print("=" * 60) | |
| print("STEP 1: Checking name/path consistency") | |
| print("=" * 60) | |
| # 1. Check name/path consistency | |
| root = toml.load('pyproject.toml') | |
| deps = root.get('tool', {}).get('poetry', {}).get('dependencies', {}) | |
| for pkg_name, config in deps.items(): | |
| if isinstance(config, dict) and 'path' in config: | |
| path = config['path'] | |
| print(f"Checking {pkg_name} -> {path}") | |
| if not os.path.exists(path): | |
| errors.append(f"Missing path: {pkg_name} -> {path}") | |
| continue | |
| pkg_toml = os.path.join(path, 'pyproject.toml') | |
| if os.path.exists(pkg_toml): | |
| pkg_config = toml.load(pkg_toml) | |
| # Try PEP 621 format first, fall back to Poetry | |
| actual_name = pkg_config.get('project', {}).get('name') | |
| if not actual_name: | |
| actual_name = pkg_config.get('tool', {}).get('poetry', {}).get('name') | |
| if actual_name and actual_name != pkg_name: | |
| errors.append( | |
| f"Name mismatch: dependency key '{pkg_name}' but " | |
| f"package defines name as '{actual_name}' at {path}" | |
| ) | |
| else: | |
| print(f" ✓ {pkg_name} matches package name") | |
| else: | |
| errors.append(f"Missing pyproject.toml in {path}") | |
| print("\n" + "=" * 60) | |
| print("STEP 2: Checking for orphaned references in lock file") | |
| print("=" * 60) | |
| # 2. Check for orphaned references in lock file | |
| actual_pkgs = set(os.listdir('packages')) | |
| print(f"Actual packages in packages/: {sorted(actual_pkgs)}") | |
| with open('poetry.lock') as f: | |
| lock_content = f.read() | |
| refs = set(re.findall(r'packages/([^/\s"]+)', lock_content)) | |
| print(f"Packages referenced in lock file: {sorted(refs)}") | |
| orphaned = refs - actual_pkgs | |
| if orphaned: | |
| errors.append(f"Orphaned lock file references: {', '.join(sorted(orphaned))}") | |
| else: | |
| print(" ✓ No orphaned references found") | |
| print("\n" + "=" * 60) | |
| print("VALIDATION RESULTS") | |
| print("=" * 60) | |
| if errors: | |
| print("ERRORS FOUND:") | |
| for e in errors: | |
| print(f" ✗ {e}") | |
| exit(1) | |
| else: | |
| print("✓ All dependency references are valid") | |
| EOF | |
| # Approach D: Lock file sync validation | |
| - name: Verify lock file is properly synced | |
| run: | | |
| echo "Backing up current lock file..." | |
| cp poetry.lock poetry.lock.original | |
| echo "Regenerating lock file..." | |
| poetry lock | |
| echo "Comparing files..." | |
| if ! diff -q poetry.lock.original poetry.lock; then | |
| echo "ERROR: poetry.lock is out of sync with pyproject.toml" | |
| echo "" | |
| echo "Differences found:" | |
| diff poetry.lock.original poetry.lock || true | |
| echo "" | |
| echo "Please run 'poetry lock' locally and commit the updated lock file." | |
| exit 1 | |
| fi | |
| echo "✓ Lock file is properly synced" | |
| # Option 3: Full dependency installation test | |
| - name: Test clean installation | |
| run: | | |
| echo "Removing existing virtual environment..." | |
| rm -rf .venv | |
| echo "Installing dependencies with --sync..." | |
| poetry install --sync | |
| echo "" | |
| echo "Installed packages:" | |
| poetry show | |
| echo "" | |
| echo "✓ All packages installed successfully" |