diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2df4e65..e84d6b2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,7 @@ on: types: [published] jobs: + build-qret: runs-on: ${{ matrix.os }} strategy: @@ -107,6 +108,7 @@ jobs: - name: Install libyaml-cpp (Linux) if: runner.os == 'Linux' + shell: bash run: | sudo apt-get update sudo apt-get install -y build-essential gcc g++ libyaml-cpp0.8 libyaml-cpp-dev @@ -148,9 +150,11 @@ jobs: -DCMAKE_TOOLCHAIN_FILE="${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" - name: Build qret + shell: bash run: cmake --build build --config Release --target qret - name: Install to stage + shell: bash run: cmake --install build --config Release --prefix stage - name: Package artifact @@ -196,6 +200,75 @@ jobs: name: qret-${{ matrix.asset_suffix }} path: dist/qret-${{ matrix.asset_suffix }}.${{ matrix.archive_ext }} + build-wheel: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - macos-latest + - macos-15-intel + - ubuntu-latest + - windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Build wheel + shell: bash + run: | + python -m pip install --upgrade pip + python -m pip install build + python -m build --wheel + + - name: Upload wheel artifact + uses: actions/upload-artifact@v4 + with: + name: qret-cli-bundle-wheel-${{ matrix.os }} + path: dist/*.whl + + test-qret: + runs-on: ${{ matrix.os }} + needs: [build-wheel] + strategy: + fail-fast: false + matrix: + os: + - macos-latest + - macos-15-intel + - ubuntu-latest + - windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Download wheel artifact + uses: actions/download-artifact@v4 + with: + name: qret-cli-bundle-wheel-${{ matrix.os }} + path: dist + + - name: Install test deps and wheel artifact + shell: bash + run: | + python -m pip install --upgrade pip + python -m pip install pytest + python -m pip install dist/*.whl + + - name: Run pytest + shell: bash + run: pytest -q tests/test_qret_cli_bundle.py + release: if: github.event_name == 'release' needs: [build-qret] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ba5dcd..25cc288 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,36 +40,36 @@ jobs: python -m pip install --upgrade pip python -m pip install -e ".[test]" - - name: Prepare qret stub for test (Unix) - if: runner.os != 'Windows' - run: | - mkdir -p .ci-bin - cat > .ci-bin/qret <<'EOF' - #!/usr/bin/env sh - echo "qret 0.0.0-ci" - EOF - cat > .ci-bin/gridsynth <<'EOF' - #!/usr/bin/env sh - echo "gridsynth 0.0.0-ci" - EOF - chmod +x .ci-bin/qret - chmod +x .ci-bin/gridsynth - echo "$GITHUB_WORKSPACE/.ci-bin" >> "$GITHUB_PATH" + # - name: Prepare qret stub for test (Unix) + # if: runner.os != 'Windows' + # run: | + # mkdir -p .ci-bin + # cat > .ci-bin/qret <<'EOF' + # #!/usr/bin/env sh + # echo "qret 0.0.0-ci" + # EOF + # cat > .ci-bin/gridsynth <<'EOF' + # #!/usr/bin/env sh + # echo "gridsynth 0.0.0-ci" + # EOF + # chmod +x .ci-bin/qret + # chmod +x .ci-bin/gridsynth + # echo "$GITHUB_WORKSPACE/.ci-bin" >> "$GITHUB_PATH" - - name: Prepare qret stub for test (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - New-Item -ItemType Directory -Force -Path .ci-bin | Out-Null - @' - @echo off - echo qret 0.0.0-ci - '@ | Set-Content -Path .ci-bin/qret.cmd - @' - @echo off - echo gridsynth 0.0.0-ci - '@ | Set-Content -Path .ci-bin/gridsynth.cmd - "$env:GITHUB_WORKSPACE/.ci-bin" | Out-File -FilePath $env:GITHUB_PATH -Append + # - name: Prepare qret stub for test (Windows) + # if: runner.os == 'Windows' + # shell: pwsh + # run: | + # New-Item -ItemType Directory -Force -Path .ci-bin | Out-Null + # @' + # @echo off + # echo qret 0.0.0-ci + # '@ | Set-Content -Path .ci-bin/qret.cmd + # @' + # @echo off + # echo gridsynth 0.0.0-ci + # '@ | Set-Content -Path .ci-bin/gridsynth.cmd + # "$env:GITHUB_WORKSPACE/.ci-bin" | Out-File -FilePath $env:GITHUB_PATH -Append - name: Run pytest run: pytest -q tests/test_qret_cli_bundle.py diff --git a/qret_cli_bundle/__init__.py b/qret_cli_bundle/__init__.py index 7b3a74a..38823ee 100644 --- a/qret_cli_bundle/__init__.py +++ b/qret_cli_bundle/__init__.py @@ -90,6 +90,17 @@ def _append_env_path(var_name: str, entry: str) -> None: os.environ[var_name] = current + os.pathsep + entry if current else entry +def _resolve_bundled_executable(bin_dir: Path, name: str) -> Path | None: + if platform.system() == "Windows": + for ext in ("", ".exe", ".cmd", ".bat"): + candidate = bin_dir / f"{name}{ext}" + if candidate.exists(): + return candidate + return None + candidate = bin_dir / name + return candidate if candidate.exists() else None + + def ensure_qret_on_path() -> None: install_root = Path(__file__).parent / "bundle" @@ -98,8 +109,13 @@ def ensure_qret_on_path() -> None: _append_env_path("PATH", str(bin_dir)) if platform.system() == "Linux": _append_env_path("LD_LIBRARY_PATH", str(lib_dir)) + elif platform.system() == "Darwin": + _append_env_path("DYLD_LIBRARY_PATH", str(lib_dir)) - if not (bin_dir / "qret").exists() or not (bin_dir / "gridsynth").exists(): + qret_bin = _resolve_bundled_executable(bin_dir, "qret") + gridsynth_bin = _resolve_bundled_executable(bin_dir, "gridsynth") + + if qret_bin is None or gridsynth_bin is None: asset_name = _platform_asset_name() release = _release_json() assets = {asset["name"]: asset["browser_download_url"] for asset in release.get("assets", [])} @@ -118,8 +134,9 @@ def ensure_qret_on_path() -> None: _extract_archive(archive_path, install_root) archive_path.unlink(missing_ok=True) - if (bin_dir / "gridsynth").exists(): - os.environ["GRIDSYNTH_PATH"] = str(bin_dir / "gridsynth") + gridsynth_bin = _resolve_bundled_executable(bin_dir, "gridsynth") + if gridsynth_bin is not None: + os.environ["GRIDSYNTH_PATH"] = str(gridsynth_bin) ensure_qret_on_path()