feat: Clean CFGPP implementation - production ready configuration parser #46
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: CI | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| jobs: | |
| test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| python-version: ['3.9', '3.10', '3.11'] | |
| exclude: | |
| # Reduce matrix size for faster CI | |
| - os: macos-latest | |
| python-version: '3.9' | |
| - os: windows-latest | |
| python-version: '3.9' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/requirements.txt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| cd implementations/python | |
| pip install -e . | |
| pip install pytest pytest-cov pytest-xdist | |
| - name: Run tests | |
| run: | | |
| cd implementations/python | |
| pytest --cov=src/cfgpp --cov-report=xml --cov-report=term-missing -v | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| file: ./implementations/python/coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.9 | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: 3.9 | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| cd implementations/python | |
| pip install -e .[dev] | |
| - name: Check code formatting with Black | |
| run: | | |
| cd implementations/python | |
| black --check --diff src/ tests/ | |
| - name: Lint with flake8 | |
| run: | | |
| cd implementations/python | |
| flake8 src/ tests/ --count --select=E9,F63,F7,F82 --show-source --statistics | |
| flake8 src/ tests/ --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics | |
| - name: Type check with mypy | |
| run: | | |
| cd implementations/python | |
| mypy src/ --ignore-missing-imports | |
| security: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.9 | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: 3.9 | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install bandit safety | |
| cd implementations/python | |
| pip install -e . | |
| - name: Run security checks with bandit | |
| run: | | |
| cd implementations/python | |
| bandit -r src/ -f json -o bandit-report.json || true | |
| bandit -r src/ | |
| - name: Check dependencies with safety | |
| run: | | |
| safety check | |
| docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.9 | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: 3.9 | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| cd implementations/python | |
| pip install -e . | |
| - name: Validate documentation links | |
| run: | | |
| # Check that all documentation files exist and are properly linked | |
| python -c " | |
| import os | |
| docs_dir = 'docs' | |
| required_docs = [ | |
| 'README.md', 'getting-started.md', 'language-specification.md', | |
| 'api-reference.md', 'error-handling.md', 'contributing.md' | |
| ] | |
| for doc in required_docs: | |
| path = os.path.join(docs_dir, doc) | |
| if not os.path.exists(path): | |
| print(f'Missing documentation: {path}') | |
| exit(1) | |
| print(f'✓ {doc}') | |
| print('All documentation files exist') | |
| " | |
| - name: Test example configurations | |
| run: | | |
| cd implementations/python | |
| python -c " | |
| from cfgpp import load | |
| import os | |
| # Test the example configuration file | |
| example_path = '../../specification/examples/complex_config.cfgpp' | |
| if os.path.exists(example_path): | |
| try: | |
| config = load(example_path) | |
| print('✓ Example configuration parses successfully') | |
| except Exception as e: | |
| print(f'✗ Example configuration failed to parse: {e}') | |
| exit(1) | |
| else: | |
| print('No example configuration found - skipping') | |
| " | |
| integration: | |
| runs-on: ubuntu-latest | |
| needs: [test, lint] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.9 | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: 3.9 | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| cd implementations/python | |
| pip install -e . | |
| - name: Run integration tests | |
| run: | | |
| python -c " | |
| # Integration test: Parse a complex configuration | |
| from cfgpp import parse_string, parse_file, loads, load | |
| from cfgpp.core.parser import ConfigParseError | |
| from cfgpp.core.lexer import LexerError | |
| import tempfile | |
| import os | |
| # Test 1: Basic parsing functionality | |
| config_text = ''' | |
| AppConfig { | |
| name = \"TestApp\" | |
| port = 8080 | |
| debug = true | |
| database = Database::PostgreSQL( | |
| string host = \"localhost\", | |
| int port = 5432 | |
| ) | |
| features = [\"auth\", \"logging\", \"metrics\"] | |
| } | |
| ''' | |
| try: | |
| # Test new clear API | |
| result = parse_string(config_text) | |
| assert 'body' in result | |
| assert 'AppConfig' in result['body'] | |
| print('✓ Complex configuration parsing (new API)') | |
| # Test backward compatibility | |
| result_legacy = loads(config_text) | |
| assert result == result_legacy | |
| print('✓ Backward compatibility verified') | |
| except Exception as e: | |
| print(f'✗ Complex configuration parsing failed: {e}') | |
| exit(1) | |
| # Test 2: File parsing | |
| with tempfile.NamedTemporaryFile(mode='w', suffix='.cfgpp', delete=False) as f: | |
| f.write(config_text) | |
| temp_file = f.name | |
| try: | |
| # Test new clear API | |
| result = parse_file(temp_file) | |
| assert 'body' in result | |
| print('✓ File parsing (new API)') | |
| # Test backward compatibility | |
| result_legacy = load(temp_file) | |
| assert result == result_legacy | |
| print('✓ File parsing backward compatibility') | |
| except Exception as e: | |
| print(f'✗ File parsing failed: {e}') | |
| exit(1) | |
| finally: | |
| os.unlink(temp_file) | |
| # Test 3: Error handling | |
| try: | |
| parse_string('Invalid { syntax') | |
| print('✗ Error handling test failed - should have raised exception') | |
| exit(1) | |
| except (ConfigParseError, LexerError): | |
| print('✓ Error handling') | |
| except Exception as e: | |
| print(f'✗ Unexpected error type: {e}') | |
| exit(1) | |
| print('All integration tests passed!') | |
| " | |
| build: | |
| runs-on: ubuntu-latest | |
| needs: [test, lint, security, docs, integration] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.9 | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: 3.9 | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install build twine | |
| cd implementations/python | |
| pip install -e . | |
| - name: Build package | |
| run: | | |
| cd implementations/python | |
| python -m build | |
| - name: Check package | |
| run: | | |
| cd implementations/python | |
| twine check dist/* | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: implementations/python/dist/ |