From f6b9edf334f75df54c7aa1354584fc3d4e35e922 Mon Sep 17 00:00:00 2001 From: oliverlaslett <11660098+owlas@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:10:57 +0100 Subject: [PATCH 1/2] ci: automate releases on merge to main Add GitHub Actions to replace the manual 'just publish' flow: - ci.yml: run unit tests on every PR and push to main (py3.9 + 3.12). - release.yml: on merge to main, run python-semantic-release to compute the next version from Conventional Commit messages, bump pyproject.toml, tag, create a GitHub Release, and publish to PyPI via Trusted Publishing (OIDC). Also declare an explicit [build-system] (setuptools) which was missing. Versioning is anchored by a baseline v1.0.1 tag matching the current PyPI release; the 8 unreleased PRs on main will publish as 1.1.0 on first run. --- .github/workflows/ci.yml | 42 +++++++++++++++++++++ .github/workflows/release.yml | 70 +++++++++++++++++++++++++++++++++++ pyproject.toml | 21 +++++++++++ 3 files changed, 133 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1e6bc6c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +# Cancel superseded runs on the same ref to save CI minutes. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Unit tests (py${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Floor and a current version; bump as supported range changes. + python-version: ["3.9", "3.12"] + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package + dev deps + run: | + uv venv + uv pip install -e ".[dev]" + + - name: Run unit tests + # test_acceptance.py and test_query.py require a live Lightdash + # instance + credentials, so they are excluded from CI. + run: | + uv run pytest tests/ \ + --ignore=tests/test_acceptance.py \ + --ignore=tests/test_query.py \ + -q diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3d2f6ff --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,70 @@ +name: Release + +# Publish on merge to main. python-semantic-release inspects the Conventional +# Commit messages since the last "v*" tag, decides the next version (or that no +# release is warranted), bumps pyproject.toml, tags, creates a GitHub Release, +# and we then upload the built artifacts to PyPI. +# +# The version-bump commit it pushes back to main contains "[skip ci]" so this +# workflow does not retrigger itself. +on: + push: + branches: [main] + +# Never run two releases concurrently. +concurrency: + group: release + cancel-in-progress: false + +jobs: + test: + name: Unit tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + python-version: "3.12" + - name: Install package + dev deps + run: | + uv venv + uv pip install -e ".[dev]" + - name: Run unit tests + run: | + uv run pytest tests/ \ + --ignore=tests/test_acceptance.py \ + --ignore=tests/test_query.py \ + -q + + release: + name: Semantic Release + runs-on: ubuntu-latest + needs: test + # Guard against forks: only the canonical repo should publish. + if: github.repository == 'lightdash/python-sdk' + permissions: + contents: write # push the version bump/tag and create the GitHub Release + id-token: write # PyPI Trusted Publishing (OIDC) + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # semantic-release needs full history + tags + + - name: Python Semantic Release + id: release + uses: python-semantic-release/python-semantic-release@v9 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to PyPI + if: steps.release.outputs.released == 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + + - name: Upload artifacts to the GitHub Release + if: steps.release.outputs.released == 'true' + uses: python-semantic-release/publish-action@v9 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ steps.release.outputs.tag }} diff --git a/pyproject.toml b/pyproject.toml index abeac22..8128a5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,3 +28,24 @@ include = ["lightdash*"] testpaths = ["tests"] python_files = ["test_*.py"] log_cli_level = "DEBUG" + +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +# Releases are automated by GitHub Actions (.github/workflows/release.yml). +# python-semantic-release computes the next version from Conventional Commit +# messages (feat: -> minor, fix: -> patch, BREAKING CHANGE -> major) since the +# last "v*" tag, bumps the version below, tags, creates a GitHub Release, and +# publishes to PyPI. Do not bump `version` by hand. +[tool.semantic_release] +version_toml = ["pyproject.toml:project.version"] +build_command = "pip install build && python -m build" +commit_message = "chore(release): v{version} [skip ci]" +tag_format = "v{version}" + +[tool.semantic_release.branches.main] +match = "main" + +[tool.semantic_release.changelog] +exclude_commit_patterns = ['''chore\(release\):.*'''] From e65bf9dad76f2272d66764820129de9d4256f931 Mon Sep 17 00:00:00 2001 From: oliverlaslett <11660098+owlas@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:13:35 +0100 Subject: [PATCH 2/2] ci: drop redundant 'uv venv' (setup-uv already creates it) --- .github/workflows/ci.yml | 5 ++--- .github/workflows/release.yml | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e6bc6c..6a22387 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install package + dev deps - run: | - uv venv - uv pip install -e ".[dev]" + # setup-uv already created .venv and set VIRTUAL_ENV. + run: uv pip install -e ".[dev]" - name: Run unit tests # test_acceptance.py and test_query.py require a live Lightdash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3d2f6ff..7c83171 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,9 +27,8 @@ jobs: with: python-version: "3.12" - name: Install package + dev deps - run: | - uv venv - uv pip install -e ".[dev]" + # setup-uv already created .venv and set VIRTUAL_ENV. + run: uv pip install -e ".[dev]" - name: Run unit tests run: | uv run pytest tests/ \