diff --git a/.github/workflows/reusable-nox.yml b/.github/workflows/reusable-nox.yml index bf8ac66ab7..2f8b8a9290 100644 --- a/.github/workflows/reusable-nox.yml +++ b/.github/workflows/reusable-nox.yml @@ -23,6 +23,8 @@ jobs: python-versions: "3.11" - session: "checkers(docs-build)" python-versions: "3.11" + - session: "actionlint" + python-versions: "3.11" name: "Run nox ${{ matrix.session }} session" steps: - name: Check out repo diff --git a/README.md b/README.md index 9ec6cd5a5b..2712aabf09 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,11 @@ The `nox` configuration also contains session to run automated docs checkers. nox -s lint ``` + The `actionlint` linter that is run as part of the `lint` session requires + `podman` or `docker` to be installed. + If both container engines are installed, `podman` is preferred. + Set `CONTAINER_ENGINE=docker` to change this behavior. + ### Checking spelling Use [`codespell`](https://github.com/codespell-project/codespell) to check for common spelling mistakes in the documentation source. diff --git a/noxfile.py b/noxfile.py index 491c700d63..5961a5b132 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,6 +2,7 @@ from __future__ import annotations import os import shlex +import shutil from argparse import ArgumentParser, BooleanOptionalAction from glob import iglob from pathlib import Path @@ -45,6 +46,29 @@ def install(session: nox.Session, *args, req: str, **kwargs): session.install("-r", f"tests/{req}.in", *args, **kwargs) +CONTAINER_ENGINES = ("podman", "docker") +CHOSEN_CONTAINER_ENGINE = os.environ.get("CONTAINER_ENGINE") +ACTIONLINT_IMAGE = "docker.io/rhysd/actionlint" + + +def _get_container_engine(session: nox.Session) -> str: + path: str | None = None + if CHOSEN_CONTAINER_ENGINE: + path = shutil.which(CHOSEN_CONTAINER_ENGINE) + if not path: + session.error( + f"CONTAINER_ENGINE {CHOSEN_CONTAINER_ENGINE!r} does not exist!" + ) + return path + for engine in CONTAINER_ENGINES: + if path := shutil.which(engine): + return path + session.error( + f"None of the following container engines were found: {CONTAINER_ENGINES}." + f" {session.name} requires a container engine installed." + ) + + @nox.session def static(session: nox.Session): """ @@ -93,12 +117,37 @@ def spelling(session: nox.Session): ) +@nox.session +def actionlint(session: nox.Session) -> None: + """ + Run actionlint to lint Github Actions workflows. + The actionlint tool is run in a Podman/Docker container. + """ + engine = _get_container_engine(session) + session.run_always(engine, "pull", ACTIONLINT_IMAGE, external=True) + session.run( + engine, + "run", + "--rm", + # fmt: off + "--volume", f"{Path.cwd()}:/pwd:z", + "--workdir", "/pwd", + # fmt: on + ACTIONLINT_IMAGE, + # Disable shellcheck for now + "-shellcheck=", + *session.posargs, + external=True, + ) + + @nox.session def lint(session: nox.Session): session.notify("typing") session.notify("static") session.notify("formatters") session.notify("spelling") + session.notify("actionlint") requirements_files = list(