Skip to content

docs: link the CLI mention to the command reference #12

docs: link the CLI mention to the command reference

docs: link the CLI mention to the command reference #12

Workflow file for this run

name: wheels
# Build one py3-none wheel per platform by bundling the official binary from
# the browser repo's GitHub release (the same asset the README tells users to
# download). No compilation happens here — all four wheels build on one
# Ubuntu runner; native runners are only needed to *test* them.
#
# Modeled on zignal's python.yml (matrix -> build -> test-the-wheel ->
# publish), minus everything a C extension needs: no per-Python builds,
# no cross-compilation, no auditwheel/delocate.
#
# Triggers:
# - pull_request / push to main: build + test against the browser
# `nightly` release, no publish.
# - release published: build + test the browser release with the SAME tag
# and publish to PyPI. A release tag on this repo must equal the browser
# release tag it ships (e.g. 0.4.0); the wheel version is derived from
# it. Releases here are created automatically by the browser repo's
# release workflow (its `update-python-package` job) whenever it builds a
# version tag, so a browser release flows to PyPI with no polling — the
# publish still stops at the pypi environment's required-reviewer gate.
# - workflow_dispatch: pick any browser tag and publish target manually.
on:
pull_request:
push:
branches: [main]
release:
types: [published]
workflow_dispatch:
inputs:
release:
description: "browser release tag to bundle (nightly or a version tag)"
default: "nightly"
publish:
description: "where to publish"
type: choice
options: [none, testpypi, pypi]
default: none
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
BROWSER_REPO: lightpanda-io/browser
jobs:
# Map the triggering event to the browser tag to bundle and the publish
# target, so the downstream jobs don't each re-derive it.
params:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
release_tag: ${{ steps.resolve.outputs.release_tag }}
publish: ${{ steps.resolve.outputs.publish }}
steps:
- name: Resolve release tag and publish target
id: resolve
run: |
case "${{ github.event_name }}" in
release)
echo "release_tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
echo "publish=pypi" >> "$GITHUB_OUTPUT"
;;
workflow_dispatch)
echo "release_tag=${{ inputs.release }}" >> "$GITHUB_OUTPUT"
echo "publish=${{ inputs.publish }}" >> "$GITHUB_OUTPUT"
;;
*)
echo "release_tag=nightly" >> "$GITHUB_OUTPUT"
echo "publish=none" >> "$GITHUB_OUTPUT"
;;
esac
cat "$GITHUB_OUTPUT"
# A nightly build keeps pyproject's dev version; never let one
# reach PyPI, whatever dispatched it.
if grep -q '^publish=pypi$' "$GITHUB_OUTPUT" && grep -q '^release_tag=nightly$' "$GITHUB_OUTPUT"; then
echo "::error::refusing to publish a nightly build to PyPI (pick a version tag)"
exit 1
fi
build:
needs: params
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
include:
- asset: lightpanda-x86_64-linux
plat: manylinux_2_35_x86_64
- asset: lightpanda-aarch64-linux
plat: manylinux_2_35_aarch64
- asset: lightpanda-aarch64-macos
plat: macosx_14_0_arm64
- asset: lightpanda-x86_64-macos
plat: macosx_13_0_x86_64
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- name: Download the release binary
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download "${{ needs.params.outputs.release_tag }}" -R "$BROWSER_REPO" \
-p "${{ matrix.asset }}" -O lightpanda-bin
chmod +x lightpanda-bin
ls -la lightpanda-bin
# The tool schemas are platform-independent; fetch the one binary
# this runner can execute to regenerate the methods from.
if [ "${{ matrix.asset }}" = lightpanda-x86_64-linux ]; then
cp lightpanda-bin lightpanda-gen
else
gh release download "${{ needs.params.outputs.release_tag }}" -R "$BROWSER_REPO" \
-p lightpanda-x86_64-linux -O lightpanda-gen
chmod +x lightpanda-gen
fi
- name: Regenerate tool methods from the bundled binary
env:
LIGHTPANDA_BIN: ${{ github.workspace }}/lightpanda-gen
run: |
# The wheel always ships methods matching the binary it bundles.
uv run --no-project python scripts/generate_methods.py
# PRs and pushes build against nightly: fail on drift so the committed
# file (what IDEs and the docs see) keeps up with the browser's tools.
case "${{ github.event_name }}" in
pull_request|push)
git diff --exit-code -- lightpanda/_methods.py || {
echo "::error::lightpanda/_methods.py is out of date: run scripts/generate_methods.py and commit the result"
exit 1
}
;;
esac
- name: Set wheel version from tag
if: needs.params.outputs.release_tag != 'nightly'
run: |
# Wheel version == browser release tag (PEP 440 expects no leading v).
tag="${{ needs.params.outputs.release_tag }}"
sed -i "s/^version = .*/version = \"${tag#v}\"/" pyproject.toml
grep '^version' pyproject.toml
- name: Build wheel
env:
LIGHTPANDA_BIN: ${{ github.workspace }}/lightpanda-bin
LIGHTPANDA_PLAT: ${{ matrix.plat }}
run: uv build --wheel
- uses: actions/upload-artifact@v4
with:
name: wheel-${{ matrix.plat }}
path: dist/*.whl
test:
needs: build
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-latest
plat: manylinux_2_35_x86_64
- runner: ubuntu-24.04-arm
plat: manylinux_2_35_aarch64
- runner: macos-14
plat: macosx_14_0_arm64
- runner: macos-15-intel
plat: macosx_13_0_x86_64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- uses: actions/download-artifact@v4
with:
name: wheel-${{ matrix.plat }}
path: dist
- name: Install the wheel into a clean venv
run: |
uv venv wheel-env
uv pip install --python wheel-env dist/*.whl pytest pytest-asyncio
- name: Run the test suite against the installed wheel
run: |
# Resolve the *bundled* binary and pin the tests to it; run from
# outside the checkout so the source tree can't shadow the install
# (-I likewise keeps the cwd off sys.path for this resolution).
# pyproject.toml comes along for its [tool.pytest.ini_options]
# (asyncio_mode) — without it the async tests are silently skipped.
BIN=$(./wheel-env/bin/python -I -c "from lightpanda.client import find_binary; print(find_binary())")
echo "bundled binary: $BIN"
mkdir -p /tmp/wheeltest && cp -r tests pyproject.toml /tmp/wheeltest/
cd /tmp/wheeltest
LIGHTPANDA_BIN="$BIN" "$GITHUB_WORKSPACE"/wheel-env/bin/python -m pytest tests -q
- name: CLI smoke
run: ./wheel-env/bin/lightpanda version
publish:
needs: [params, test]
if: needs.params.outputs.publish != 'none'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: ${{ needs.params.outputs.publish }}
permissions:
id-token: write # PyPI trusted publishing
steps:
- uses: astral-sh/setup-uv@v5
- uses: actions/download-artifact@v4
with:
pattern: wheel-*
merge-multiple: true
path: dist
- name: Publish
run: |
if [ "${{ needs.params.outputs.publish }}" = "testpypi" ]; then
uv publish --publish-url https://test.pypi.org/legacy/ dist/*.whl
else
uv publish dist/*.whl
fi