From 838999f63b1f6c80dd933329c9e1f35cc228636e Mon Sep 17 00:00:00 2001 From: how2how2how2-arch Date: Sun, 25 Oct 2026 16:35:54 +0800 Subject: [PATCH] ci: add macOS and Windows smoke tests Add a `smoke` job that installs the package, starts the console script, and round-trips a saved trace on macOS and Windows. The full suite, lint, type checks and build stay in the existing Linux job, which is not modified. The subset is deliberately narrow: test_storage.py saves and loads traces under tmp_path and test_cli.py covers help/version/no-command, so the job answers "does this install and does the format round-trip here" without requiring the whole suite on every OS. Both use tmp_path or the in-process runner, so neither reads a committed bundle. Documented in the job rather than fixed here: the committed .sftrace bundles carry SHA-256 digests over file bytes, while the writers in trace/storage.py open in text mode without newline="". A bundle written on Windows therefore carries CRLF and cannot reproduce a Linux digest, and a Windows checkout rewrites the committed fixtures before any test runs (no .gitattributes). Making the on-disk format byte-identical across platforms is a separate change. Python versions are 3.11 and 3.13, the lowest and highest supported; the middle version remains covered by the Linux matrix. --- .github/workflows/ci.yml | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2c4bbd..4d9173e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,3 +48,66 @@ jobs: - name: Build package run: uv build + + # Cross-platform smoke tests (#28). + # + # Scope is deliberately narrow: this job answers "does the package install, + # does the console script start, and does the saved trace format round-trip + # on this OS" -- not "does the whole suite pass here". The full suite, lint, + # type checks and the build stay in `test` above and remain Linux-only, so + # adding an OS costs one short job instead of a full matrix. + # + # Python versions are the lowest and the highest supported (3.11 and 3.13, + # per requires-python). The middle version stays covered by the Linux matrix; + # that is a deliberate cost choice, not a claim of identical coverage. + # + # Known platform limitation, deliberately not covered here: the committed + # `.sftrace` bundles under `examples/` and `tests/golden/` record SHA-256 + # digests over file bytes (`trace/integrity.py::_hash_file`, + # `export/receipt.py::bundle_digest`), while the writers in + # `trace/storage.py` open files in text mode without `newline=""`. A bundle + # written on Windows therefore carries CRLF and cannot reproduce a digest + # recorded on Linux, and a Windows checkout (git's default `core.autocrlf=true`) + # rewrites those committed files before any test runs. Making the on-disk + # format byte-identical across platforms is a separate change + # (`newline=""` and/or `.gitattributes`). Until that lands, this job runs the + # save/load and CLI tests, which round-trip within a single platform and never + # read a committed bundle. + smoke: + name: Smoke ${{ matrix.os }} / Python ${{ matrix.python-version }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: ["macos-latest", "windows-latest"] + python-version: ["3.11", "3.13"] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v10.1.0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Sync dependencies + run: uv sync --locked --python ${{ matrix.python-version }} + + # The console script, not the in-process test runner: this is the part + # that actually breaks on a new OS (entry point, shim, launcher). + - name: CLI starts + run: uv run --no-sync stepfork --version + + - name: CLI help + run: uv run --no-sync stepfork --help + + # Trace save/load round-trip plus CLI startup/version/no-command tests. + # Both files use tmp_path or the in-process runner, so they exercise the + # format on this OS without depending on a committed bundle. + - name: Trace save/load and CLI smoke tests + run: uv run --no-sync pytest tests/unit/test_storage.py tests/unit/test_cli.py -q