diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 5479305d7..126939d9c 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -4,7 +4,7 @@ name: Security check - Bandit on: push # yamllint disable-line rule:truthy jobs: - build: + bandit: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 000000000..6a5bbf0fe --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,12 @@ +--- +name: codespell + +on: push # yamllint disable-line rule:truthy + +jobs: + codespell: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml new file mode 100644 index 000000000..9198446dd --- /dev/null +++ b/.github/workflows/flake8.yml @@ -0,0 +1,17 @@ +--- +name: Flake8 + +on: push # yamllint disable-line rule:truthy + +jobs: + flake8: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: TrueBrain/actions-flake8@v2 + with: + plugins: > + flake8-2020>=1.6.1 + flake8-bugbear>=22.1.11 + flake8-comprehensions>=3.7.0 diff --git a/.github/workflows/isort.yml b/.github/workflows/isort.yml new file mode 100644 index 000000000..241a17507 --- /dev/null +++ b/.github/workflows/isort.yml @@ -0,0 +1,18 @@ +--- +name: isort + +on: push # yamllint disable-line rule:truthy + +jobs: + isort: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install 'isort>=5.0.1' + - uses: wearerequired/lint-action@v2.0.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + isort: true + continue_on_error: false diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml new file mode 100644 index 000000000..758b4b00c --- /dev/null +++ b/.github/workflows/mypy.yml @@ -0,0 +1,19 @@ +--- +name: mypy + +on: push # yamllint disable-line rule:truthy + +jobs: + mypy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install -U isort mypy pytest types-toml + - uses: wearerequired/lint-action@v2.0.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + mypy: true + mypy_args: "src" + continue_on_error: false diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 000000000..2e4419f24 --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,18 @@ +--- +name: pylint + +on: push # yamllint disable-line rule:truthy + +jobs: + pylint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install pylint + - uses: wearerequired/lint-action@v2.0.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + pylint: true + continue_on_error: false diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 80701edf3..bf7bda87e 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -1,5 +1,5 @@ --- -name: build +name: Build and test on: # yamllint disable-line rule:truthy push: @@ -12,6 +12,34 @@ on: # yamllint disable-line rule:truthy jobs: + build-wheel: + runs-on: ubuntu-latest + outputs: + wheel-path: ${{ steps.get-darker-version.outputs.wheel-path }} + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Install wheel + run: python -m pip install wheel + - name: Build wheel distribution + run: python setup.py bdist_wheel + - name: Upload wheel for other jobs + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist/ + if-no-files-found: error + - name: Find out Darker version and output it for test jobs + id: get-darker-version + shell: python + run: | + from runpy import run_path + version = run_path("src/darker/version.py")["__version__"] + print( + "::set-output name=wheel-path::" + f"dist/darker-{version}-py3-none-any.whl" + ) + test-nixos: runs-on: ${{ matrix.os }} strategy: @@ -23,13 +51,15 @@ jobs: - os: macos-latest python-version: python39 # see https://github.com/cachix/install-nix-action/issues/135 + needs: + - build-wheel steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - uses: cachix/install-nix-action@v17 with: nix_path: nixpkgs=channel:nixos-21.11 + - name: Download wheel uploaded by the build-wheel job + uses: actions/download-artifact@v3 - name: Run tests in nix-shell run: | nix-shell \ @@ -38,13 +68,12 @@ jobs: --run ' python -m venv venv source venv/bin/activate - pip install -e '.[isort,test]' + pip install "${{needs.build-wheel.outputs.wheel-path}}[test]" pytest ' \ ./default.nix - build: - + test: runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -59,7 +88,6 @@ jobs: - '3.9' - '3.10' constraints: [''] - lint: ['--darker --flake8 --isort'] include: - os: ubuntu-latest python-version: '3.7' @@ -68,71 +96,40 @@ jobs: python-version: '3.10' constraints: '--constraint constraints-future.txt' upgrade: '--upgrade --upgrade-strategy=eager' - env: - RUN_MYPY_AND_PYLINT: >- - ${{ matrix.python-version == '3.9' || matrix.python-version == '3.10' }} + needs: + - build-wheel steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - + # need full history since Pytest runs Darker itself below - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - - name: Upgrade pip, install wheel and twine - run: | - # strict dependency resolution added in pip 20.3 - python -m pip install --upgrade 'pip>=20.3' wheel twine - - name: Build source distribution - run: python setup.py sdist - - name: Build wheel distribution - run: python setup.py bdist_wheel - - name: Validate distributions - run: twine check dist/* - - name: Get Darker version - shell: python - run: | - from os import environ - from pathlib import Path - from runpy import run_path - version = run_path("src/darker/version.py")["__version__"] - Path(environ["GITHUB_ENV"]).write_text(f"VERSION={version}\n") - - name: Install Darker and its dependencies + - name: Download wheel uploaded by the build-wheel job + uses: actions/download-artifact@v3 + - name: Install Darker and its dependencies from the wheel build earlier env: pip_options: ${{ matrix.upgrade }} ${{ matrix.constraints }} run: pip install ${pip_options} - "dist/darker-${{ env.VERSION }}-py3-none-any.whl[isort,test]" - - name: Run Pytest without Mypy and Pylint if Python < 3.9 - if: env.RUN_MYPY_AND_PYLINT == 'false' + "${{needs.build-wheel.outputs.wheel-path}}[test]" + - name: Run Pytest run: | - pytest ${{ matrix.lint }} - - name: Run Pytest with Mypy and Pylint if Python >= 3.9 - if: env.RUN_MYPY_AND_PYLINT == 'true' - shell: python - run: | - import sys - from pathlib import Path - from subprocess import run - import toml + pytest --darker - data = toml.load("pyproject.toml") - data["tool"]["darker"]["lint"] = ["pylint", "mypy"] - Path("pyproject.toml").write_text(toml.dumps(data)) - pytest_cmd = ["pytest"] + "${{ matrix.lint }}".split() - retval = run(pytest_cmd).returncode - run(["git", "restore", "pyproject.toml"]) - sys.exit(retval) - - name: Check English spelling in the code base using codespell - run: codespell - - name: Ensure modern Python style using pyupgrade - # This script is written in a Linux / macos / windows portable way - run: | - python -c " - from pyupgrade._main import main - from glob import glob - files = glob('**/*.py', recursive=True) - main(files + ['--py37-plus']) - " - - name: Check dependencies for known security vulterabilities using Safety - run: safety check + build-sdist-validate-dists: + runs-on: ubuntu-latest + needs: + - build-wheel + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Install twine + run: python -m pip install twine + - name: Download wheel uploaded by the build-wheel job + uses: actions/download-artifact@v3 + - name: Build source distribution + run: python setup.py sdist + - name: Validate distributions + run: twine check dist/* diff --git a/.github/workflows/pyupgrade.yml b/.github/workflows/pyupgrade.yml new file mode 100644 index 000000000..408f4094f --- /dev/null +++ b/.github/workflows/pyupgrade.yml @@ -0,0 +1,23 @@ +--- +name: pyupgrade + +on: push # yamllint disable-line rule:truthy + +jobs: + pyupgrade: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install pyupgrade + - name: Ensure modern Python style using pyupgrade + # This script is written in a Linux / macos / windows portable way + run: | + python -c " + import sys + from pyupgrade._main import main + from glob import glob + files = glob('**/*.py', recursive=True) + sys.exit(main(files + ['--py37-plus'])) + " || ( git diff ; false ) diff --git a/.github/workflows/safety.yml b/.github/workflows/safety.yml new file mode 100644 index 000000000..da8b8ecc8 --- /dev/null +++ b/.github/workflows/safety.yml @@ -0,0 +1,15 @@ +--- +name: safety + +on: push # yamllint disable-line rule:truthy + +jobs: + safety: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install -U safety + - name: Check dependencies for known security vulnerabilities using Safety + run: safety check diff --git a/.github/workflows/test-future.yml b/.github/workflows/test-future.yml index 7dae08a7b..de64a670a 100644 --- a/.github/workflows/test-future.yml +++ b/.github/workflows/test-future.yml @@ -9,7 +9,7 @@ on: # yamllint disable-line rule:truthy - cron: "05 20 * * 6" jobs: - build: + test-future: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -27,7 +27,7 @@ jobs: --constraint=constraints-future.txt \ --upgrade \ --upgrade-strategy=eager \ - -e '.[isort,test]' + -e '.[test]' - name: Test with pytest run: | pytest diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index abd3fc96b..ba25d1bf3 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -6,7 +6,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: yaml-lint uses: ibiqlik/action-yamllint@v3 diff --git a/CHANGES.rst b/CHANGES.rst index 16e122b6b..5c36d3d75 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Added ----- - Add a CI workflow which verifies that the ``darker --help`` output in ``README.rst`` is up to date. +- Only run linters, security checks and package builds once in the CI build. Fixed ----- diff --git a/constraints-oldest.txt b/constraints-oldest.txt index 90ea502c9..b639e274e 100644 --- a/constraints-oldest.txt +++ b/constraints-oldest.txt @@ -4,25 +4,17 @@ # interpreter and Python ependencies. Keep this up-to-date with minimum # versions in `setup.cfg`. airium==0.2.3 -bandit==1.7.1 black==21.8b0 -codespell==2.1.0 defusedxml==0.7.1 flake8-2020==1.6.1 flake8-bugbear==22.1.11 flake8-comprehensions==3.7.0 -mypy==0.940 Pygments==2.4.0 -pylint==2.13.0 pytest==6.2.0 -pytest-flake8==1.0.6 -pytest-isort==1.1.0 pytest-kwparametrize==0.0.3 -pyupgrade==2.31.0 regex==2021.4.4 requests_cache==0.7 ruamel.yaml==0.17.21 -safety==1.10.3 toml==0.10.0 twine==2.0.0 types-toml==0.10.4 diff --git a/pyproject.toml b/pyproject.toml index 23d5b00af..5e49fb85a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,3 @@ src = [ "src", ] revision = "origin/master..." -# The empty linter list is here so `.github/workflows/python-package.yml` can -# add Pylint in certain run configurations: -lint = [] diff --git a/setup.cfg b/setup.cfg index af22cd34c..b4b4c5b63 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,28 +51,16 @@ color = test = # NOTE: remember to keep `constraints-oldest.txt` in sync with these airium>=0.2.3 - bandit>=1.7.1 black>=21.7b1 # to prevent Mypy error about `gen_python_files`, see issue #189 - codespell>=2.1.0 defusedxml>=0.7.1 - flake8<4 - flake8-2020>=1.6.1 - flake8-bugbear>=22.1.11 - flake8-comprehensions>=3.7.0 - mypy>=0.940 + isort>=5.0.1 pygments - pylint>=2.13.0 pytest>=6.2.0 pytest-darker - pytest-flake8>=1.0.6 - pytest-isort>=1.1.0 pytest-kwparametrize>=0.0.3 - pytest-mypy - pyupgrade>=2.31.0 regex>=2021.4.4 requests_cache>=0.7 ruamel.yaml>=0.17.21 - safety>=1.10.3 twine>=2.0.0 types-requests>=2.27.9 types-toml>=0.10.4 diff --git a/src/darker/help.py b/src/darker/help.py index d5b04f470..411f280b0 100644 --- a/src/darker/help.py +++ b/src/darker/help.py @@ -11,7 +11,7 @@ try: import isort except ImportError: - isort = None # type: ignore + isort = None # type: ignore[assignment] DESCRIPTION_PARTS.extend( ["\n", "\n", f"{ISORT_INSTRUCTION} to enable sorting of import definitions"] ) diff --git a/src/darker/import_sorting.py b/src/darker/import_sorting.py index 1174d96f4..4f7344cb0 100644 --- a/src/darker/import_sorting.py +++ b/src/darker/import_sorting.py @@ -33,7 +33,7 @@ def isort_code(*args: Any, **kwargs: Any) -> str: # type: ignore[misc] ) except ImportError: # `isort` is an optional dependency. Prevent the `ImportError` if it's missing. - isort = None # type: ignore + isort = None # type: ignore[assignment] def isort_code(*args: Any, **kwargs: Any) -> str: # type: ignore[misc] """Fake `isort.code()` function to use when `isort` isn't installed""" diff --git a/src/darker/tests/test_git.py b/src/darker/tests/test_git.py index d0ad478c3..112b2d661 100644 --- a/src/darker/tests/test_git.py +++ b/src/darker/tests/test_git.py @@ -422,7 +422,7 @@ def encodings_repo(tmp_path_factory): git_repo.add({"file.py": content}, commit="iso-8859-1") git_repo.create_tag("iso-8859-1") # Commit with a utf-8 encoding cookie - content = "# coding: utf-8\npython = 'パイソン'\n".encode("utf-8") + content = "# coding: utf-8\npython = 'パイソン'\n".encode() git_repo.add({"file.py": content}, commit="utf-8") git_repo.create_tag("utf-8") # Current worktree content (not committed) with a shitfjs encoding cookie