Skip to content

Commit

Permalink
ci: Replace tox with nox (#780)
Browse files Browse the repository at this point in the history
* ci: Replace tox with nox

* Use color in all jobs

* environments -> sessions

* Move tool config out of tox.ini
  • Loading branch information
edgarrmondragon authored Jul 1, 2022
1 parent b5968a7 commit 6e3b0bc
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 166 deletions.
16 changes: 16 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[flake8]
ignore = W503, C901, ANN101
max-line-length = 88
exclude = cookiecutter
per-file-ignores =
# Don't require docstrings or type annotations in tests
# tests/*:D100,D102,D103,DAR,ANN
# Don't require docstrings conventions or type annotations in SDK samples
# samples/*:ANN,DAR
# Don't require docstrings conventions or type annotations in private modules
singer_sdk/helpers/_*.py:ANN,DAR,D105
# Don't require docstrings conventions in "meta" code
# singer_sdk/helpers/_classproperty.py:D105
max-complexity = 10
docstring-convention = google
allow-star-arg-any = true
2 changes: 2 additions & 0 deletions .github/workflows/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ pip==22.1.2
poetry==1.1.13
virtualenv==20.15.1
changelog-cli==0.7.1
nox==2022.1.7
nox-poetry==1.0.1
69 changes: 43 additions & 26 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ on:
workflow_dispatch:
inputs: {}

env:
FORCE_COLOR: "1"

jobs:
tests:
name: Test on ${{ matrix.python-version }} (${{ matrix.tox-env }}) / ${{ matrix.os }}
name: Test on ${{ matrix.python-version }} (${{ matrix.session }}) / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
NOXSESSION: ${{ matrix.session }}
strategy:
fail-fast: false
matrix:
include:
- { tox-env: py, python-version: "3.7", os: "ubuntu-latest" }
- { tox-env: py, python-version: "3.8", os: "ubuntu-latest" }
- { tox-env: py, python-version: "3.9", os: "ubuntu-latest" }
- { tox-env: py, python-version: "3.10", os: "ubuntu-latest" }
- { tox-env: doctest, python-version: "3.10", os: "ubuntu-latest" }
- { tox-env: mypy, python-version: "3.8", os: "ubuntu-latest" }
- { session: tests, python-version: "3.7", os: "ubuntu-latest" }
- { session: tests, python-version: "3.8", os: "ubuntu-latest" }
- { session: tests, python-version: "3.9", os: "ubuntu-latest" }
- { session: tests, python-version: "3.10", os: "ubuntu-latest" }
- { session: doctest, python-version: "3.10", os: "ubuntu-latest" }
- { session: mypy, python-version: "3.8", os: "ubuntu-latest" }

steps:
- name: Check out the repository
Expand All @@ -39,7 +44,8 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
architecture: x64
cache: 'poetry'
cache: 'pip'
cache-dependency-path: 'poetry.lock'

- name: Upgrade pip
env:
Expand All @@ -48,17 +54,20 @@ jobs:
pip install pip
pip --version
- name: Install Dependencies
- name: Install Nox
env:
PIP_CONSTRAINT: .github/workflows/constraints.txt
run: |
poetry env use "${{ matrix.python-version }}"
poetry install
pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox
pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry
nox --version
- name: Run tox
- name: Run Nox
run: |
poetry run tox -e ${{ matrix.tox-env }} --${{ matrix.doctest && ' --doctest-modules singer_sdk' }}
nox --python=${{ matrix.python-version }}
- name: Upload coverage data
if: always() && (matrix.tox-env == 'py')
if: always() && (matrix.session == 'tests')
uses: actions/[email protected]
with:
name: coverage-data
Expand Down Expand Up @@ -93,7 +102,8 @@ jobs:
with:
python-version: '3.10'
architecture: x64
cache: 'poetry'
cache: 'pip'
cache-dependency-path: 'poetry.lock'

- name: Upgrade pip
env:
Expand All @@ -102,14 +112,17 @@ jobs:
pip install pip
pip --version
- name: Install Dependencies
- name: Install Nox
env:
PIP_CONSTRAINT: .github/workflows/constraints.txt
run: |
poetry env use "3.10"
poetry install
pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox
pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry
nox --version
- name: Run tox
- name: Run Nox
run: |
poetry run tox -e py -- -m "external"
nox -s tests -p 3.10 -- -m "external"
coverage:
name: Coverage
Expand All @@ -128,7 +141,8 @@ jobs:
uses: actions/[email protected]
with:
python-version: '3.10'
cache: 'poetry'
cache: 'pip'
cache-dependency-path: 'poetry.lock'

- name: Upgrade pip
run: |
Expand All @@ -140,18 +154,21 @@ jobs:
with:
name: coverage-data

- name: Install Dependencies
- name: Install Nox
env:
PIP_CONSTRAINT: .github/workflows/constraints.txt
run: |
poetry env use "3.10"
poetry install
pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox
pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry
nox --version
- name: Combine coverage data and display human readable report
run: |
poetry run tox -e combine_coverage
nox --session=coverage
- name: Create coverage report
run: |
poetry run tox -e coverage_artifact -- xml
nox --session=coverage -- xml
- name: Upload coverage report
uses: codecov/[email protected]
27 changes: 11 additions & 16 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Contributors are expected to follow our [Code of Conduct](https://docs.meltano.c
## Setting up Prereqs

Make sure [`poetry`](https://python-poetry.org/docs/),
[`pre-commit`](https://pre-commit.com/) and [`tox`](https://tox.wiki/en/latest/)
[`pre-commit`](https://pre-commit.com/) and [`nox`](https://nox.thea.codes/en/stable/)
are installed. You can use [`pipx`](https://pypa.github.io/pipx/) to install
all of them. To install `pipx`:

Expand All @@ -29,7 +29,8 @@ With `pipx` installed, you globally add the required tools:
```bash
pipx install poetry
pipx install pre-commit
pipx install tox
pipx install nox
pipx install nox-poetry
```

Now you can use Poetry to install package dependencies:
Expand All @@ -55,18 +56,18 @@ First clone, then...
- `poetry install -E docs`
1. The project has `pre-commit` hooks. Install them with:
- `pre-commit install`
1. Most development tasks you might need should be covered by `tox` environments. You can use `tox -l` to list all available tasks.
1. Most development tasks you might need should be covered by `nox` sessions. You can use `nox -l` to list all available tasks.
For example:

- Run unit tests: `tox -e py`.
- Run unit tests: `nox -r`.

We use `coverage` for code coverage metrics.

- Run pre-commit hooks: `tox -e pre-commit`.
- Run pre-commit hooks: `pre-commit run --all`.

We use `black`, `flake8`, `isort`, `mypy` and `pyupgrade`. The project-wide max line length is `88`.

- Build documentation: `tox -e docs`
- Build documentation: `nox -rs docs`

We use `sphinx` to build documentation.

Expand All @@ -84,22 +85,16 @@ To run tests:

```bash
# Run just the core and cookiecutter tests (no external creds required):
tox -e py
nox -rs tests

# Run all tests (external creds required):
tox -e py -- -m "external"
```

To gather and display coverage metrics:

```bash
tox -e combine_coverage
nox -rs tests -- -m "external"
```

To view the code coverage report in HTML format:

```bash
tox -e coverage_artifact -- html && open ./htmlcov/index.html
nox -rs coverage -- html && open ./htmlcov/index.html
```

## Testing Updates to Docs
Expand All @@ -113,7 +108,7 @@ To build the docs:

```bash
# Build docs
tox -e docs
nox -rs docs

# Open in the local browser:
open build/index.html
Expand Down
128 changes: 128 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""Nox configuration."""

from __future__ import annotations

import os
import shutil
import sys
from pathlib import Path
from textwrap import dedent

import nox

try:
from nox_poetry import Session, session
except ImportError:
message = f"""\
Nox failed to import the 'nox-poetry' package.
Please install it using the following command:
{sys.executable} -m pip install nox-poetry"""
raise SystemExit(dedent(message)) from None

package = "singer_sdk"
python_versions = ["3.10", "3.9", "3.8", "3.7"]
main_python_version = "3.10"
locations = "singer_sdk", "tests", "noxfile.py", "docs/conf.py"
nox.options.sessions = (
"mypy",
"tests",
"doctest",
)


@session(python=python_versions)
def mypy(session: Session) -> None:
"""Check types with mypy."""
args = session.posargs or ["singer_sdk"]
session.install(".")
session.install(
"mypy",
"sqlalchemy2-stubs",
"types-python-dateutil",
"types-requests",
)
session.run("mypy", *args)
if not session.posargs:
session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py")


@session(python=python_versions)
def tests(session: Session) -> None:
"""Execute pytest tests and compute coverage."""
session.install(".")
session.install(
"coverage[toml]",
"pytest",
"freezegun",
"pandas",
"pyarrow",
"requests-mock",
# Cookiecutter tests
"black",
"cookiecutter",
"PyYAML",
"darglint",
"flake8",
"flake8-annotations",
"flake8-docstrings",
"mypy",
)

try:
session.run(
"coverage",
"run",
"--parallel",
"-m",
"pytest",
"-x",
"-v",
*session.posargs,
)
finally:
if session.interactive:
session.notify("coverage", posargs=[])


@session(python=python_versions)
def doctest(session: Session) -> None:
"""Run examples with xdoctest."""
if session.posargs:
args = [package, *session.posargs]
else:
args = [package]
if "FORCE_COLOR" in os.environ:
args.append("--xdoctest-colored=1")

session.install(".")
session.install("pytest", "xdoctest[colors]")
session.run("pytest", "--xdoctest", *args)


@session(python=main_python_version)
def coverage(session: Session) -> None:
"""Generate coverage report."""
args = session.posargs or ["report"]

session.install("coverage[toml]")

if not session.posargs and any(Path().glob(".coverage.*")):
session.run("coverage", "combine")

session.run("coverage", *args)


@session(name="docs", python=main_python_version)
def docs(session: Session) -> None:
"""Build the documentation."""
args = session.posargs or ["docs", "build", "-W"]
if not session.posargs and "FORCE_COLOR" in os.environ:
args.insert(0, "--color")

session.install(".[docs]")

build_dir = Path("build")
if build_dir.exists():
shutil.rmtree(build_dir)

session.run("sphinx-build", *args)
Loading

0 comments on commit 6e3b0bc

Please sign in to comment.