diff --git a/README.md b/README.md index 888191b80b343952f0e1a560a493aa47f6d9c6f7..e065b76e4835020775989ccb1683039376091362 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,25 @@ In addition to logs in the console, this job produces the following reports, kep | `$PYTHON_PROJECT_DIR/reports/py-ruff.gitlab.json` | [GitLab](https://docs.astral.sh/ruff/settings/#output-format) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) | | `$PYTHON_PROJECT_DIR/reports/py-ruff.native.json` | [JSON](https://docs.astral.sh/ruff/settings/#output-format) | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/)<br/>_This report is generated only if SonarQube template is detected_ | +#### `py-mypy` job + +This job is **disabled by default** and performs code analysis based on [mypy](https://mypy.readthedocs.io/en/stable/). +It is activated by setting `$MYPY_ENABLED` to `true`. + +It is bound to the `build` stage, and uses the following variables: + +| Input / Variable | Description | Default value | +| ------------------------ | ---------------------------------- | ----------------- | +| `mypy-args` / `MYPY_ARGS` | Additional [mypy CLI options](https://mypy.readthedocs.io/en/stable/command_line.html) | _none_ | +| `mypy-files` / `MYPY_FILES` | Files or directories to analyse | _none_ (by default analyses all found python source files) | + +In addition to a textual report in the console, this job produces the following reports, kept for one day: + +| Report | Format | Usage | +| -------------- | ---------------------------------------------------------------------------- | ----------------- | +| `$PYTHON_PROJECT_DIR/reports/py-mypy.codeclimate.json` | [Code Climate](https://github.com/soul-catcher/mypy-gitlab-code-quality) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) | +| `$PYTHON_PROJECT_DIR/reports/py-mypy.console.txt` | [mypy console output](https://mypy.readthedocs.io/) | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/) | + ### SonarQube analysis If you're using the SonarQube template to analyse your Python code, here is a sample `sonar-project.properties` file: @@ -326,6 +345,8 @@ sonar.python.pylint.reportPaths=reports/py-lint.parseable.txt sonar.python.bandit.reportPaths=reports/py-bandit.bandit.csv # Ruff: JSON format (if enabled) sonar.python.ruff.reportPaths=reports/py-ruff.native.json +# mypy: JSON format (if enabled) +sonar.python.mypy.reportPaths=reports/py-mypy.console.txt ``` More info: diff --git a/kicker.json b/kicker.json index b6c9c789bde24db52281b08e48a7d8062309d0d1..518615487367fc95c63fd484be71782f4a9dd4b3 100644 --- a/kicker.json +++ b/kicker.json @@ -271,6 +271,24 @@ "advanced": true } ] + }, + { + "id": "mypy", + "name": "mypy", + "description": "Code analysis based on [mypy](https://mypy.readthedocs.io/).", + "enable_with": "MYPY_ENABLED", + "variables": [ + { + "name": "MYPY_ARGS", + "description": "Additional [mypy CLI options](https://mypy.readthedocs.io/en/stable/command_line.html)", + "advanced": true + }, + { + "name": "MYPY_FILES", + "description": "Files or directories to analyse", + "advanced": true + } + ] } ], "variants": [ diff --git a/templates/gitlab-ci-python.yml b/templates/gitlab-ci-python.yml index 38d089ccc5ccfc1953b687700fef4fe8ec03a8d2..1cc04b9454666d812aa68152ca54f5a4d9558a4e 100644 --- a/templates/gitlab-ci-python.yml +++ b/templates/gitlab-ci-python.yml @@ -165,6 +165,16 @@ spec: ruff-ext-exclude: description: Define [extend-exclude](https://docs.astral.sh/ruff/settings/#extend-exclude) files default: "" + mypy-enabled: + description: Enable mypy + type: boolean + default: false + mypy-args: + description: Additional [mypy CLI options](https://mypy.readthedocs.io/en/stable/command_line.html) + default: "" + mypy-files: + description: Files or directories to analyse + default: '' --- # default workflow rules: Merge Request pipelines workflow: @@ -275,6 +285,9 @@ variables: RUFF_ENABLED: $[[ inputs.ruff-enabled ]] RUFF_ARGS: $[[ inputs.ruff-args ]] RUFF_EXT_EXCLUDE: $[[ inputs.ruff-ext-exclude ]] + MYPY_ENABLED: $[[ inputs.mypy-enabled ]] + MYPY_ARGS: $[[ inputs.mypy-args ]] + MYPY_FILES: $[[ inputs.mypy-files ]] .python-scripts: &python-scripts | @@ -939,6 +952,32 @@ py-ruff: when: never - !reference [.test-policy, rules] +py-mypy: + extends: .python-base + stage: build + variables: + MYPY_CACHE_DIR: "$CI_PROJECT_DIR/.cache/mypy" + script: + - mkdir -p -m 777 reports + - install_requirements + - _pip install mypy mypy-to-codeclimate + - _run mypy ${MYPY_ARGS} ${MYPY_FILES:-$(find -type f -name "*.py" -not -path "./.cache/*")} | tee reports/py-mypy.console.txt || true + # mypy-to-codeclimate will fail if any error was found + - _run mypy-to-codeclimate reports/py-mypy.console.txt reports/py-mypy.codeclimate.json + artifacts: + name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG" + expire_in: 1 day + when: always + reports: + codequality: $PYTHON_PROJECT_DIR/reports/py-mypy.codeclimate.json + paths: + - "$PYTHON_PROJECT_DIR/reports/py-mypy.*" + rules: + # exclude if $MYPY_ENABLED not set + - if: '$MYPY_ENABLED != "true"' + when: never + - !reference [.test-policy, rules] + ############################################################################################### # test stage # ###############################################################################################