From 51b568e28eef6e1b0cedc074e8ebda2be77d5ee4 Mon Sep 17 00:00:00 2001 From: mcflugen Date: Mon, 30 Mar 2026 14:57:47 -0600 Subject: [PATCH] add ci step to build sdist for publishing --- .github/workflows/test.yml | 34 ++++++++++++++++--- noxfile.py | 69 +++++++++++++++++++------------------- pyproject.toml | 4 +++ 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbd1244..66215f2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,14 +17,32 @@ on: - pypi jobs: - test: - # We want to run on external PRs, but not on our own internal PRs as they'll be run - # by the push to the branch. Without this if check, checks are duplicated since - # internal PRs match both the push and pull_request events. + build: if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 + with: + python-version: "3.15" + + - name: Build sdist + run: | + pip install nox + nox -s build + + - uses: actions/upload-artifact@v6 + with: + name: build-dist + path: ${{ github.workspace }}/dist/ + if-no-files-found: error + + test: + needs: [build] runs-on: ${{ matrix.os }} defaults: @@ -43,11 +61,17 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Download source distribution + uses: actions/download-artifact@v8 + with: + name: build-dist + path: ${{ github.workspace }}/dist + - name: Test run: | pip install --upgrade pip pip install nox - nox -s test + nox -s test -- dist/*.whl - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v7 diff --git a/noxfile.py b/noxfile.py index df3c807..0e7a0f4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os import pathlib import shutil @@ -11,18 +12,29 @@ @nox.session def test(session: nox.Session) -> None: - """Run the tests.""" - session.install(".[testing]") + """Test the source, or the built distribution.""" + path = session.posargs[0] if session.posargs else None + + _install_from_path(session, path=path) + + pytest_args: tuple[str, ...] = () + if path is not None: + pytest_args = ("--import-mode=importlib", "--pyargs", "bmipy", "tests") + + session.install("coverage", "pytest", "numpy") + session.run("coverage", "erase") session.run( "coverage", "run", - "--source=bmipy,tests", - "--branch", + "--parallel-mode", "--module", "pytest", + *pytest_args, ) - session.run("coverage", "report", "--ignore-errors", "--show-missing") + + session.run("coverage", "combine") + session.run("coverage", "report", "--show-missing") session.run("coverage", "xml", "-o", "coverage.xml") @@ -74,11 +86,8 @@ def sync_requirements(session: nox.Session) -> None: @nox.session def build(session: nox.Session) -> None: """Build sdist and wheel dists.""" - session.install("pip") session.install("build") - session.run("python", "--version") - session.run("pip", "--version") - session.run("python", "-m", "build", "--outdir", "./build/wheelhouse") + session.run("python", "-m", "build", "--outdir", str(ROOT / "dist")) @nox.session @@ -88,32 +97,6 @@ def release(session): session.run("fullrelease") -@nox.session(name="publish-testpypi") -def publish_testpypi(session): - """Publish wheelhouse/* to TestPyPI.""" - session.run("twine", "check", "build/wheelhouse/*") - session.run( - "twine", - "upload", - "--skip-existing", - "--repository-url", - "https://test.pypi.org/legacy/", - "build/wheelhouse/*.tar.gz", - ) - - -@nox.session(name="publish-pypi") -def publish_pypi(session): - """Publish wheelhouse/* to PyPI.""" - session.run("twine", "check", "build/wheelhouse/*") - session.run( - "twine", - "upload", - "--skip-existing", - "build/wheelhouse/*.tar.gz", - ) - - @nox.session(python=False) def clean(session): """Remove all .venv's, build files and caches in the directory.""" @@ -143,3 +126,19 @@ def _clean_rglob(pattern): p.rmdir() else: p.unlink() + + +def _install_from_path(session: nox.Session, path: str | None = None) -> None: + if path is None: + session.install("-e", ".") + elif os.path.isfile(path): + session.install(path) + elif os.path.isdir(path): + session.install( + "--force-reinstall", + "bmipy", + f"--find-links={path}", + "--no-index", + ) + else: + session.error("path must be a source distribution or folder") diff --git a/pyproject.toml b/pyproject.toml index b2fc547..a24bf20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,10 @@ where = [ [tool.coverage.run] relative_files = true +source = ["bmipy", "tests"] + +[tool.coverage.paths] +source = ["src/bmipy", "*/site-packages/bmipy"] [tool.isort] known_first_party = "bmipy"