From 9367457825d1e9bda76b3371ebc768b2753c450b Mon Sep 17 00:00:00 2001 From: Hashwanth Sutharapu Date: Sat, 6 Jun 2026 22:02:26 -0700 Subject: [PATCH] ci: add GitHub Actions workflow for unit tests Adds .github/workflows/ci.yml that runs pytest tests/unit/ on every push and pull request to main. - Tests Python 3.10, 3.11, 3.12, 3.13 on ubuntu-latest - Adds a windows-latest smoke test on 3.13 to guard against platform-specific issues (non-UTF-8 stdout, missing /bin/bash) - Pins both actions to full SHA digests for supply-chain integrity - Caches pip downloads via setup-python built-in cache (keyed on pyproject.toml hash) - Restricts GITHUB_TOKEN to contents: read (OSSF Scorecard compliance) - Cancels in-progress runs when a new commit is pushed to the same branch/PR - 10-minute job timeout to prevent runaway jobs - No Playwright browser install needed: all 16 unit tests pass without browser binaries (confirmed locally) Also declares pytest>=7.4 as a [dev] optional dependency in pyproject.toml so `pip install -e ".[dev]"` resolves the test runner cleanly without a bare unpinned pip install. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 68 ++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 3 ++ 2 files changed, 71 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0665309 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,68 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +# Restrict the default GITHUB_TOKEN to read-only. +# This workflow only checks out code and runs tests — no write access needed. +# Satisfies OSSF Scorecard "Token-Permissions" check. +permissions: + contents: read + +# Cancel any in-progress run for the same branch/PR when a new commit is pushed. +# Prevents stacked runs from queuing up on active PR branches. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + # Matrix: Python 3.10–3.13 on Linux, plus a Windows smoke test on 3.13. + # The Windows leg specifically guards against platform-specific issues + # (UnicodeEncodeError on non-UTF-8 stdout, /bin/bash not found, etc.). + name: Python ${{ matrix.python-version }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + python-version: ["3.10", "3.11", "3.12", "3.13"] + include: + - os: windows-latest + python-version: "3.13" + + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + # Caches the pip download cache keyed on pyproject.toml hash. + # Saves ~20 s per matrix leg on a warm cache. + cache: "pip" + + - name: Install package and test dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + pip install -e ".[dev]" + + # Playwright browser binaries are intentionally NOT installed here. + # All 16 current unit tests are pure-Python and pass without a real browser: + # the `playwright` Python package is installed as a runtime dep (via pip install -e .) + # so `import playwright` works, but check_screenshot() gracefully returns + # (False, "unable to launch...") when no browser binary is present. + # Uncomment the step below when browser-level integration tests are added. + # + # - name: Install Playwright browsers + # run: playwright install --with-deps chromium + + - name: Run unit tests + run: pytest tests/unit/ -v --tb=short + + # TODO: Add `ruff check src/ tests/` here once ruff is configured in pyproject.toml. diff --git a/pyproject.toml b/pyproject.toml index fb4d113..5786527 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,9 @@ dependencies = [ "platformdirs>=4.0", ] +[project.optional-dependencies] +dev = ["pytest>=7.4"] + [project.scripts] webwright = "webwright.run.cli:app"