diff --git a/.github/actions/python_linter/action.yml b/.github/actions/python_linter/action.yml index 8c285e0..1bd4637 100644 --- a/.github/actions/python_linter/action.yml +++ b/.github/actions/python_linter/action.yml @@ -5,6 +5,12 @@ inputs: description: Directory that must be run against the linters required: true + use_autoflake: + description: Use autoflake + required: true + use_bandit: + description: Use bandit linter + required: true use_black: description: Use black formatter required: true @@ -17,11 +23,11 @@ inputs: use_pylint: description: Use pylint linter required: true - use_bandit: - description: Use bandit linter + use_ruff_formatter: + description: Use ruff formatter required: true - use_autoflake: - description: Use autoflake + use_ruff_linter: + description: Use ruff linter required: true runs: @@ -66,11 +72,9 @@ runs: else echo "Skipping isort linter" fi - working-directory: ${{ inputs.working_directory }} shell: bash - - name: bandit run: | if [[ ${{inputs.use_bandit }} != 'false' ]]; then @@ -78,7 +82,6 @@ runs: else echo "Skipping bandit linter" fi - working-directory: ${{ inputs.working_directory }} shell: bash @@ -90,4 +93,24 @@ runs: echo "Skipping autoflake" fi working-directory: ${{ inputs.working_directory }} + shell: bash + + - name: ruff formatter + run: | + if [[ ${{ inputs.use_ruff_formatter }} != 'false' ]]; then + ruff format --config ${GITHUB_WORKSPACE}/.github/configurations/python_linters/.ruff.toml --diff . + else + echo "Skipping ruff formatter" + fi + working-directory: ${{ inputs.working_directory }} + shell: bash + + - name: ruff linter + run: | + if [[ ${{ inputs.use_ruff_linter }} != 'false' ]]; then + ruff check --config ${GITHUB_WORKSPACE}/.github/configurations/python_linters/.ruff.toml . + else + echo "Skipping ruff linter" + fi + working-directory: ${{ inputs.working_directory }} shell: bash \ No newline at end of file diff --git a/.github/actions/python_requirements/create_linter_requirements_file/README.md b/.github/actions/python_requirements/create_linter_requirements_file/README.md index 9be5aa9..fafbb9b 100644 --- a/.github/actions/python_requirements/create_linter_requirements_file/README.md +++ b/.github/actions/python_requirements/create_linter_requirements_file/README.md @@ -13,6 +13,7 @@ As of today only the following linters are supported: * `isort` * `pylint` * `pylint-django` +* `ruff` ## Documentation @@ -23,5 +24,9 @@ As of today only the following linters are supported: * **django_settings_module** - Optional - Path to the Django settings file. It's used to make GitHub action aware of Django presence. In the case of a Django project, `flake8-django` and `pylint-django`, may be used and hence they will be added to the newly created requirements file. **Be careful: if a relative path is used this will depend on *install_from*.** Defaults to empty strings, and hence **no Django settings file**. * **use_autoflake** - Optional - Flag to state whether to use or not `autoflake` linter. It defaults to false. * **use_bandit** - Optional - Flag to state whether to use or not `bandit` linter. It defaults to false. +* **use_black** - Optional - Flag to state whether to use `black` formatter. It defaults to false. * **use_flake8** - Optional - Flag to state whether to use or not `flake8` linter. It defaults to false. +* **use_isort** - Optional - Flag to state whether to use or not `isort` formatter. It defaults to false. * **use_pylint** - Optional - Flag to state whether to use or not `pylint` linter. It defaults to false. +* **use_ruff_formatter** - Optional - Flag to state whether to use `ruff` **formatter** (so without the linting). It defaults to false. +* **use_ruff_linter** - Optional - Flag to state whether to use `ruff` **linter** (so without the formatting). It defaults to false. diff --git a/.github/actions/python_requirements/create_linter_requirements_file/action.yml b/.github/actions/python_requirements/create_linter_requirements_file/action.yml index 7edb47f..b7ac092 100644 --- a/.github/actions/python_requirements/create_linter_requirements_file/action.yml +++ b/.github/actions/python_requirements/create_linter_requirements_file/action.yml @@ -17,13 +17,24 @@ inputs: use_bandit: description: Use bandit linter required: false + use_black: + description: Use black formatter + required: false use_flake8: description: Use flake8 linter required: false + use_isort: + description: Use isort formatter + required: false use_pylint: description: Use pylint linter required: false - + use_ruff_formatter: + description: Use ruff formatter + required: false + use_ruff_linter: + description: Use ruff linter + required: false runs: @@ -76,10 +87,15 @@ runs: if [[ '${{ inputs.use_bandit }}' != 'false' ]]; then check_linter_dependency_and_append_to_file "bandit" "$CI_REQUIREMENTS_LINTERS" fi + if [[ '${{ inputs.use_autoflake }}' != 'false' ]]; then check_linter_dependency_and_append_to_file "autoflake" "$CI_REQUIREMENTS_LINTERS" fi + if [[ '${{ inputs.use_ruff_formatter }}' != 'false' || '${{ inputs.use_ruff_linter }}' != 'false' ]]; then + check_linter_dependency_and_append_to_file "ruff" "$CI_REQUIREMENTS_LINTERS" + fi + if [[ -z '${{ inputs.project_linter_requirements_file }}' ]]; then cat $(echo ${{ inputs.project_linter_requirements_file }}) >> requirements-linters.txt fi diff --git a/.github/configurations/python_linters/.ruff.toml b/.github/configurations/python_linters/.ruff.toml new file mode 100644 index 0000000..601926e --- /dev/null +++ b/.github/configurations/python_linters/.ruff.toml @@ -0,0 +1,51 @@ +# Top level settings +## Reference: https://docs.astral.sh/ruff/settings/#top-level + +extend-exclude = [ + ".github", + ".idea", + ".vscode", + "**/migrations/*" +] + +include = ["*.py"] + +indent-width = 4 + +line-length = 160 + +output-format = "full" + +respect-gitignore = false + +show-fixes = true + +target-version = "py312" + +# Format settings level +## Reference: https://docs.astral.sh/ruff/settings/#format +[format] + +docstring-code-format = true + +indent-style = "space" + +line-ending = "native" + +quote-style = "double" + +skip-magic-trailing-comma = false + +[lint] + +# Default + Isort +select = [ + "E4", + "E7", + "E9", + "F", + # Isort - https://docs.astral.sh/ruff/rules/#isort-i + "I" +] + +ignore = [ ] diff --git a/.github/configurations/python_linters/requirements-linters.txt b/.github/configurations/python_linters/requirements-linters.txt index d8e8a4c..5f7cdde 100644 --- a/.github/configurations/python_linters/requirements-linters.txt +++ b/.github/configurations/python_linters/requirements-linters.txt @@ -8,4 +8,5 @@ flake8-django @ git+https://github.com/terencehonles/flake8-django.git@a6e369e89 flake8~=7.1.2 isort~=6.0.1 pylint-django~=2.6.1 -pylint~=3.3.5 \ No newline at end of file +pylint~=3.3.5 +ruff~=0.12.7 \ No newline at end of file diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 63ae6b8..258d5a1 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -133,10 +133,12 @@ It is composed of one job: * **max_timeout** - Optional - Maximum amount of time (in minutes) the workflow is allowed to run. By default, it is set to `30`. * **use_black** - Optional - Whether to use black formatter. By default, it is set to `false`. * **use_isort** - Optional - Whether to use isort formatter. By default, it is set to `false`. +* **use_ruff_formatter** - Optional - Whether to use ruff formatter. By default, it is set to `false`. * **use_autoflake** - Optional - Whether to use autoflake linter. By default, it is set to `false`. * **use_bandit** - Optional - Whether to use bandit linter. By default, it is set to `false`. * **use_flake8** - Optional - Whether to use flake8 linter. By default, it is set to `false`. * **use_pylint** - Optional - Whether to use pylint linter. By default, it is set to `false`. +* **use_ruff_linter** - Optional - Whether to use ruff linter. By default, it is set to `false`. * **use_coverage** - Optional - Whether to use coverage. By default, it is set to `false`. * **coverage_config_path** - Optional - Path to the coverage configuration file. By default, it is set to `.coveragerc`. * **upload_coverage** - Optional - Whether to upload coverage report to GitHub. To work, it needs *use_coverage* to be true. By default, it is set to `false`. diff --git a/.github/workflows/_python.yml b/.github/workflows/_python.yml index e2142b1..8c5c39f 100644 --- a/.github/workflows/_python.yml +++ b/.github/workflows/_python.yml @@ -50,6 +50,10 @@ on: description: Use isort formatter type: boolean required: false + use_ruff_formatter: + description: Use ruff formatter + type: boolean + required: false # Linters use_autoflake: @@ -68,6 +72,10 @@ on: description: Use pylint linter type: boolean required: false + use_ruff_linter: + description: Use ruff linter + type: boolean + required: false # Coverage configs use_coverage: @@ -306,8 +314,12 @@ jobs: django_settings_module: ${{ inputs.django_settings_module }} use_autoflake: ${{ inputs.use_autoflake }} use_bandit: ${{ inputs.use_bandit }} + use_black: ${{ inputs.use_black }} use_flake8: ${{ inputs.use_flake8 }} + use_isort: ${{ inputs.use_isort }} use_pylint: ${{ inputs.use_pylint }} + use_ruff_formatter: ${{ inputs.use_ruff_formatter }} + use_ruff_linter: ${{ inputs.use_ruff_linter }} - name: Create dev requirements file uses: ./.github/actions/python_requirements/create_dev_requirements_file @@ -416,7 +428,15 @@ jobs: - name: Run linters uses: ./.github/actions/python_linter - if: inputs.use_black || inputs.use_isort || inputs.use_flake8 || inputs.use_pylint || inputs.use_bandit || inputs.use_autoflake + if: > + inputs.use_black || + inputs.use_isort || + inputs.use_flake8 || + inputs.use_pylint || + inputs.use_bandit || + inputs.use_autoflake || + inputs.use_ruff_formatter || + inputs.use_ruff_linter with: working_directory: ${{ inputs.working_directory }} use_black: ${{ inputs.use_black }} @@ -425,6 +445,8 @@ jobs: use_pylint: ${{ inputs.use_pylint }} use_bandit: ${{ inputs.use_bandit }} use_autoflake: ${{ inputs.use_autoflake }} + use_ruff_formatter: ${{ inputs.use_ruff_formatter }} + use_ruff_linter: ${{ inputs.use_ruff_linter }} - name: Run CodeQL if: inputs.run_codeql diff --git a/.github/workflows/pull_request_automation.yml b/.github/workflows/pull_request_automation.yml index 7433a96..fc6a62e 100644 --- a/.github/workflows/pull_request_automation.yml +++ b/.github/workflows/pull_request_automation.yml @@ -62,6 +62,8 @@ jobs: use_pylint: true use_bandit: false use_autoflake: true + use_ruff_formatter: false + use_ruff_linter: true run_codeql: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c845ce3..9697a09 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,3 +43,12 @@ repos: hooks: - id: autoflake args: ["-i", "--remove-all-unused-imports", "--remove-unused-variables", "--ignore-init-module-imports", "--ignore-pass-statements"] + +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.7 + hooks: + - id: ruff-format + args: ["--config", "./.github/configurations/python_linters/.ruff.toml"] + - id: ruff + name: ruff-lint + args: ["--config", "./.github/configurations/python_linters/.ruff.toml"] diff --git a/CHANGELOG.md b/CHANGELOG.md index c1fdbe5..d32056d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ * Added "release.yml" action to to push containers to AWS ECR * Added *create_apt_cache.yaml* workflow to cache APT requirements each time a commit is pushed on selected branch and **when the requirements file has changed**. * Added documentation. +* Added "Ruff" to the list of available Python linters. #### Bugfix * Updated python linters also in '_python.yml' workflow (missing from previous release) * Explicitly disabled `xpack.security` in Elasticsearch container, since it is enabled by default in newer versions of Elasticsearch +* Added missing inputs for "create_linter_requirements_file" action. #### Changes * Deprecation of license check table-headers * Updated Python linters: diff --git a/actions/python_linter/action.yml b/actions/python_linter/action.yml index 8c285e0..1bd4637 100644 --- a/actions/python_linter/action.yml +++ b/actions/python_linter/action.yml @@ -5,6 +5,12 @@ inputs: description: Directory that must be run against the linters required: true + use_autoflake: + description: Use autoflake + required: true + use_bandit: + description: Use bandit linter + required: true use_black: description: Use black formatter required: true @@ -17,11 +23,11 @@ inputs: use_pylint: description: Use pylint linter required: true - use_bandit: - description: Use bandit linter + use_ruff_formatter: + description: Use ruff formatter required: true - use_autoflake: - description: Use autoflake + use_ruff_linter: + description: Use ruff linter required: true runs: @@ -66,11 +72,9 @@ runs: else echo "Skipping isort linter" fi - working-directory: ${{ inputs.working_directory }} shell: bash - - name: bandit run: | if [[ ${{inputs.use_bandit }} != 'false' ]]; then @@ -78,7 +82,6 @@ runs: else echo "Skipping bandit linter" fi - working-directory: ${{ inputs.working_directory }} shell: bash @@ -90,4 +93,24 @@ runs: echo "Skipping autoflake" fi working-directory: ${{ inputs.working_directory }} + shell: bash + + - name: ruff formatter + run: | + if [[ ${{ inputs.use_ruff_formatter }} != 'false' ]]; then + ruff format --config ${GITHUB_WORKSPACE}/.github/configurations/python_linters/.ruff.toml --diff . + else + echo "Skipping ruff formatter" + fi + working-directory: ${{ inputs.working_directory }} + shell: bash + + - name: ruff linter + run: | + if [[ ${{ inputs.use_ruff_linter }} != 'false' ]]; then + ruff check --config ${GITHUB_WORKSPACE}/.github/configurations/python_linters/.ruff.toml . + else + echo "Skipping ruff linter" + fi + working-directory: ${{ inputs.working_directory }} shell: bash \ No newline at end of file diff --git a/actions/python_requirements/create_linter_requirements_file/README.md b/actions/python_requirements/create_linter_requirements_file/README.md index 9be5aa9..fafbb9b 100644 --- a/actions/python_requirements/create_linter_requirements_file/README.md +++ b/actions/python_requirements/create_linter_requirements_file/README.md @@ -13,6 +13,7 @@ As of today only the following linters are supported: * `isort` * `pylint` * `pylint-django` +* `ruff` ## Documentation @@ -23,5 +24,9 @@ As of today only the following linters are supported: * **django_settings_module** - Optional - Path to the Django settings file. It's used to make GitHub action aware of Django presence. In the case of a Django project, `flake8-django` and `pylint-django`, may be used and hence they will be added to the newly created requirements file. **Be careful: if a relative path is used this will depend on *install_from*.** Defaults to empty strings, and hence **no Django settings file**. * **use_autoflake** - Optional - Flag to state whether to use or not `autoflake` linter. It defaults to false. * **use_bandit** - Optional - Flag to state whether to use or not `bandit` linter. It defaults to false. +* **use_black** - Optional - Flag to state whether to use `black` formatter. It defaults to false. * **use_flake8** - Optional - Flag to state whether to use or not `flake8` linter. It defaults to false. +* **use_isort** - Optional - Flag to state whether to use or not `isort` formatter. It defaults to false. * **use_pylint** - Optional - Flag to state whether to use or not `pylint` linter. It defaults to false. +* **use_ruff_formatter** - Optional - Flag to state whether to use `ruff` **formatter** (so without the linting). It defaults to false. +* **use_ruff_linter** - Optional - Flag to state whether to use `ruff` **linter** (so without the formatting). It defaults to false. diff --git a/actions/python_requirements/create_linter_requirements_file/action.yml b/actions/python_requirements/create_linter_requirements_file/action.yml index 7edb47f..b7ac092 100644 --- a/actions/python_requirements/create_linter_requirements_file/action.yml +++ b/actions/python_requirements/create_linter_requirements_file/action.yml @@ -17,13 +17,24 @@ inputs: use_bandit: description: Use bandit linter required: false + use_black: + description: Use black formatter + required: false use_flake8: description: Use flake8 linter required: false + use_isort: + description: Use isort formatter + required: false use_pylint: description: Use pylint linter required: false - + use_ruff_formatter: + description: Use ruff formatter + required: false + use_ruff_linter: + description: Use ruff linter + required: false runs: @@ -76,10 +87,15 @@ runs: if [[ '${{ inputs.use_bandit }}' != 'false' ]]; then check_linter_dependency_and_append_to_file "bandit" "$CI_REQUIREMENTS_LINTERS" fi + if [[ '${{ inputs.use_autoflake }}' != 'false' ]]; then check_linter_dependency_and_append_to_file "autoflake" "$CI_REQUIREMENTS_LINTERS" fi + if [[ '${{ inputs.use_ruff_formatter }}' != 'false' || '${{ inputs.use_ruff_linter }}' != 'false' ]]; then + check_linter_dependency_and_append_to_file "ruff" "$CI_REQUIREMENTS_LINTERS" + fi + if [[ -z '${{ inputs.project_linter_requirements_file }}' ]]; then cat $(echo ${{ inputs.project_linter_requirements_file }}) >> requirements-linters.txt fi diff --git a/configurations/python_linters/.ruff.toml b/configurations/python_linters/.ruff.toml new file mode 100644 index 0000000..601926e --- /dev/null +++ b/configurations/python_linters/.ruff.toml @@ -0,0 +1,51 @@ +# Top level settings +## Reference: https://docs.astral.sh/ruff/settings/#top-level + +extend-exclude = [ + ".github", + ".idea", + ".vscode", + "**/migrations/*" +] + +include = ["*.py"] + +indent-width = 4 + +line-length = 160 + +output-format = "full" + +respect-gitignore = false + +show-fixes = true + +target-version = "py312" + +# Format settings level +## Reference: https://docs.astral.sh/ruff/settings/#format +[format] + +docstring-code-format = true + +indent-style = "space" + +line-ending = "native" + +quote-style = "double" + +skip-magic-trailing-comma = false + +[lint] + +# Default + Isort +select = [ + "E4", + "E7", + "E9", + "F", + # Isort - https://docs.astral.sh/ruff/rules/#isort-i + "I" +] + +ignore = [ ] diff --git a/configurations/python_linters/requirements-linters.txt b/configurations/python_linters/requirements-linters.txt index d8e8a4c..5f7cdde 100644 --- a/configurations/python_linters/requirements-linters.txt +++ b/configurations/python_linters/requirements-linters.txt @@ -8,4 +8,5 @@ flake8-django @ git+https://github.com/terencehonles/flake8-django.git@a6e369e89 flake8~=7.1.2 isort~=6.0.1 pylint-django~=2.6.1 -pylint~=3.3.5 \ No newline at end of file +pylint~=3.3.5 +ruff~=0.12.7 \ No newline at end of file diff --git a/workflows/README.md b/workflows/README.md index 63ae6b8..258d5a1 100644 --- a/workflows/README.md +++ b/workflows/README.md @@ -133,10 +133,12 @@ It is composed of one job: * **max_timeout** - Optional - Maximum amount of time (in minutes) the workflow is allowed to run. By default, it is set to `30`. * **use_black** - Optional - Whether to use black formatter. By default, it is set to `false`. * **use_isort** - Optional - Whether to use isort formatter. By default, it is set to `false`. +* **use_ruff_formatter** - Optional - Whether to use ruff formatter. By default, it is set to `false`. * **use_autoflake** - Optional - Whether to use autoflake linter. By default, it is set to `false`. * **use_bandit** - Optional - Whether to use bandit linter. By default, it is set to `false`. * **use_flake8** - Optional - Whether to use flake8 linter. By default, it is set to `false`. * **use_pylint** - Optional - Whether to use pylint linter. By default, it is set to `false`. +* **use_ruff_linter** - Optional - Whether to use ruff linter. By default, it is set to `false`. * **use_coverage** - Optional - Whether to use coverage. By default, it is set to `false`. * **coverage_config_path** - Optional - Path to the coverage configuration file. By default, it is set to `.coveragerc`. * **upload_coverage** - Optional - Whether to upload coverage report to GitHub. To work, it needs *use_coverage* to be true. By default, it is set to `false`. diff --git a/workflows/_python.yml b/workflows/_python.yml index e2142b1..8c5c39f 100644 --- a/workflows/_python.yml +++ b/workflows/_python.yml @@ -50,6 +50,10 @@ on: description: Use isort formatter type: boolean required: false + use_ruff_formatter: + description: Use ruff formatter + type: boolean + required: false # Linters use_autoflake: @@ -68,6 +72,10 @@ on: description: Use pylint linter type: boolean required: false + use_ruff_linter: + description: Use ruff linter + type: boolean + required: false # Coverage configs use_coverage: @@ -306,8 +314,12 @@ jobs: django_settings_module: ${{ inputs.django_settings_module }} use_autoflake: ${{ inputs.use_autoflake }} use_bandit: ${{ inputs.use_bandit }} + use_black: ${{ inputs.use_black }} use_flake8: ${{ inputs.use_flake8 }} + use_isort: ${{ inputs.use_isort }} use_pylint: ${{ inputs.use_pylint }} + use_ruff_formatter: ${{ inputs.use_ruff_formatter }} + use_ruff_linter: ${{ inputs.use_ruff_linter }} - name: Create dev requirements file uses: ./.github/actions/python_requirements/create_dev_requirements_file @@ -416,7 +428,15 @@ jobs: - name: Run linters uses: ./.github/actions/python_linter - if: inputs.use_black || inputs.use_isort || inputs.use_flake8 || inputs.use_pylint || inputs.use_bandit || inputs.use_autoflake + if: > + inputs.use_black || + inputs.use_isort || + inputs.use_flake8 || + inputs.use_pylint || + inputs.use_bandit || + inputs.use_autoflake || + inputs.use_ruff_formatter || + inputs.use_ruff_linter with: working_directory: ${{ inputs.working_directory }} use_black: ${{ inputs.use_black }} @@ -425,6 +445,8 @@ jobs: use_pylint: ${{ inputs.use_pylint }} use_bandit: ${{ inputs.use_bandit }} use_autoflake: ${{ inputs.use_autoflake }} + use_ruff_formatter: ${{ inputs.use_ruff_formatter }} + use_ruff_linter: ${{ inputs.use_ruff_linter }} - name: Run CodeQL if: inputs.run_codeql diff --git a/workflows/pull_request_automation.yml b/workflows/pull_request_automation.yml index 7433a96..fc6a62e 100644 --- a/workflows/pull_request_automation.yml +++ b/workflows/pull_request_automation.yml @@ -62,6 +62,8 @@ jobs: use_pylint: true use_bandit: false use_autoflake: true + use_ruff_formatter: false + use_ruff_linter: true run_codeql: true