name: Python Wheels # The core libfyaml library supports Linux, macOS, the BSDs, and Windows. # This workflow covers the Python wheel matrix expected to be reliable in CI. # BSDs still use source builds. Windows wheels require a Clang-family toolchain # because the binding depends on libfyaml generics. # # Keep the matrix explicit by target platform/architecture. Using multiple # runner labels that resolve to the same wheel tags can produce duplicate # artifacts and break the publish job. on: push: branches: - master - stable - devel tags: - "v*" paths: - ".github/workflows/python-wheels.yaml" - "CMakeLists.txt" - "cmake/**" - "include/**" - "src/**" - "python-libfyaml/**" - ".libtool-version" - ".tarball-version" - "build-aux/git-version-gen" pull_request: paths: - ".github/workflows/python-wheels.yaml" - "CMakeLists.txt" - "cmake/**" - "include/**" - "src/**" - "python-libfyaml/**" - ".libtool-version" - ".tarball-version" - "build-aux/git-version-gen" workflow_dispatch: inputs: publish: description: "Publish built distributions to PyPI" required: true default: false type: boolean jobs: build_wheels: name: Build Wheels (${{ matrix.name }}) runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: include: - name: linux-x86_64 runner: ubuntu-latest cibw_archs: x86_64 cibw_environment: LIBFYAML_REPO_ROOT=/project - name: macos-x86_64 runner: macos-15-intel cibw_archs: x86_64 cibw_environment: LIBFYAML_REPO_ROOT=${{ github.workspace }} - name: macos-arm64 runner: macos-14 cibw_archs: arm64 cibw_environment: LIBFYAML_REPO_ROOT=${{ github.workspace }} - name: windows-amd64 runner: windows-latest cibw_archs: AMD64 cibw_environment: >- LIBFYAML_REPO_ROOT=${{ github.workspace }} CC=clang-cl CXX=clang-cl CMAKE_GENERATOR=Ninja LIBFYAML_CMAKE_ARGS=-DCMAKE_C_COMPILER=clang-cl cibw_environment_windows: >- LIBFYAML_REPO_ROOT=${{ github.workspace }} CC=clang-cl CXX=clang-cl CMAKE_GENERATOR=Ninja LIBFYAML_CMAKE_ARGS=-DCMAKE_C_COMPILER=clang-cl steps: - uses: actions/checkout@v4 - name: Setup Windows Clang if: runner.os == 'Windows' shell: powershell run: | $llvm = 'C:\Program Files\LLVM\bin' if (-not (Test-Path (Join-Path $llvm 'clang-cl.exe'))) { throw "clang-cl.exe not found in $llvm" } Add-Content -Path $env:GITHUB_PATH -Value $llvm - name: Validate release tag shell: bash run: | python3 - <<'PY' import pathlib import re raw_version = pathlib.Path(".tarball-version").read_text().strip() match = re.fullmatch(r"(\d+\.\d+\.\d+)(?:-(alpha|beta|rc)(\d+))?", raw_version) if not match: raise SystemExit(f"Unsupported libfyaml release version format: {raw_version!r}") ref_name = "${{ github.ref_name }}" ref_type = "${{ github.ref_type }}" if ref_type == "tag": expected_tag = f"v{raw_version}" if ref_name != expected_tag: raise SystemExit( f"Git tag {ref_name!r} does not match .tarball-version {raw_version!r} " f"(expected {expected_tag!r})" ) print(f"Validated core release version {raw_version}") PY - name: Build wheels uses: pypa/cibuildwheel@v3.3.0 with: package-dir: python-libfyaml output-dir: wheelhouse env: CIBW_ARCHS: ${{ matrix.cibw_archs }} CIBW_ENVIRONMENT: ${{ matrix.cibw_environment }} CIBW_ENVIRONMENT_WINDOWS: ${{ matrix.cibw_environment_windows }} - name: Upload wheel artifacts uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.name }} path: wheelhouse/*.whl build_sdist: name: Build Source Distribution runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Validate release tag shell: bash run: | python3 - <<'PY' import pathlib import re raw_version = pathlib.Path(".tarball-version").read_text().strip() match = re.fullmatch(r"(\d+\.\d+\.\d+)(?:-(alpha|beta|rc)(\d+))?", raw_version) if not match: raise SystemExit(f"Unsupported libfyaml release version format: {raw_version!r}") ref_name = "${{ github.ref_name }}" ref_type = "${{ github.ref_type }}" if ref_type == "tag": expected_tag = f"v{raw_version}" if ref_name != expected_tag: raise SystemExit( f"Git tag {ref_name!r} does not match .tarball-version {raw_version!r} " f"(expected {expected_tag!r})" ) print(f"Validated core release version {raw_version}") PY - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install build frontend run: python -m pip install --upgrade build - name: Stage sdist source tree shell: bash run: | set -euo pipefail stage_root="${RUNNER_TEMP}/libfyaml-python-sdist" rm -rf "${stage_root}" mkdir -p "${stage_root}" cp -R python-libfyaml/. "${stage_root}/" cp -R include src cmake "${stage_root}/" cp CMakeLists.txt .tarball-version .libtool-version "${stage_root}/" - name: Build sdist run: python -m build --sdist "${RUNNER_TEMP}/libfyaml-python-sdist" - name: Upload sdist artifact uses: actions/upload-artifact@v4 with: name: sdist path: ${{ runner.temp }}/libfyaml-python-sdist/dist/*.tar.gz publish: name: Publish To PyPI if: > startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.publish) needs: - build_wheels - build_sdist runs-on: ubuntu-latest permissions: id-token: write environment: name: pypi steps: - name: Download distribution artifacts uses: actions/download-artifact@v4 with: path: dist merge-multiple: true - name: Publish distributions uses: pypa/gh-action-pypi-publish@release/v1