Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow constraining linter versions in GitHub Action configuration #349

Merged
merged 2 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Added
-----
- The ``--jobs`` option now specifies how many Darker jobs are used to process files in
parallel to complete reformatting/linting faster.
- Linters can now be run in the GitHub Action using the ``lint:`` option.
- Linters can now be installed and run in the GitHub Action using the ``lint:`` option.

Fixed
-----
Expand Down
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ Create a file named ``.github/workflows/darker.yml`` inside your repository with
revision: "master..."
src: "./src"
version: "1.4.2"
lint: "flake8,pylint"
lint: "flake8,pylint==2.13.1"

There needs to be a working Python environment, set up using ``actions/setup-python``
in the above example. Darker will be installed in an isolated virtualenv to prevent
Expand Down Expand Up @@ -603,6 +603,7 @@ You can e.g. add ``"--isort"`` to sort imports, or ``"--verbose"`` for debug log

To run linters through Darker, you can provide a comma separated list of linters using
the ``lint:`` option. Only ``flake8``, ``pylint`` and ``mypy`` are supported.
Versions can be constrained using ``pip`` syntax, e.g. ``"flake8>=3.9.2"``.

*New in version 1.1.0:*
GitHub Actions integration. Modeled after how Black_ does it,
Expand Down
3 changes: 2 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ inputs:
lint:
description: >-
Comma-separated list of linters to `pip install` and run from Darker.
Example: flake8,pylint
Optionally, version constraints (using pip syntax) can be specified.
Example: flake8,pylint==2.13.1
required: false
default: ''
branding:
Expand Down
11 changes: 6 additions & 5 deletions action/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
from pathlib import Path
from subprocess import PIPE, STDOUT, run # nosec

from pkg_resources import parse_requirements

LINTER_WHITELIST = {"flake8", "pylint", "mypy"}
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
ENV_PATH = ACTION_PATH / ".darker-env"
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
SRC = os.getenv("INPUT_SRC", default="")
VERSION = os.getenv("INPUT_VERSION", default="")
LINT = os.getenv("INPUT_LINT", default="")
REVISION = os.getenv(
"INPUT_REVISION", default=os.getenv("INPUT_COMMIT_RANGE", default="HEAD^")
)
Expand All @@ -21,15 +24,13 @@
if VERSION:
req[0] += f"=={VERSION}"
linter_options = []
for linter_ in os.getenv("INPUT_LINT", default="").split(","):
linter = linter_.strip()
if not linter:
continue
for linter_requirement in parse_requirements(LINT.replace(",", "\n")):
linter = linter_requirement.name
if linter not in LINTER_WHITELIST:
raise RuntimeError(
f"{linter!r} is not supported as a linter by the GitHub Action"
)
req.append(linter)
req.append(str(linter_requirement))
linter_options.extend(["--lint", linter])

pip_proc = run( # nosec
Expand Down
10 changes: 9 additions & 1 deletion action/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ def test_creates_virtualenv(tmp_path, main_patch):
run_main_env={"INPUT_LINT": " flake8 , pylint "},
expect=["darker[isort]", "flake8", "pylint"],
),
dict(
run_main_env={"INPUT_LINT": " flake8 >= 3.9.2 , pylint == 2.13.1 "},
expect=["darker[isort]", "flake8>=3.9.2", "pylint==2.13.1"],
),
)
def test_installs_packages(tmp_path, main_patch, run_main_env, expect):
"""Darker, isort and linters are installed in the virtualenv using pip"""
Expand All @@ -126,7 +130,7 @@ def test_installs_packages(tmp_path, main_patch, run_main_env, expect):


@pytest.mark.parametrize(
"linters", ["foo", " foo ", "foo,bar", " foo , bar ", "pylint,foo"]
"linters", ["foo", " foo ", "foo==2.0,bar", " foo>1.0 , bar ", "pylint,foo"]
)
def test_wont_install_unknown_packages(tmp_path, linters):
"""Non-whitelisted linters raise an exception"""
Expand Down Expand Up @@ -173,6 +177,10 @@ def test_wont_install_unknown_packages(tmp_path, linters):
env={"INPUT_SRC": ".", "INPUT_LINT": "pylint,flake8"},
expect=["--lint", "pylint", "--lint", "flake8", "--revision", "HEAD^", "."],
),
dict(
env={"INPUT_SRC": ".", "INPUT_LINT": "pylint == 2.13.1,flake8>=3.9.2"},
expect=["--lint", "pylint", "--lint", "flake8", "--revision", "HEAD^", "."],
),
dict(
env={
"INPUT_SRC": "here.py there/too",
Expand Down