Skip to content

Add packaging CI gates: wheel/sdist build + install-from-wheel smoke + public-API import test #274

Description

@breimanntools

Problem

PyPI advertises Python 3.10–3.14 support, but nothing in CI proves the built
wheel/sdist actually installs and imports
on a clean environment. The test
matrix runs against the source tree (editable/dev install), so a missing
package-data file, a bad build-backend include, or a broken __init__
re-export would only surface after a user pip installs the release — exactly
when it is most expensive. A standalone py.typed-in-wheel guard exists, but
there is no general build → install-from-wheel → public-API-import gate. With
v1.1 still unreleased (pyproject is at 1.0.3), this is the missing safety net
before the next publish.

Goal

Add a CI job that builds the wheel and sdist, installs the wheel into a fresh
venv with base dependencies only, and asserts every public symbol in
aaanalysis.__all__ imports and that bundled _data resources load — across the
min+max supported Python versions, with no new required runtime dependency.

Requirements

  • Build sdist + wheel via python -m build; assert exactly one of each is
    produced.
  • Install the built wheel (not editable, not the source tree) into a
    clean venv with base deps only (no [dev]/[pro]) — this is what
    catches missing package data / bad includes.
  • Public-API import test: import aaanalysis; assert every name in
    aaanalysis.__all__ is importable, and that pro-gated symbols degrade to
    missing_feature_stub gracefully when the pro extra is absent.
  • Bundled-data check: a representative load_dataset(...) / load_scales()
    call succeeds on the clean wheel install (proves _data/*.xlsx/*.tsv
    package-data inclusion).
  • Run on the supported matrix brackets (at least py3.10 + py3.14) on Linux,
    reusing existing matrix conventions in .github/workflows/.

KPIs / Acceptance criteria

  • CI fails if any aaanalysis.__all__ symbol is unimportable from the
    installed wheel (binary pass/fail).
  • CI fails if a bundled _data resource is missing from the wheel
    (asserted via a load_* call on the clean install).
  • Build produces exactly one wheel + one sdist; install into a clean venv
    succeeds with base deps only (no [dev]/[pro] resolved).
  • Green on py3.10 and py3.14.

Scope / non-goals

  • Out: publishing to PyPI / release automation (a separate release step).
  • Out: multi-OS beyond the existing Windows bracket — this gate is Linux;
    Windows min+max is already bracketed in the unit matrix.
  • Out: docs-build-in-CI and downstream-typing-smoke gates (possible
    follow-ups; one issue = one deliverable).
  • Reuses the existing py.typed-in-wheel guard rather than duplicating it.

Dependencies

Standards checklist

  • Frontend/backend split honored — n/a (CI + packaging test)
  • CONFIRM-FIRST surface touched: .github/workflows/* (new job) — flag
    for approval; no pyproject.toml runtime-dep change
  • numpydoc docstring — n/a unless a helper script is added
  • tests — the import/data-load assertions live in a small test invoked
    against the installed wheel
  • no print(); bare ValueError/RuntimeError; coverage measured on the
    package only (--cov=aaanalysis), gate unchanged

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions