Blas\Lapack #15
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: Pull Request | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, labeled, unlabeled] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: pull-request-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| PRIK_GFORTRAN_BINARY: gfortran-13 | |
| PRIK_GFORTRAN_PACKAGE: gfortran-13 | |
| PRIK_IFX_VERSION: "2026.1.1" | |
| PRIK_FLANG_VERSION: "22.1.8" | |
| PRIK_FLANG_RUNTIME_VERSION: "22.1.7" | |
| jobs: | |
| static-analysis: | |
| name: Static analysis · Ubuntu 24.04 · Python 3.12 | |
| 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: Wrapper-plan generator contracts | |
| run: python tools/check_wrapper_codegen_complexity.py | |
| - name: Bandit security scan | |
| run: python -m bandit -c pyproject.toml -r prik --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 prik -n C -s --total-average | |
| - name: Radon maintainability report | |
| continue-on-error: true | |
| run: python -m radon mi prik -s | |
| parser-reference-guard: | |
| name: Parser reference guard · Ubuntu 24.04 | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Verify parser references were updated when needed | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }} | |
| run: | | |
| set -euo pipefail | |
| CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA") | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| echo "PR labels: ${PR_LABELS:-<none>}" | |
| FORCE_LABEL="require-parser-reference-update" | |
| IGNORE_LABEL="ignore-parser-reference-guard" | |
| if [[ ",${PR_LABELS}," == *",${FORCE_LABEL},"* && \ | |
| ",${PR_LABELS}," == *",${IGNORE_LABEL},"* ]]; then | |
| echo "Conflicting labels: ${FORCE_LABEL} and ${IGNORE_LABEL}. Remove one." | |
| exit 1 | |
| fi | |
| if [[ ",${PR_LABELS}," == *",${IGNORE_LABEL},"* ]]; then | |
| echo "${IGNORE_LABEL} label present; skipping guard." | |
| exit 0 | |
| fi | |
| C_DOC="docs/developer/c-parser-reference.md" | |
| FORTRAN_DOC="docs/developer/fortran-parser-reference.md" | |
| PYI_DOC="docs/user/reference/semantic-pyi-format.md" | |
| C_DOC_CHANGED=false | |
| FORTRAN_DOC_CHANGED=false | |
| PYI_DOC_CHANGED=false | |
| C_PARSER_CHANGED=false | |
| FORTRAN_PARSER_CHANGED=false | |
| PYI_PARSER_CHANGED=false | |
| SHARED_PARSER_CHANGED=false | |
| if grep -Fxq "$C_DOC" <<< "$CHANGED_FILES"; then | |
| C_DOC_CHANGED=true | |
| fi | |
| if grep -Fxq "$FORTRAN_DOC" <<< "$CHANGED_FILES"; then | |
| FORTRAN_DOC_CHANGED=true | |
| fi | |
| if grep -Fxq "$PYI_DOC" <<< "$CHANGED_FILES"; then | |
| PYI_DOC_CHANGED=true | |
| fi | |
| while IFS= read -r changed_file; do | |
| case "$changed_file" in | |
| prik/parsers/c/*|tests/c/parsing/*|tests/c/fixtures/*|tests/c/probes/test_c_types.py) | |
| C_PARSER_CHANGED=true | |
| ;; | |
| prik/parsers/fortran/*|tests/fortran/source_parsing/parsing/*|tests/fortran/data_types/probes/test_fortran_type_probes.py) | |
| FORTRAN_PARSER_CHANGED=true | |
| ;; | |
| prik/parsers/pyi/*|tests/fortran/semantic_pyi_format/*) | |
| PYI_PARSER_CHANGED=true | |
| ;; | |
| tests/fortran/command_line_interface/pipeline/*|\ | |
| tests/fortran/source_preprocessing/preprocessing/*|\ | |
| prik/parsers/__init__.py|\ | |
| prik/preprocessing.py) | |
| SHARED_PARSER_CHANGED=true | |
| ;; | |
| esac | |
| done <<< "$CHANGED_FILES" | |
| if [[ ",${PR_LABELS}," == *",${FORCE_LABEL},"* ]]; then | |
| if [ "$C_DOC_CHANGED" = true ] || [ "$FORTRAN_DOC_CHANGED" = true ] || [ "$PYI_DOC_CHANGED" = true ]; then | |
| echo "${FORCE_LABEL} label present and at least one parser reference changed." | |
| else | |
| echo "${FORCE_LABEL} label present, but no parser reference changed." | |
| echo "Update ${C_DOC}, ${FORTRAN_DOC}, or ${PYI_DOC}, or remove ${FORCE_LABEL}." | |
| exit 1 | |
| fi | |
| fi | |
| FAILED=false | |
| if [ "$C_PARSER_CHANGED" = true ] && [ "$C_DOC_CHANGED" != true ]; then | |
| echo "C parser-related files changed without updating ${C_DOC}." | |
| FAILED=true | |
| fi | |
| if [ "$FORTRAN_PARSER_CHANGED" = true ] && [ "$FORTRAN_DOC_CHANGED" != true ]; then | |
| echo "Fortran parser-related files changed without updating ${FORTRAN_DOC}." | |
| FAILED=true | |
| fi | |
| if [ "$PYI_PARSER_CHANGED" = true ] && [ "$PYI_DOC_CHANGED" != true ]; then | |
| echo "Semantic .pyi parser-related files changed without updating ${PYI_DOC}." | |
| FAILED=true | |
| fi | |
| if [ "$SHARED_PARSER_CHANGED" = true ] && \ | |
| [ "$C_DOC_CHANGED" != true ] && \ | |
| [ "$FORTRAN_DOC_CHANGED" != true ] && \ | |
| [ "$PYI_DOC_CHANGED" != true ]; then | |
| echo "Shared parser workflow files changed without updating a parser reference." | |
| echo "Update ${C_DOC}, ${FORTRAN_DOC}, or ${PYI_DOC}, whichever behavior changed." | |
| FAILED=true | |
| fi | |
| if [ "$FAILED" = true ]; then | |
| echo "Use ${IGNORE_LABEL} only when the parser reference is already accurate." | |
| exit 1 | |
| fi | |
| if [ "$C_DOC_CHANGED" = true ]; then | |
| echo "${C_DOC} changed." | |
| fi | |
| if [ "$FORTRAN_DOC_CHANGED" = true ]; then | |
| echo "${FORTRAN_DOC} changed." | |
| fi | |
| if [ "$PYI_DOC_CHANGED" = true ]; then | |
| echo "${PYI_DOC} changed." | |
| fi | |
| echo "Parser reference guard passed." | |
| compiler-smoke: | |
| name: Compiler smoke · ${{ matrix.display_name }} | |
| needs: [static-analysis, parser-reference-guard] | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - toolchain: ifx | |
| display_name: Ubuntu 24.04 · Intel IFX 2026.1.1 · Python 3.12 | |
| environment: prik-ifx-2026.1.1 | |
| fortran_compiler: ifx | |
| c_compiler: icx | |
| cache_version: "2026.1.1-v2" | |
| - toolchain: flang | |
| display_name: Ubuntu 24.04 · LLVM Flang 22.1.8 · Python 3.12 | |
| environment: prik-flang-22.1.8 | |
| fortran_compiler: flang | |
| c_compiler: clang | |
| cache_version: "22.1.8-runtime-22.1.7-v1" | |
| 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: Cache compiler environment | |
| id: compiler-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ runner.temp }}/${{ matrix.environment }} | |
| key: fortran-toolchain-${{ runner.os }}-${{ matrix.toolchain }}-${{ matrix.cache_version }} | |
| - name: Install Intel IFX and ICX | |
| if: matrix.toolchain == 'ifx' && steps.compiler-cache.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| conda create --yes --solver=libmamba \ | |
| --prefix "$RUNNER_TEMP/${{ matrix.environment }}" \ | |
| --override-channels \ | |
| --channel https://software.repos.intel.com/python/conda/ \ | |
| --channel conda-forge \ | |
| "ifx_linux-64=$PRIK_IFX_VERSION" \ | |
| "dpcpp_linux-64=$PRIK_IFX_VERSION" | |
| - name: Install LLVM Flang and Clang | |
| if: matrix.toolchain == 'flang' && steps.compiler-cache.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| conda create --yes --solver=libmamba \ | |
| --prefix "$RUNNER_TEMP/${{ matrix.environment }}" \ | |
| --override-channels \ | |
| --channel conda-forge \ | |
| "flang=$PRIK_FLANG_VERSION" \ | |
| "clang=$PRIK_FLANG_VERSION" \ | |
| "libflang-rt=$PRIK_FLANG_RUNTIME_VERSION" | |
| - name: Export coherent compiler profile | |
| shell: bash | |
| run: | | |
| toolchain_prefix="$RUNNER_TEMP/${{ matrix.environment }}" | |
| echo "$toolchain_prefix/bin" >> "$GITHUB_PATH" | |
| echo "LD_LIBRARY_PATH=$toolchain_prefix/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" >> "$GITHUB_ENV" | |
| - name: Verify compiler pair | |
| shell: bash | |
| run: | | |
| "${RUNNER_TEMP}/${{ matrix.environment }}/bin/${{ matrix.fortran_compiler }}" --version | |
| "${RUNNER_TEMP}/${{ matrix.environment }}/bin/${{ matrix.c_compiler }}" --version | |
| - name: Show repository-owned lane plan | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler "$RUNNER_TEMP/${{ matrix.environment }}/bin/${{ matrix.fortran_compiler }}" \ | |
| --junit-dir "$RUNNER_TEMP" \ | |
| --plan | |
| - name: Run profile checks and strict smoke | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler "$RUNNER_TEMP/${{ matrix.environment }}/bin/${{ matrix.fortran_compiler }}" \ | |
| --junit-dir "$RUNNER_TEMP" | |
| - name: Summarize failed pytest nodes | |
| if: failure() | |
| shell: bash | |
| run: | | |
| shopt -s nullglob | |
| reports=("$RUNNER_TEMP"/pytest-toolchain-*-results.xml) | |
| for report in "${reports[@]}"; do | |
| python tools/print_pytest_failures.py "$report" | |
| done | |
| compiler-smoke-macos: | |
| name: Compiler smoke · macOS 15 ARM64 · LLVM Flang · Python 3.12 | |
| needs: [static-analysis, parser-reference-guard] | |
| runs-on: macos-15 | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| env: | |
| HOMEBREW_NO_AUTO_UPDATE: "1" | |
| PRIK_MACOS_FLANG_ENVIRONMENT: prik-flang-macos | |
| 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 LLVM Flang and Clang | |
| shell: bash | |
| run: | | |
| brew install flang | |
| toolchain_prefix="$RUNNER_TEMP/$PRIK_MACOS_FLANG_ENVIRONMENT" | |
| flang_prefix="$(brew --prefix flang)" | |
| llvm_prefix="$(brew --prefix llvm)" | |
| flang_c_include="$flang_prefix/include/flang" | |
| test -f "$flang_c_include/ISO_Fortran_binding.h" | |
| mkdir -p "$toolchain_prefix/bin" | |
| ln -sf "$flang_prefix/bin/flang" "$toolchain_prefix/bin/flang" | |
| ln -sf "$llvm_prefix/bin/clang" "$toolchain_prefix/bin/clang" | |
| echo "$toolchain_prefix/bin" >> "$GITHUB_PATH" | |
| echo "C_INCLUDE_PATH=$flang_c_include${C_INCLUDE_PATH:+:$C_INCLUDE_PATH}" >> "$GITHUB_ENV" | |
| echo "DYLD_LIBRARY_PATH=$flang_prefix/lib:$llvm_prefix/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}" \ | |
| >> "$GITHUB_ENV" | |
| - name: Verify macOS compiler pair | |
| shell: bash | |
| run: | | |
| echo "runner image: ${ImageOS:-unknown} ${ImageVersion:-unknown}" | |
| sw_vers | |
| uname -m | |
| python --version | |
| command -v flang | |
| flang --version | |
| command -v clang | |
| clang --version | |
| printf '#include <ISO_Fortran_binding.h>\n' | | |
| clang -std=c99 -fsyntax-only -x c - | |
| - name: Show repository-owned lane plan | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler flang \ | |
| --junit-dir "$RUNNER_TEMP" \ | |
| --plan | |
| - name: Run profile checks and strict smoke | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler flang \ | |
| --junit-dir "$RUNNER_TEMP" | |
| - name: Summarize failed pytest nodes | |
| if: failure() | |
| shell: bash | |
| run: | | |
| shopt -s nullglob | |
| reports=("$RUNNER_TEMP"/pytest-toolchain-*-results.xml) | |
| for report in "${reports[@]}"; do | |
| python tools/print_pytest_failures.py "$report" | |
| done | |
| unit-tests: | |
| name: ${{ matrix.display_name }} | |
| needs: [compiler-smoke, compiler-smoke-macos] | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - python-version: "3.10" | |
| display_name: Unit tests · Ubuntu 24.04 · Python 3.10 | |
| coverage: false | |
| - python-version: "3.11" | |
| display_name: Unit tests · Ubuntu 24.04 · Python 3.11 | |
| coverage: false | |
| - python-version: "3.12" | |
| display_name: Unit tests + project coverage · Ubuntu 24.04 · Python 3.12 | |
| coverage: true | |
| 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 "$PRIK_GFORTRAN_BINARY" >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --yes "$PRIK_GFORTRAN_PACKAGE" | |
| fi | |
| compiler_dir="$RUNNER_TEMP/prik-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$PRIK_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| "$compiler_dir/gfortran" --version | |
| - name: Run tests | |
| if: ${{ !matrix.coverage }} | |
| shell: bash | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| run: | | |
| python -m pytest -q --randomly-seed=1 \ | |
| -o junit_family=legacy \ | |
| --junitxml="$RUNNER_TEMP/pytest-smoke-results.xml" \ | |
| tests/fortran \ | |
| -m toolchain_smoke \ | |
| --require-toolchain-smoke \ | |
| --prik-fortran-compiler=gfortran | |
| python -m pytest -q --randomly-seed=1 \ | |
| -o junit_family=legacy \ | |
| --junitxml="$RUNNER_TEMP/pytest-suite-results.xml" \ | |
| -m "not real_library and not toolchain_smoke" \ | |
| tests/architecture \ | |
| tests/c \ | |
| tests/fortran \ | |
| tests/shared | |
| - name: Run tests with project coverage | |
| if: ${{ matrix.coverage }} | |
| shell: bash | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml | |
| run: | | |
| python -m coverage run -m pytest -q --randomly-seed=1 \ | |
| -o junit_family=legacy \ | |
| --junitxml="$RUNNER_TEMP/pytest-smoke-results.xml" \ | |
| tests/fortran \ | |
| -m toolchain_smoke \ | |
| --require-toolchain-smoke \ | |
| --prik-fortran-compiler=gfortran | |
| python -m coverage run -m pytest -q --randomly-seed=1 \ | |
| -o junit_family=legacy \ | |
| --junitxml="$RUNNER_TEMP/pytest-suite-results.xml" \ | |
| -m "not real_library and not toolchain_smoke" \ | |
| tests/architecture \ | |
| tests/c \ | |
| tests/fortran \ | |
| tests/shared | |
| - name: Summarize failed pytest nodes | |
| if: failure() | |
| shell: bash | |
| run: | | |
| shopt -s nullglob | |
| reports=("$RUNNER_TEMP"/pytest-*-results.xml) | |
| for report in "${reports[@]}"; do | |
| python tools/print_pytest_failures.py "$report" | |
| done | |
| - name: Combine coverage data | |
| if: ${{ matrix.coverage }} | |
| run: python -m coverage combine | |
| - name: Report coverage | |
| if: ${{ matrix.coverage }} | |
| run: python -m coverage report | |
| - name: Emit coverage XML | |
| if: ${{ matrix.coverage }} | |
| run: python -m coverage xml -o coverage.xml | |
| - name: Upload coverage to Codecov | |
| if: ${{ matrix.coverage }} | |
| uses: codecov/codecov-action@v6 | |
| with: | |
| files: ./coverage.xml | |
| flags: py312 | |
| use_oidc: true | |
| fail_ci_if_error: true | |
| unit-tests-macos: | |
| name: Unit tests · macOS 15 ARM64 · Python 3.12 | |
| needs: [compiler-smoke, compiler-smoke-macos] | |
| runs-on: macos-15 | |
| timeout-minutes: 120 | |
| permissions: | |
| contents: read | |
| env: | |
| PRIK_GFORTRAN_BINARY: gfortran-13 | |
| PRIK_GCC_BINARY: gcc-13 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python 3.12 | |
| 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: Configure GNU Fortran and GCC 13 | |
| shell: bash | |
| run: | | |
| if ! command -v "$PRIK_GFORTRAN_BINARY" >/dev/null 2>&1 || \ | |
| ! command -v "$PRIK_GCC_BINARY" >/dev/null 2>&1; then | |
| brew install gcc@13 | |
| fi | |
| compiler_dir="$RUNNER_TEMP/prik-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$PRIK_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| ln -sf "$(command -v "$PRIK_GCC_BINARY")" "$compiler_dir/gcc" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| - name: Show macOS test environment | |
| shell: bash | |
| run: | | |
| echo "runner image: ${ImageOS:-unknown} ${ImageVersion:-unknown}" | |
| sw_vers | |
| uname -m | |
| python --version | |
| command -v gfortran | |
| gfortran --version | |
| command -v gcc | |
| gcc --version | |
| - name: Show repository-owned lane plan | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler gfortran \ | |
| --junit-dir "$RUNNER_TEMP" \ | |
| --plan | |
| - name: Run compiler checks and strict smoke | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| run: | | |
| python tools/run_fortran_toolchain_lane.py \ | |
| --compiler gfortran \ | |
| --junit-dir "$RUNNER_TEMP" | |
| - name: Run full suite without BLAS or LAPACK | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| run: | | |
| python -m pytest -q --randomly-seed=1 \ | |
| -o junit_family=legacy \ | |
| --junitxml="$RUNNER_TEMP/pytest-macos-suite-results.xml" \ | |
| -m "not real_library and not toolchain_smoke" \ | |
| tests/architecture \ | |
| tests/c \ | |
| tests/fortran \ | |
| tests/shared | |
| - name: Summarize failed pytest nodes | |
| if: failure() | |
| shell: bash | |
| run: | | |
| shopt -s nullglob | |
| reports=("$RUNNER_TEMP"/pytest-*-results.xml) | |
| for report in "${reports[@]}"; do | |
| python tools/print_pytest_failures.py "$report" | |
| done | |
| native-libraries: | |
| name: BLAS + LAPACK · Ubuntu 24.04 · Python 3.12 | |
| needs: [unit-tests, unit-tests-macos] | |
| if: >- | |
| ${{ !contains(github.event.pull_request.labels.*.name, 'ignore-real-library-wrappers') }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 120 | |
| 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]" | |
| python -m pip install \ | |
| "numpy==2.5.1" \ | |
| "meson==1.11.2" \ | |
| "ninja==1.13.0" \ | |
| "scipy==1.18.0" | |
| - name: Install pinned GFortran and LAPACK link dependencies | |
| shell: bash | |
| run: | | |
| packages=(libblas-dev liblapack-dev) | |
| if ! command -v "$PRIK_GFORTRAN_BINARY" >/dev/null 2>&1; then | |
| packages+=("$PRIK_GFORTRAN_PACKAGE") | |
| fi | |
| sudo apt-get update | |
| sudo apt-get install --yes "${packages[@]}" | |
| compiler_dir="$RUNNER_TEMP/prik-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$PRIK_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| "$compiler_dir/gfortran" --version | |
| - name: Restore compiled native library cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ runner.temp }}/prik-real-library-native | |
| key: real-libraries-${{ runner.os }}-gfortran13-${{ hashFiles('examples/blas/native/**', 'examples/lapack/native/**') }} | |
| - name: Run BLAS example and CI full-surface audit | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| PRIK_REAL_LIBRARY_NATIVE_CACHE_DIR: ${{ runner.temp }}/prik-real-library-native | |
| run: | | |
| source examples/blas/build_all.sh | |
| python -m pytest -q examples/blas/tests examples/blas/ci/full_surface.py | |
| - name: Report reviewed LAPACK inventory | |
| env: | |
| PYTHONPATH: . | |
| run: | | |
| python - <<'PY' | |
| from examples.lapack.routine_inventory import ( | |
| EXPECTED_LAPACK_PROCEDURES, | |
| EXPECTED_LAPACK_SOURCE_FILES, | |
| F2PY_SCALAR_WRITEBACK_ROUTINES, | |
| ROUTINE_GROUPS, | |
| ROUTINES, | |
| SCIPY_VERSION, | |
| ) | |
| print(f"SciPy version: {SCIPY_VERSION}") | |
| print(f"LAPACK implementation sources: {EXPECTED_LAPACK_SOURCE_FILES}") | |
| print(f"Expected PRIK procedures: {EXPECTED_LAPACK_PROCEDURES}") | |
| print(f"Selected float64 correctness routines: {len(ROUTINES)}") | |
| print(f"f2py scalar writebacks: {len(F2PY_SCALAR_WRITEBACK_ROUTINES)}") | |
| for family, routines in ROUTINE_GROUPS.items(): | |
| print(f" {family}: {len(routines)}") | |
| PY | |
| - name: Run LAPACK example and CI full-surface audit | |
| env: | |
| PYTHONPATH: . | |
| HYPOTHESIS_PROFILE: ci | |
| PRIK_REAL_LIBRARY_NATIVE_CACHE_DIR: ${{ runner.temp }}/prik-real-library-native | |
| run: | | |
| source examples/lapack/build_all.sh | |
| python -m pytest -q examples/lapack/tests examples/lapack/ci/full_surface.py | |
| documentation-benchmark: | |
| name: Documentation performance benchmark · Ubuntu 24.04 ARM64 · Python 3.12 | |
| needs: native-libraries | |
| if: >- | |
| ${{ | |
| always() && | |
| (needs.native-libraries.result == 'success' || | |
| (needs.native-libraries.result == 'skipped' && | |
| contains(github.event.pull_request.labels.*.name, 'ignore-real-library-wrappers'))) | |
| }} | |
| runs-on: ubuntu-24.04-arm | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Verify and record benchmark host | |
| run: >- | |
| python tools/benchmark_host.py | |
| --require-machine aarch64 | |
| --require-arm-part 0xd49 | |
| --github-env "$GITHUB_ENV" | |
| - name: Install benchmark dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[docs]" \ | |
| "numpy==2.5.1" \ | |
| "meson==1.11.2" \ | |
| "ninja==1.13.0" | |
| - name: Install pinned GFortran | |
| shell: bash | |
| run: | | |
| if ! command -v "$PRIK_GFORTRAN_BINARY" >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --yes "$PRIK_GFORTRAN_PACKAGE" | |
| fi | |
| compiler_dir="$RUNNER_TEMP/prik-gfortran" | |
| mkdir -p "$compiler_dir" | |
| ln -sf "$(command -v "$PRIK_GFORTRAN_BINARY")" "$compiler_dir/gfortran" | |
| echo "$compiler_dir" >> "$GITHUB_PATH" | |
| "$compiler_dir/gfortran" --version | |
| - name: Run correctness and rigorous performance suite | |
| shell: bash | |
| run: | | |
| if (( GITHUB_RUN_NUMBER % 2 == 0 )); then | |
| export PRIK_BENCHMARK_FIRST=f2py | |
| else | |
| export PRIK_BENCHMARK_FIRST=prik | |
| fi | |
| bash benchmarks/run.sh | |
| - name: Generate public Performance snapshot | |
| run: | | |
| python tools/generate_performance_docs.py \ | |
| --commit "$GITHUB_SHA" | |
| - name: Report measurement stability | |
| run: | | |
| python -m pyperf check \ | |
| benchmarks/results/f2py.json \ | |
| benchmarks/results/prik.json \ | |
| benchmarks/results/f2py-build.json \ | |
| benchmarks/results/prik-build.json | |
| - name: Upload Performance snapshot and raw results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: performance-snapshot | |
| path: | | |
| benchmarks/results/f2py.json | |
| benchmarks/results/prik.json | |
| benchmarks/results/f2py-build.json | |
| benchmarks/results/prik-build.json | |
| docs/user/performance.md | |
| docs/user/assets/performance-comparison.svg | |
| docs/user/assets/build-time-comparison.svg | |
| retention-days: 90 | |
| documentation-build: | |
| name: Documentation site build · Ubuntu 24.04 · Python 3.12 | |
| needs: documentation-benchmark | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install documentation dependencies | |
| run: python -m pip install -e ".[docs,qa]" | |
| - name: Download generated Performance snapshot | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: performance-snapshot | |
| path: . | |
| - name: Run documentation tests | |
| run: python -m pytest -q tests/shared/docs | |
| - name: Build reviewed documentation | |
| run: python -m mkdocs build --strict | |
| merge-gate: | |
| name: Validation · all required checks | |
| if: ${{ always() }} | |
| needs: | |
| - static-analysis | |
| - parser-reference-guard | |
| - compiler-smoke | |
| - compiler-smoke-macos | |
| - unit-tests | |
| - unit-tests-macos | |
| - native-libraries | |
| - documentation-benchmark | |
| - documentation-build | |
| runs-on: ubuntu-24.04 | |
| permissions: {} | |
| env: | |
| STATIC_ANALYSIS_RESULT: ${{ needs.static-analysis.result }} | |
| PARSER_REFERENCE_RESULT: ${{ needs.parser-reference-guard.result }} | |
| COMPILER_SMOKE_RESULT: ${{ needs.compiler-smoke.result }} | |
| COMPILER_SMOKE_MACOS_RESULT: ${{ needs.compiler-smoke-macos.result }} | |
| UNIT_TESTS_RESULT: ${{ needs.unit-tests.result }} | |
| UNIT_TESTS_MACOS_RESULT: ${{ needs.unit-tests-macos.result }} | |
| NATIVE_LIBRARIES_RESULT: ${{ needs.native-libraries.result }} | |
| DOCUMENTATION_BENCHMARK_RESULT: ${{ needs.documentation-benchmark.result }} | |
| DOCUMENTATION_BUILD_RESULT: ${{ needs.documentation-build.result }} | |
| IGNORE_NATIVE_LIBRARIES: ${{ contains(github.event.pull_request.labels.*.name, 'ignore-real-library-wrappers') }} | |
| steps: | |
| - name: Require every staged validation result | |
| shell: bash | |
| run: | | |
| failed=0 | |
| for staged_result in \ | |
| "static-analysis=$STATIC_ANALYSIS_RESULT" \ | |
| "parser-reference=$PARSER_REFERENCE_RESULT" \ | |
| "compiler-smoke=$COMPILER_SMOKE_RESULT" \ | |
| "compiler-smoke-macos=$COMPILER_SMOKE_MACOS_RESULT" \ | |
| "unit-tests=$UNIT_TESTS_RESULT" \ | |
| "unit-tests-macos=$UNIT_TESTS_MACOS_RESULT" \ | |
| "native-libraries=$NATIVE_LIBRARIES_RESULT" \ | |
| "documentation-benchmark=$DOCUMENTATION_BENCHMARK_RESULT" \ | |
| "documentation-build=$DOCUMENTATION_BUILD_RESULT" | |
| do | |
| stage=${staged_result%%=*} | |
| result=${staged_result#*=} | |
| if [[ "$stage" == "native-libraries" && \ | |
| "$result" == "skipped" && \ | |
| "$IGNORE_NATIVE_LIBRARIES" == "true" ]]; then | |
| continue | |
| fi | |
| if [[ "$result" != "success" ]]; then | |
| echo "::error::$stage finished with result: $result" | |
| failed=1 | |
| fi | |
| done | |
| exit "$failed" |