docs #100
Workflow file for this run
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: Quality | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, labeled, unlabeled] | |
| push: | |
| branches: | |
| - main | |
| - release/* | |
| workflow_call: | |
| inputs: | |
| static_analysis_only: | |
| description: Skip the pytest matrix after static analysis. | |
| required: false | |
| type: boolean | |
| default: false | |
| coverage: | |
| description: Run the Python 3.12 tests under coverage and publish coverage results. | |
| required: false | |
| type: boolean | |
| default: false | |
| env: | |
| X2PY_GFORTRAN_BINARY: gfortran-13 | |
| X2PY_GFORTRAN_PACKAGE: gfortran-13 | |
| X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH: .pytest_cache/x2py/real-library-native | |
| jobs: | |
| static-analysis: | |
| name: Static Analysis | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install QA dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[qa]" | |
| - name: Verify static-analysis versions | |
| run: python tools/check_static_analysis_versions.py | |
| - name: Ruff lint | |
| run: python -m ruff check . | |
| - name: Ruff format | |
| run: python -m ruff format --check . | |
| - name: Bandit security scan | |
| run: python -m bandit -c pyproject.toml -r c_parser fortran_parser semantics x2py --severity-level medium --confidence-level medium | |
| - name: Vulture dead-code scan | |
| run: python -m vulture | |
| - name: Radon complexity policy | |
| env: | |
| PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| PUSH_BEFORE_SHA: ${{ github.event.before }} | |
| run: python tools/check_radon_policy.py --base-ref auto | |
| - name: Radon complexity report | |
| continue-on-error: true | |
| run: python -m radon cc c_parser fortran_parser semantics x2py -n C -s --total-average | |
| - name: Radon maintainability report | |
| continue-on-error: true | |
| run: python -m radon mi c_parser fortran_parser semantics x2py -s | |
| real-library-native-cache: | |
| name: Real-Library Native Cache | |
| if: ${{ !inputs.static_analysis_only }} | |
| needs: static-analysis | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install test dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[qa]" | |
| - name: Install pinned GFortran | |
| shell: bash | |
| run: | | |
| if ! command -v "$X2PY_GFORTRAN_BINARY" >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --yes "$X2PY_GFORTRAN_PACKAGE" | |
| fi | |
| compiler_dir="$RUNNER_TEMP/x2py-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$X2PY_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| "$compiler_dir/gfortran" --version | |
| - name: Capture native cache key facts | |
| id: native-cache-facts | |
| shell: bash | |
| run: | | |
| echo "gfortran_hash=$(gfortran --version | head -n 1 | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" | |
| - name: Restore real-library native cache | |
| id: restore-real-library-native-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: ${{ env.X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH }} | |
| key: real-library-native-${{ runner.os }}-${{ runner.arch }}-${{ steps.native-cache-facts.outputs.gfortran_hash }}-${{ hashFiles('tests/data/fortran/blas/**', 'tests/data/fortran/lapack/**', 'tests/wrapper/fortran/real_libraries/test_real_blas_lapack.py', 'tools/warm_real_library_native_cache.py') }} | |
| restore-keys: | | |
| real-library-native-${{ runner.os }}-${{ runner.arch }}-${{ steps.native-cache-facts.outputs.gfortran_hash }}- | |
| - name: Warm real-library native cache | |
| env: | |
| PYTHONPATH: . | |
| X2PY_REAL_LIBRARY_NATIVE_CACHE_DIR: ${{ github.workspace }}/${{ env.X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH }} | |
| run: python tools/warm_real_library_native_cache.py | |
| - name: Save real-library native cache | |
| if: steps.restore-real-library-native-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: ${{ env.X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH }} | |
| key: real-library-native-${{ runner.os }}-${{ runner.arch }}-${{ steps.native-cache-facts.outputs.gfortran_hash }}-${{ hashFiles('tests/data/fortran/blas/**', 'tests/data/fortran/lapack/**', 'tests/wrapper/fortran/real_libraries/test_real_blas_lapack.py', 'tools/warm_real_library_native_cache.py') }} | |
| test: | |
| name: Tests (Python ${{ matrix.python-version }}) | |
| if: ${{ !inputs.static_analysis_only }} | |
| needs: [static-analysis, real-library-native-cache] | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12"] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install test dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[qa]" | |
| - name: Install pinned GFortran | |
| shell: bash | |
| run: | | |
| if ! command -v "$X2PY_GFORTRAN_BINARY" >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --yes "$X2PY_GFORTRAN_PACKAGE" | |
| fi | |
| compiler_dir="$RUNNER_TEMP/x2py-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$X2PY_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| "$compiler_dir/gfortran" --version | |
| - name: Capture native cache key facts | |
| id: native-cache-facts | |
| shell: bash | |
| run: | | |
| echo "gfortran_hash=$(gfortran --version | head -n 1 | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" | |
| - name: Restore real-library native cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: ${{ env.X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH }} | |
| key: real-library-native-${{ runner.os }}-${{ runner.arch }}-${{ steps.native-cache-facts.outputs.gfortran_hash }}-${{ hashFiles('tests/data/fortran/blas/**', 'tests/data/fortran/lapack/**', 'tests/wrapper/fortran/real_libraries/test_real_blas_lapack.py', 'tools/warm_real_library_native_cache.py') }} | |
| restore-keys: | | |
| real-library-native-${{ runner.os }}-${{ runner.arch }}-${{ steps.native-cache-facts.outputs.gfortran_hash }}- | |
| - name: Run tests | |
| shell: bash | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| X2PY_COVERAGE_REQUESTED: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-coverage')) || (github.event_name == 'workflow_call' && inputs.coverage) }} | |
| X2PY_REAL_LIBRARY_NATIVE_CACHE_DIR: ${{ github.workspace }}/${{ env.X2PY_REAL_LIBRARY_NATIVE_CACHE_PATH }} | |
| run: | | |
| if [[ "${{ matrix.python-version }}" == "3.12" ]]; then | |
| test_paths=(tests) | |
| else | |
| test_paths=( | |
| tests/parser | |
| tests/property | |
| tests/semantics | |
| tests/pyi | |
| tests/tools | |
| tests/benchmarks | |
| tests/test_naming_policy.py | |
| tests/wrapper/fortran/arrays | |
| tests/wrapper/fortran/build_from_pyi | |
| tests/wrapper/fortran/build_from_source | |
| tests/wrapper/fortran/callbacks | |
| tests/wrapper/fortran/derived_types | |
| tests/wrapper/fortran/edit_pyi_contracts | |
| tests/wrapper/fortran/external_routines | |
| tests/wrapper/fortran/function_calls | |
| tests/wrapper/fortran/layout_rules | |
| tests/wrapper/fortran/module_state | |
| tests/wrapper/fortran/multiple_files | |
| tests/wrapper/fortran/naming | |
| tests/wrapper/fortran/runtime_behavior | |
| tests/wrapper/fortran/scalars | |
| tests/wrapper/fortran/strings | |
| "tests/wrapper/fortran/real_libraries/test_real_blas_lapack.py::test_full_library_wrapper_imports_every_root_procedure_from_cached_shared_library[blas]" | |
| tests/wrapper/fortran/real_libraries/test_stage7_native_bundles.py | |
| ) | |
| fi | |
| if [[ "${{ matrix.python-version }}" == "3.12" && "$X2PY_COVERAGE_REQUESTED" == "true" ]]; then | |
| COVERAGE_PROCESS_START="${{ github.workspace }}/pyproject.toml" \ | |
| python -m coverage run -m pytest -q --randomly-seed=1 "${test_paths[@]}" | |
| else | |
| python -m pytest -q --randomly-seed=1 "${test_paths[@]}" | |
| fi | |
| - name: Upload coverage data | |
| if: matrix.python-version == '3.12' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-coverage')) || (github.event_name == 'workflow_call' && inputs.coverage)) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-py312 | |
| path: .coverage.* | |
| include-hidden-files: true | |
| if-no-files-found: error | |
| coverage-report: | |
| name: Coverage Report | |
| if: ${{ !inputs.static_analysis_only && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-coverage')) || (github.event_name == 'workflow_call' && inputs.coverage)) }} | |
| needs: test | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install coverage dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[qa]" | |
| - name: Download coverage data | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: coverage-* | |
| path: coverage-artifacts | |
| merge-multiple: true | |
| - name: Combine coverage data | |
| run: python -m coverage combine coverage-artifacts | |
| - name: Report coverage | |
| run: python -m coverage report | |
| - name: Emit coverage XML | |
| run: python -m coverage xml -o coverage.xml | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v6 | |
| with: | |
| files: ./coverage.xml | |
| flags: py312 | |
| use_oidc: true | |
| fail_ci_if_error: true | |
| # Benchmark workflow is intentionally parked for later activation. | |
| # benchmark: | |
| # if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| # runs-on: ubuntu-latest | |
| # timeout-minutes: 15 | |
| # permissions: | |
| # contents: read | |
| # steps: | |
| # - name: Checkout repository | |
| # uses: actions/checkout@v4 | |
| # - name: Set up Python | |
| # uses: actions/setup-python@v5 | |
| # with: | |
| # python-version: "3.12" | |
| # - name: Install QA dependencies | |
| # run: | | |
| # python -m pip install --upgrade pip | |
| # python -m pip install -e ".[qa]" | |
| # - name: Run parser benchmarks | |
| # env: | |
| # PYTHONPATH: . | |
| # run: python -m pytest -q tests/benchmarks -m benchmark --benchmark-only --benchmark-json=benchmark.json | |
| # - name: Upload benchmark report | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # name: parser-benchmark-${{ github.run_id }} | |
| # path: benchmark.json | |
| # retention-days: 90 |