nox: add actionlint to lint Github Actions workflows

This PR integrates [actionlint](https://github.com/rhysd/actionlint)
into our CI pipeline to check our Github Actions for best practices and
common errors.
This commit is contained in:
Maxwell G
2024-09-09 16:42:58 -05:00
parent 7138e42716
commit 107a3c4383
3 changed files with 56 additions and 0 deletions

View File

@@ -23,6 +23,8 @@ jobs:
python-versions: "3.11" python-versions: "3.11"
- session: "checkers(docs-build)" - session: "checkers(docs-build)"
python-versions: "3.11" python-versions: "3.11"
- session: "actionlint"
python-versions: "3.11"
name: "Run nox ${{ matrix.session }} session" name: "Run nox ${{ matrix.session }} session"
steps: steps:
- name: Check out repo - name: Check out repo

View File

@@ -79,6 +79,11 @@ The `nox` configuration also contains session to run automated docs checkers.
nox -s lint 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 ### Checking spelling
Use [`codespell`](https://github.com/codespell-project/codespell) to check for common spelling mistakes in the documentation source. Use [`codespell`](https://github.com/codespell-project/codespell) to check for common spelling mistakes in the documentation source.

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import os import os
import shlex import shlex
import shutil
from argparse import ArgumentParser, BooleanOptionalAction from argparse import ArgumentParser, BooleanOptionalAction
from glob import iglob from glob import iglob
from pathlib import Path 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) 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 @nox.session
def static(session: 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 @nox.session
def lint(session: nox.Session): def lint(session: nox.Session):
session.notify("typing") session.notify("typing")
session.notify("static") session.notify("static")
session.notify("formatters") session.notify("formatters")
session.notify("spelling") session.notify("spelling")
session.notify("actionlint")
requirements_files = list( requirements_files = list(