Skip to content

Commit

Permalink
Attempt to update GitHub Actions to new approach.
Browse files Browse the repository at this point in the history
This synchronizes the GH Actions setup to what I'm using in a couple
other projects, and also fixes some errors that crept into the previous
commits setting up PDM usage -- it *seems* like PDM is not actually
needed, which is good because it was messing with the installed Django
versions.
  • Loading branch information
ubernostrum committed Oct 31, 2024
1 parent 249a8ca commit 562efcc
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 86 deletions.
182 changes: 166 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,193 @@ name: CI
on:
push:
branches: [trunk]
tags: ["*"]
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 Python ${{ matrix.python-version }}
needs: build-package
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ${{ fromJson(needs.build-package.outputs.python-versions) }}

steps:
- 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: Set up PDM
uses: pdm-project/setup-pdm@v4
allow-prereleases: true
- name: Install test runner
run: |
python -VV
python -Im site
python -Im pip install --upgrade nox
python -Im nox --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:
python-version: ${{ matrix.python-version }}
- name: "Install dependencies"
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: actions/download-artifact@v4
with:
pattern: coverage-data-*
merge-multiple: true

- name: Combine coverage & 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.13"
- name: Lint code
run: "python -Im nox --non-interactive --error-on-external-run --tag linters --python 3.13"


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 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 --python ${{ matrix.python-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) }}
61 changes: 36 additions & 25 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
nox.options.default_venv_backend = "venv"
nox.options.reuse_existing_virtualenvs = True

os.environ.update({"PDM_IGNORE_SAVED_PYTHON": "1"})

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

NOXFILE_PATH = pathlib.Path(__file__).parents[0]
Expand Down Expand Up @@ -73,8 +72,7 @@ def tests_with_coverage(session: nox.Session, django: str) -> None:
Run the package's unit tests, with coverage report.
"""
session.install(f"Django~={django}.0")
session.run_always("pdm", "install", "-dG", "tests", external=True)
session.install(f"Django~={django}.0", ".[tests]")
python_version = session.run(
f"{session.bin}/python{session.python}", "--version", silent=True
).strip()
Expand All @@ -98,27 +96,40 @@ def tests_with_coverage(session: nox.Session, django: str) -> None:
"runtests.py",
env={"DJANGO_SETTINGS_MODULE": "tests.settings"},
)
clean()


@nox.session(python=["3.13"], 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"{session.bin}/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")


# Tasks which test the package's documentation.
# -----------------------------------------------------------------------------------


@nox.session(python=["3.12"], tags=["docs"])
@nox.session(python=["3.13"], tags=["docs"])
def docs_build(session: nox.Session) -> None:
"""
Build the package's documentation as HTML.
"""
session.run_always("pdm", "install", "-dG", "docs", external=True)
session.install(".[docs]")
build_dir = session.create_tmp()
session.run(
f"{session.bin}/python{session.python}",
Expand All @@ -137,7 +148,7 @@ def docs_build(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["docs"])
@nox.session(python=["3.13"], tags=["docs"])
def docs_docstrings(session: nox.Session) -> None:
"""
Enforce the presence of docstrings on all modules, classes, functions, and
Expand All @@ -160,13 +171,13 @@ def docs_docstrings(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["docs"])
@nox.session(python=["3.13"], tags=["docs"])
def docs_spellcheck(session: nox.Session) -> None:
"""
Spell-check the package's documentation.
"""
session.run_always("pdm", "install", "-dG", "docs", external=True)
session.install(".[docs]")
session.install("pyenchant", "sphinxcontrib-spelling")
build_dir = session.create_tmp()
session.run(
Expand Down Expand Up @@ -197,7 +208,7 @@ def docs_spellcheck(session: nox.Session) -> None:
# -----------------------------------------------------------------------------------


@nox.session(python=["3.12"], tags=["formatters"])
@nox.session(python=["3.13"], tags=["formatters"])
def format_black(session: nox.Session) -> None:
"""
Check code formatting with Black.
Expand All @@ -219,7 +230,7 @@ def format_black(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["formatters"])
@nox.session(python=["3.13"], tags=["formatters"])
def format_isort(session: nox.Session) -> None:
"""
Check code formating with Black.
Expand All @@ -245,7 +256,7 @@ def format_isort(session: nox.Session) -> None:
# -----------------------------------------------------------------------------------


@nox.session(python=["3.12"], tags=["linters", "security"])
@nox.session(python=["3.13"], tags=["linters", "security"])
def lint_bandit(session: nox.Session) -> None:
"""
Lint code with the Bandit security analyzer.
Expand All @@ -266,7 +277,7 @@ def lint_bandit(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["linters"])
@nox.session(python=["3.13"], tags=["linters"])
def lint_flake8(session: nox.Session) -> None:
"""
Lint code with flake8.
Expand All @@ -286,7 +297,7 @@ def lint_flake8(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["linters"])
@nox.session(python=["3.13"], tags=["linters"])
def lint_pylint(session: nox.Session) -> None:
"""
Lint code with Pylint.
Expand All @@ -305,7 +316,7 @@ def lint_pylint(session: nox.Session) -> None:
# -----------------------------------------------------------------------------------


@nox.session(python=["3.12"], tags=["packaging"])
@nox.session(python=["3.13"], tags=["packaging"])
def package_build(session: nox.Session) -> None:
"""
Check that the package builds.
Expand All @@ -317,7 +328,7 @@ def package_build(session: nox.Session) -> None:
session.run(f"{session.bin}/python{session.python}", "-Im", "build")


@nox.session(python=["3.12"], tags=["packaging"])
@nox.session(python=["3.13"], tags=["packaging"])
def package_description(session: nox.Session) -> None:
"""
Check that the package description will render on the Python Package Index.
Expand Down Expand Up @@ -345,7 +356,7 @@ def package_description(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["packaging"])
@nox.session(python=["3.13"], tags=["packaging"])
def package_manifest(session: nox.Session) -> None:
"""
Check that the set of files in the package matches the set under version
Expand All @@ -362,7 +373,7 @@ def package_manifest(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["packaging"])
@nox.session(python=["3.13"], tags=["packaging"])
def package_pyroma(session: nox.Session) -> None:
"""
Check package quality with pyroma.
Expand All @@ -378,7 +389,7 @@ def package_pyroma(session: nox.Session) -> None:
clean()


@nox.session(python=["3.12"], tags=["packaging"])
@nox.session(python=["3.13"], tags=["packaging"])
def package_wheel(session: nox.Session) -> None:
"""
Check the built wheel package for common errors.
Expand Down
Loading

0 comments on commit 562efcc

Please sign in to comment.