Feature/ci cd #32
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: Build and Test Wheels | |
| on: | |
| push: | |
| branches: [main, master] | |
| tags: | |
| - "v*" | |
| pull_request: | |
| branches: [main, master] | |
| release: | |
| types: [published] | |
| # Allow manual triggering or remote triggering via GitHub CLI/API | |
| # (used by cfd repo's version-release.yml via: gh workflow run build-wheels.yml) | |
| workflow_dispatch: | |
| inputs: | |
| cfd_ref: | |
| description: "CFD library ref (tag/branch/commit). Leave empty to auto-detect." | |
| required: false | |
| default: "" | |
| jobs: | |
| build_wheels: | |
| name: Build wheels on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| # Build only on Linux for now (simplified debugging) | |
| os: [ubuntu-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| # Determine which version of CFD library to use | |
| # Priority: workflow_dispatch input > latest cfd release tag | |
| # This ensures we always build against stable, tested cfd releases | |
| - name: Determine CFD library version | |
| id: cfd-version | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # Check for workflow_dispatch input first | |
| if [[ -n "${{ github.event.inputs.cfd_ref }}" ]]; then | |
| echo "ref=${{ github.event.inputs.cfd_ref }}" >> $GITHUB_OUTPUT | |
| echo "Using CFD library ref from input: ${{ github.event.inputs.cfd_ref }}" | |
| else | |
| # Fetch the latest release tag from cfd repo | |
| LATEST_TAG=$(gh api repos/${{ github.repository_owner }}/cfd/releases/latest --jq '.tag_name' 2>/dev/null || echo "") | |
| if [[ -n "$LATEST_TAG" ]]; then | |
| echo "ref=$LATEST_TAG" >> $GITHUB_OUTPUT | |
| echo "Using latest CFD release: $LATEST_TAG" | |
| else | |
| # Fallback to master if no releases exist | |
| echo "ref=master" >> $GITHUB_OUTPUT | |
| echo "No CFD releases found, falling back to master branch" | |
| fi | |
| fi | |
| # Checkout the CFD C library into 'src/cfd_lib' subdirectory | |
| # This location is inside the source tree so it's accessible from cibuildwheel | |
| # build environments (including Linux Docker containers where source is mounted) | |
| - name: Checkout CFD C library | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.repository_owner }}/cfd | |
| path: src/cfd_lib | |
| ref: ${{ steps.cfd-version.outputs.ref }} | |
| fetch-depth: 0 | |
| # Build wheels using cibuildwheel | |
| # Configuration is in pyproject.toml - we only override CFD_ROOT for CI | |
| # (pyproject.toml defaults to ../cfd for local dev, CI uses ./src/cfd_lib) | |
| - name: Build wheels | |
| uses: pypa/cibuildwheel@v2.21.3 | |
| env: | |
| # Override CFD_ROOT to point to the cfd checkout inside the source tree | |
| # All other settings (build flags, before-build, etc.) come from pyproject.toml | |
| CIBW_ENVIRONMENT: "CMAKE_BUILD_TYPE=Release CFD_STATIC_LINK=ON CFD_USE_STABLE_ABI=ON CFD_ROOT=./src/cfd_lib" | |
| # Enable verbose output to see CMake and compiler commands | |
| CIBW_BUILD_VERBOSITY: "3" | |
| - name: List wheel contents for debugging | |
| shell: bash | |
| run: | | |
| echo "=== Wheels built ===" | |
| ls -la wheelhouse/ | |
| echo "" | |
| echo "=== Inspecting wheel contents ===" | |
| for wheel in wheelhouse/*.whl; do | |
| echo "--- $wheel ---" | |
| python -m zipfile -l "$wheel" | grep -E '\.(so|pyd|dylib)$' || echo "No extension found!" | |
| done | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: wheels-${{ matrix.os }} | |
| path: ./wheelhouse/*.whl | |
| build_sdist: | |
| name: Build source distribution | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Build sdist | |
| run: pipx run build --sdist | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: sdist | |
| path: dist/*.tar.gz | |
| test_package: | |
| name: Test package installation | |
| needs: [build_wheels] | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| # Test on Linux with Python 3.8 (matches abi3 wheel) and 3.12 (to verify abi3 compat) | |
| os: [ubuntu-latest] | |
| python-version: ["3.8", "3.12"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: wheels-${{ matrix.os }} | |
| path: wheelhouse | |
| - name: List available wheels | |
| shell: bash | |
| run: | | |
| echo "=== Available wheels ===" | |
| ls -la wheelhouse/ | |
| echo "" | |
| echo "=== Python version ===" | |
| python --version | |
| echo "" | |
| echo "=== Wheel contents (looking for .so/.pyd files) ===" | |
| for wheel in wheelhouse/*.whl; do | |
| echo "--- $wheel ---" | |
| python -m zipfile -l "$wheel" | grep -E '\.(so|pyd|dylib)$' || echo "No extension found in wheel!" | |
| done | |
| - name: Install wheel and test dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -v --find-links wheelhouse cfd-python | |
| python -m pip install pytest numpy | |
| - name: Verify installation | |
| shell: bash | |
| run: | | |
| echo "=== Installed package location ===" | |
| python -c "import cfd_python; print('Package __file__:', cfd_python.__file__)" | |
| echo "" | |
| echo "=== Package directory contents ===" | |
| python -c "import cfd_python, os; pkgdir=os.path.dirname(cfd_python.__file__); print('Contents:', os.listdir(pkgdir)); exts=[f for f in os.listdir(pkgdir) if '.so' in f or '.pyd' in f]; print('Extensions found:', exts)" | |
| echo "" | |
| echo "=== Try importing C extension directly ===" | |
| python -c " | |
| import sys, os | |
| import cfd_python | |
| pkgdir = os.path.dirname(cfd_python.__file__) | |
| print('Package dir:', pkgdir) | |
| print('Has list_solvers:', hasattr(cfd_python, 'list_solvers')) | |
| # Try direct import of the extension | |
| try: | |
| from cfd_python import cfd_python as ext | |
| print('Direct extension import OK') | |
| print('Extension has PyInit:', hasattr(ext, '__name__')) | |
| print('list_solvers available:', hasattr(ext, 'list_solvers')) | |
| except ImportError as e: | |
| print('Direct extension import FAILED:', e) | |
| # Check __all__ | |
| print('__all__:', getattr(cfd_python, '__all__', 'NOT DEFINED')) | |
| print('__version__:', getattr(cfd_python, '__version__', 'NOT DEFINED')) | |
| " | |
| - name: Run full test suite | |
| run: pytest tests/ -v | |
| upload_pypi: | |
| name: Upload to PyPI | |
| needs: [build_wheels, build_sdist, test_package] | |
| runs-on: ubuntu-latest | |
| # Publish on: release event, tag push (v*), or workflow_dispatch on a tag | |
| if: | | |
| github.event_name == 'release' || | |
| (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || | |
| (github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/v')) | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/cfd-python | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wheels-* | |
| path: dist | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: sdist | |
| path: dist | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@v1.12.4 # Pin to specific version for security | |
| with: | |
| packages-dir: dist/ | |
| upload_test_pypi: | |
| name: Upload to Test PyPI | |
| needs: [build_wheels, build_sdist, test_package] | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') | |
| environment: | |
| name: testpypi | |
| url: https://test.pypi.org/p/cfd-python | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wheels-* | |
| path: dist | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: sdist | |
| path: dist | |
| - name: Publish to Test PyPI | |
| uses: pypa/gh-action-pypi-publish@v1.12.4 # Pin to specific version for security | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| packages-dir: dist/ |