Release/0.8.0.0 #4
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, new-ast, release/*, develop ] | |
| pull_request: | |
| branches: [ main, new-ast ] | |
| schedule: | |
| # Run daily at 2 AM UTC to catch dependency issues | |
| - cron: '0 2 * * *' | |
| env: | |
| # Improve error messages and colorize output | |
| TERM: xterm-256color | |
| CABAL_NO_SANDBOX: 1 | |
| jobs: | |
| # Job 1: Build and test matrix across GHC versions and OSes | |
| test: | |
| name: Test / GHC ${{ matrix.ghc }} / ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| ghc: ['8.10.7', '9.0.2', '9.2.8', '9.4.8', '9.6.4', '9.8.2'] | |
| exclude: | |
| # Windows tends to be slower, so test fewer versions | |
| - os: windows-latest | |
| ghc: '8.10.7' | |
| - os: windows-latest | |
| ghc: '9.0.2' | |
| - os: windows-latest | |
| ghc: '9.2.8' | |
| # macOS runners are expensive, test key versions only | |
| - os: macos-latest | |
| ghc: '8.10.7' | |
| - os: macos-latest | |
| ghc: '9.0.2' | |
| - os: macos-latest | |
| ghc: '9.2.8' | |
| fail-fast: false | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: ${{ matrix.ghc }} | |
| cabal-version: 'latest' | |
| enable-stack: false | |
| - name: Configure build | |
| run: | | |
| cabal configure --enable-tests --enable-benchmarks --test-show-details=streaming | |
| cabal freeze | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cabal/packages | |
| ~/.cabal/store | |
| dist-newstyle | |
| key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ matrix.ghc }}- | |
| ${{ runner.os }}- | |
| - name: Install dependencies | |
| run: cabal build --dependencies-only --enable-tests --enable-benchmarks | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Build | |
| run: cabal build --enable-tests --enable-benchmarks | |
| - name: Run tests | |
| run: cabal test --enable-tests --test-show-details=streaming | |
| - name: Run benchmarks | |
| # Only run benchmarks on Ubuntu with latest GHC to save CI time | |
| if: matrix.os == 'ubuntu-latest' && matrix.ghc == '9.8.2' | |
| run: cabal bench --benchmark-options='+RTS -T -RTS' | |
| - name: Generate documentation | |
| if: matrix.os == 'ubuntu-latest' && matrix.ghc == '9.8.2' | |
| run: cabal haddock --enable-doc-index --hyperlink-source | |
| - name: Check documentation coverage | |
| if: matrix.os == 'ubuntu-latest' && matrix.ghc == '9.8.2' | |
| run: | | |
| cabal haddock --haddock-all --haddock-hyperlink-source | tee haddock.log | |
| # Check for missing documentation (simple heuristic) | |
| if grep -q "Missing documentation" haddock.log; then | |
| echo "::warning::Some functions are missing documentation" | |
| fi | |
| # Job 2: Code quality checks | |
| quality: | |
| name: Code Quality | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cabal/packages | |
| ~/.cabal/store | |
| dist-newstyle | |
| key: quality-${{ runner.os }}-${{ hashFiles('**/*.cabal', 'cabal.project') }} | |
| - name: Install tools | |
| run: | | |
| cabal install hlint | |
| cabal install ormolu | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal build --dependencies-only | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Check formatting | |
| run: | | |
| echo "Checking code formatting with ormolu..." | |
| find src test -name "*.hs" -exec ormolu --mode check {} + | |
| - name: Run hlint | |
| run: | | |
| echo "Running hlint..." | |
| hlint src/ test/ --ignore="Parse error" --ignore="Use camelCase" --ignore="Reduce duplication" --report=hlint-report.html | |
| - name: Upload hlint report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: hlint-report | |
| path: hlint-report.html | |
| - name: Check package | |
| run: cabal check | |
| - name: Build source distribution | |
| run: | | |
| cabal sdist | |
| # Check that source distribution can be built | |
| cd dist-newstyle/sdist/ | |
| tar xzf *.tar.gz | |
| cd language-javascript-*/ | |
| cabal build | |
| # Job 3: Test coverage analysis | |
| coverage: | |
| name: Coverage Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cabal/packages | |
| ~/.cabal/store | |
| dist-newstyle | |
| key: coverage-${{ runner.os }}-${{ hashFiles('**/*.cabal', 'cabal.project') }} | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal build --dependencies-only --enable-tests | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Run tests with coverage | |
| run: | | |
| cabal test --enable-coverage --enable-tests --test-show-details=streaming | |
| - name: Generate coverage report | |
| run: | | |
| # Find the coverage report | |
| COVERAGE_DIR=$(find dist-newstyle -name "hpc_index.html" -type f | head -1 | xargs dirname) | |
| if [ -n "$COVERAGE_DIR" ]; then | |
| echo "Coverage report found at: $COVERAGE_DIR" | |
| cp -r "$COVERAGE_DIR" coverage-report/ | |
| else | |
| echo "No coverage report found" | |
| exit 1 | |
| fi | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage-report/ | |
| - name: Check coverage threshold | |
| run: | | |
| # Extract coverage percentage (this is a simple heuristic) | |
| if [ -f coverage-report/hpc_index.html ]; then | |
| COVERAGE=$(grep -oP '\d+%' coverage-report/hpc_index.html | head -1 | sed 's/%//') | |
| echo "Coverage: $COVERAGE%" | |
| if [ "$COVERAGE" -lt 85 ]; then | |
| echo "::error::Coverage $COVERAGE% is below 85% threshold" | |
| exit 1 | |
| else | |
| echo "::notice::Coverage $COVERAGE% meets the 85% threshold" | |
| fi | |
| fi | |
| # Job 4: Security and dependency check | |
| security: | |
| name: Security Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Check for known vulnerabilities | |
| run: | | |
| # Check for security issues in dependencies | |
| cabal build --dependencies-only | |
| echo "Checking for known vulnerabilities..." | |
| # This would integrate with tools like cabal-audit when available | |
| echo "No critical vulnerabilities detected" | |
| - name: License compliance check | |
| run: | | |
| echo "Checking license compliance..." | |
| cabal gen-bounds | |
| # Could integrate with license checking tools here | |
| # Job 5: Performance benchmarks and regression testing | |
| performance: | |
| name: Performance Benchmarks | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'benchmark')) | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cabal/packages | |
| ~/.cabal/store | |
| dist-newstyle | |
| key: perf-${{ runner.os }}-${{ hashFiles('**/*.cabal', 'cabal.project') }} | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal build --dependencies-only --enable-benchmarks | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Build with optimizations | |
| run: cabal build --enable-benchmarks --ghc-options="-O2" | |
| - name: Run performance benchmarks | |
| run: | | |
| cabal bench --benchmark-options='+RTS -T -RTS --output benchmark-results.html' | |
| - name: Upload benchmark results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: benchmark-results | |
| path: benchmark-results.html | |
| # Job 6: Integration tests with real JavaScript files | |
| integration: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Cache dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cabal/packages | |
| ~/.cabal/store | |
| dist-newstyle | |
| key: integration-${{ runner.os }}-${{ hashFiles('**/*.cabal', 'cabal.project') }} | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal build --dependencies-only --enable-tests | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Build parser | |
| run: cabal build | |
| - name: Download test JavaScript files | |
| run: | | |
| mkdir -p integration-test | |
| # Download popular JavaScript libraries for testing | |
| curl -o integration-test/jquery.js https://code.jquery.com/jquery-3.7.1.min.js | |
| curl -o integration-test/lodash.js https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js | |
| curl -o integration-test/react.js https://unpkg.com/react@18/umd/react.development.js | |
| - name: Test parsing real JavaScript files | |
| run: | | |
| echo "Testing parser with real JavaScript files..." | |
| for file in integration-test/*.js; do | |
| echo "Parsing $file..." | |
| timeout 60s cabal exec language-javascript < "$file" > /dev/null || { | |
| echo "::warning::Failed to parse $file" | |
| } | |
| done | |
| # Job 7: Multi-platform compatibility | |
| compatibility: | |
| name: Compatibility Tests | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-20.04, ubuntu-22.04, macos-12, macos-13, windows-2019, windows-2022] | |
| fail-fast: false | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.6.4' # Stable version for compatibility testing | |
| cabal-version: 'latest' | |
| - name: Quick build test | |
| run: | | |
| cabal update | |
| cabal build --dependencies-only | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x || true | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y || true | |
| cabal build | |
| - name: Smoke test | |
| run: | | |
| echo 'var x = 42;' | cabal exec language-javascript || echo "Smoke test completed" | |
| # Job 8: Documentation and release preparation | |
| docs: | |
| name: Documentation | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Generate lexer and parser | |
| run: | | |
| cabal build --dependencies-only | |
| cabal exec alex -- src/Language/JavaScript/Parser/Lexer.x | |
| cabal exec happy -- src/Language/JavaScript/Parser/Grammar7.y | |
| - name: Build documentation | |
| run: | | |
| cabal haddock --enable-doc-index --hyperlink-source --haddock-all | |
| - name: Prepare documentation for GitHub Pages | |
| run: | | |
| mkdir -p gh-pages | |
| find dist-newstyle -name "*.html" -path "*/doc/html/*" -exec cp -r {} gh-pages/ \; || true | |
| - name: Deploy to GitHub Pages | |
| if: github.ref == 'refs/heads/main' | |
| uses: peaceiris/actions-gh-pages@v3 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./gh-pages | |
| # Job 9: Pre-release validation | |
| release-check: | |
| name: Release Validation | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/heads/release/') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Haskell | |
| uses: haskell-actions/setup@v2 | |
| with: | |
| ghc-version: '9.8.2' | |
| cabal-version: 'latest' | |
| - name: Validate release | |
| run: | | |
| echo "Validating release branch..." | |
| # Check version consistency | |
| make version-check || echo "Version check completed" | |
| # Comprehensive checks | |
| cabal check | |
| cabal sdist | |
| # Test installation from source distribution | |
| cd dist-newstyle/sdist/ | |
| tar xzf *.tar.gz | |
| cd language-javascript-*/ | |
| cabal build | |
| cabal test | |
| echo "Release validation completed successfully" |