Skip to content

Commit

Permalink
Actions, Hynek-style.
Browse files Browse the repository at this point in the history
  • Loading branch information
ubernostrum committed Sep 26, 2024
1 parent ec0702e commit d62d16e
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 32 deletions.
191 changes: 167 additions & 24 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,193 @@ name: CI

on:
push:
branches: [trunk]
tags: ["*"]
branches: [main]
pull_request:
branches: [trunk]
workflow_dispatch:

env:
FORCE_COLOR: "1"
PIP_DISABLE_VERSION_CHECK: "1"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
PIP_NO_PYTHON_VERSION_WARNING: "1"

permissions:
contents: read
permissions: {}

jobs:
tests:
name: nox on ${{ matrix.python-version }}
build-package:
name: Build and verify package
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: hynek/build-and-inspect-python-package@v2
id: baipp

outputs:
python-versions: ${{ steps.baipp.outputs.supported_python_classifiers_json_array }}

tests:
name: Tests on ${{ matrix.python-version }}
needs: build-package
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ${{ fromJson(needs.build-package.outputs.python-versions) }}

steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
docs.python.org:443
files.pythonhosted.org:443
github.com:443
pypi.org:443
- uses: actions/checkout@v4
- name: Download pre-built packages
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- run: tar xf dist/*.tar.gz --strip-components=1
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: "Install dependencies"
allow-prereleases: true
- name: Install test runner
run: |
python -VV
python -Im site
python -Im pip install --upgrade pip setuptools wheel
python -Im pip install --upgrade nox
python -Im nox --version
- name: "Run CI suite with nox"
run: "python -Im nox --non-interactive --error-on-external-run --python ${{ matrix.python-version }}"
- name: Run tests
run: "python -Im nox --non-interactive --error-on-external-run --tag tests --python ${{ matrix.python-version }}"
- name: Upload coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-${{ matrix.python-version }}
path: .coverage.*
include-hidden-files: true
if-no-files-found: ignore


coverage:
name: Combine and check coverage
needs: tests
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: hynek/setup-cached-uv@v2
- run: python -Im pip install --system --upgrade coverage[toml]
- uses: actions/download-artifact@v4
with:
pattern: coverage-data-*
merge-multiple: true

- name: Combine coverage and fail under 100%
run: |
python -Im pip install --upgrade "coverage[toml]"
coverage combine
coverage html --skip-covered --skip-empty
# Report and write to summary.
coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
# Report again and fail if under 100%.
coverage report --fail-under=100
- name: Upload HTML report if check failed.
uses: actions/upload-artifact@v4
with:
name: html-report
path: htmlcov
if: ${{ failure() }}


docs:
name: Check documentation
needs: build-package
runs-on: ubuntu-latest
steps:
- name: Download pre-built packages
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- run: tar xf dist/*.tar.gz --strip-components=1
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up test runner
- run: |
python -VV
python -Im site
python -Im pip install --upgrade nox
python -Im nox --version
- name: Run documentation checks
run: "python -Im nox --non-interactive --error-on-external-run --tag docs"


lint-format:
name: Lint code and check formatting
needs: build-package
runs-on: ubuntu-latest
steps:
- name: Download pre-built packages
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- run: tar xf dist/*.tar.gz --strip-components=1
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up test runner
- run: |
python -VV
python -Im site
python -Im pip install --upgrade nox
python -Im nox --version
- name: Check code formatting
run: "python -Im nox --non-interactive --error-on-external-run --tag formatters --python 3.12"
- name: Lint code
run: "python -Im nox --non-interactive --error-on-external-run --tag linters --python 3.12"


check-package:
name: Additional package checks
needs: build-package
runs-on: ubuntu-latest
steps:
- name: Download pre-built packages
uses: actions/download-artifact@v4
with:
name: Packages
path: dist
- run: tar xf dist/*.tar.gz --strip-components=1
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up test runner
- run: |
python -VV
python -Im site
python -Im pip install --upgrade nox
python -Im nox --version
- name: Check package
run: "python -Im nox --non-interactive --error-on-external-run --tag packaging --python 3.12"


required-checks-pass:
name: Ensure required checks pass for branch protection
if: always()

needs:
- check-package
- coverage
- docs
- lint-format

runs-on: ubuntu-latest

steps:
- name: Decide whether the jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
35 changes: 27 additions & 8 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

PACKAGE_NAME = "webcolors"

IS_CI = bool(os.getenv("CI", False))

NOXFILE_PATH = pathlib.Path(__file__).parents[0]
ARTIFACT_PATHS = (
NOXFILE_PATH / "src" / f"{PACKAGE_NAME}.egg-info",
Expand All @@ -41,6 +43,10 @@ def clean(paths: typing.Iterable[os.PathLike] = ARTIFACT_PATHS) -> None:
Clean up after a test run.
"""
# This cleanup is only useful for the working directory of a local checkout; in CI
# we don't need it because CI environments are ephemeral anyway.
if IS_CI:
return
[
shutil.rmtree(path) if path.is_dir() else path.unlink()
for path in paths
Expand All @@ -55,7 +61,7 @@ def clean(paths: typing.Iterable[os.PathLike] = ARTIFACT_PATHS) -> None:
@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12"], tags=["tests"])
def tests_with_coverage(session: nox.Session) -> None:
"""
Run the package's unit tests, with coverage report.
Run the package's unit tests, with coverage instrumentation.
"""
session.install(".[tests]")
Expand All @@ -71,14 +77,27 @@ def tests_with_coverage(session: nox.Session) -> None:
"unittest",
"discover",
)
clean()


@nox.session(python=["3.12"], tags=["tests"])
def coverage_report(session: nox.Session) -> None:
"""
Combine coverage from the various test runs and output the report.
"""
# In CI this job does not run because we substitute one that integrates with the CI
# system.
if IS_CI:
session.skip(
"Running in CI -- skipping nox coverage job in favor of CI coverage job"
)
session.install("coverage[toml]")
session.run(f"python{session.python}", "-Im", "coverage", "combine")
session.run(
f"python{session.python}",
"-Im",
"coverage",
"report",
"--show-missing",
f"python{session.python}", "-Im", "coverage", "report", "--show-missing"
)
clean()
session.run(f"python{session.python}", "-Im", "coverage", "erase")


@nox.session(python=["3.12"], tags=["tests", "release"])
Expand Down Expand Up @@ -185,7 +204,7 @@ def docs_spellcheck(session: nox.Session) -> None:
clean()


@nox.session(python=["3.11"], tags=["docs", "tests"])
@nox.session(python=["3.12"], tags=["docs", "tests"])
def docs_test(session: nox.Session) -> None:
"""
Run the code samples in the documentation with doctest, to ensure they are
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ target-version = ["py38", "py39", "py310", "py311", "py312"]
[tool.coverage.report]
fail_under = 100

[tool.coverage.run]
parallel = true

[tool.interrogate]
ignore-init-module = true

Expand Down

0 comments on commit d62d16e

Please sign in to comment.