Commit 9a35ea3b authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

Merge branch 'feat/normalize-reports' into 'master'

Normalize reports

See merge request to-be-continuous/python!52
parents 51574b22 d591f6d1
Loading
Loading
Loading
Loading
+71 −86
Original line number Diff line number Diff line
@@ -72,10 +72,12 @@ It is bound to the `build` stage, and uses the following variables:
| `PYLINT_ARGS`            | Additional [pylint CLI options](http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options) |  _none_           |
| `PYLINT_FILES`           | Files or directories to analyse   | _none_ (by default analyses all found python source files) |

This job produces the following artifacts, kept for one day:
In addition to a textual report in the console, this job produces the following reports, kept for one day:

* Code quality json report in code climate format.
* Pylint report for SonarQube (if `SONAR_URL` is defined).
| Report         | Format                                                                       | Usage             |
| -------------- | ---------------------------------------------------------------------------- | ----------------- |
| `$PYTHON_PROJECT_DIR/reports/py-lint.codeclimate.json` | [Code Climate](https://docs.codeclimate.com/docs/pylint) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) |
| `$PYTHON_PROJECT_DIR/reports/py-lint.parseable.txt` | [parseable](https://pylint.pycqa.org/en/latest/user_guide/usage/output.html) | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/) |

### Test jobs

@@ -99,14 +101,7 @@ It is bound to the `build` stage, and uses the following variables:
| ------------------------ | -------------------------------------------------------------------- | ----------------------- |
| `UNITTEST_ARGS`          | Additional xmlrunner/unittest CLI options                            | _none_                  |

This job produces the following artifacts, kept for one day:

* JUnit test report (using the [xmlrunner](https://github.com/xmlrunner/unittest-xml-reporting) module)
* code coverage report (cobertura xml format).

:warning: code coverage report artifact is disabled, due to a deprecated syntax, see [Activate code coverage report artifact](#activate-code-coverage-report-artifact)

:warning: create a `.coveragerc` file at the root of your Python project to control the coverage settings.
:information_source: use a `.coveragerc` file at the root of your Python project to control the coverage settings.

Example:

@@ -120,6 +115,13 @@ source =
    module_2
```

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/TEST-*.xml` | [xUnit](https://en.wikipedia.org/wiki/XUnit) test report(s) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsjunit) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/test-execution-parameters/#header-8) |
| `$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml` | [Cobertura XML](https://gcovr.com/en/stable/output/cobertura.html) coverage report | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/python-test-coverage/) |

#### `py-pytest` job

This job is **disabled by default** and performs tests based on [pytest](https://docs.pytest.org/en/latest/) Python lib.
@@ -131,14 +133,7 @@ It is bound to the `build` stage, and uses the following variables:
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| `PYTEST_ARGS`            | Additional [pytest](https://docs.pytest.org/en/stable/usage.html) or [pytest-cov](https://github.com/pytest-dev/pytest-cov#usage) CLI options | _none_                  |

This job produces the following artifacts, kept for one day:

* JUnit test report (with the [`--junit-xml`](http://doc.pytest.org/en/latest/usage.html#creating-junitxml-format-files) argument)
* code coverage report (cobertura xml format).

:warning: code coverage report artifact is disabled, due to a deprecated syntax, see [Activate code coverage report artifact](#activate-code-coverage-report-artifact)

:warning: create a `.coveragerc` file at the root of your Python project to control the coverage settings.
:information_source: use a `.coveragerc` file at the root of your Python project to control the coverage settings.

Example:

@@ -152,6 +147,13 @@ source =
    module_2
```

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/TEST-*.xml` | [xUnit](https://en.wikipedia.org/wiki/XUnit) test report(s) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsjunit) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/test-execution-parameters/#header-8) |
| `$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml` | [Cobertura XML](https://gcovr.com/en/stable/output/cobertura.html) coverage report | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/python-test-coverage/) |

#### `py-nosetest` job

This job is **disabled by default** and performs tests based on [nose](https://nose.readthedocs.io/en/latest/) Python lib.
@@ -163,17 +165,17 @@ It is bound to the `build` stage, and uses the following variables:
| ------------------------ | --------------------------------------------------------------------------------------- | ----------------------- |
| `NOSETESTS_ARGS`         | Additional [nose CLI options](https://nose.readthedocs.io/en/latest/usage.html#options) | _none_                  |

By default coverage will be run on all the directory. You can restrict it to your packages by setting NOSE_COVER_PACKAGE variable.
By default coverage will be run on all the project directories. You can restrict it to your packages by setting the `$NOSE_COVER_PACKAGE` variable.
More [info](https://nose.readthedocs.io/en/latest/plugins/cover.html)

This job produces the following artifacts, kept for one day:

* JUnit test report (with the [`--with-xunit`](https://nose.readthedocs.io/en/latest/plugins/xunit.html) argument)
* code coverage report (cobertura xml format + html report).
:information_source: use a `.coveragerc` file at the root of your Python project to control the coverage settings.

:warning: code coverage report artifact is disabled, due to a deprecated syntax, see [Activate code coverage report artifact](#activate-code-coverage-report-artifact)
In addition to a textual report in the console, this job produces the following reports, kept for one day:

:warning: create a `.coveragerc` file at the root of your Python project or use [nose CLI options](https://nose.readthedocs.io/en/latest/plugins/cover.html#options) to control the coverage settings.
| Report         | Format                                                                       | Usage             |
| -------------- | ---------------------------------------------------------------------------- | ----------------- |
| `$PYTHON_PROJECT_DIR/reports/TEST-*.xml` | [xUnit](https://en.wikipedia.org/wiki/XUnit) test report(s) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsjunit) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/test-execution-parameters/#header-8) |
| `$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml` | [Cobertura XML](https://gcovr.com/en/stable/output/cobertura.html) coverage report | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report) & [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/python-test-coverage/) |

#### `py-compile` job

@@ -186,58 +188,6 @@ It is bound to the `build` stage, and uses the following variables:
| --------------------- | ----------------------------------------------------------------------------- | ------------- |
| `PYTHON_COMPILE_ARGS` | [`compileall` CLI options](https://docs.python.org/3/library/compileall.html) | `*`           |

#### Activate code coverage report artifact

Code coverage report artifact is disabled, due to a [deprecated syntax](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78132).

In order to activate code coverage report artifact, you need to override your actual unit test job depending on our GitLab version.

Here is an example with `py-pytest` job (change to `py-unittest` or `py-nosetests` depending on your unit tests library):

* for GitLab < 14.10:
```yaml
py-pytest:
  artifacts:
    reports:
      cobertura: $PYTHON_PROJECT_DIR/reports/coverage.xml
```
* for GitLab >= 14.10:
```yaml
py-pytest:
  artifacts:
    reports:
      coverage_report:
        ​coverage_format: cobertura
        path: ​$PYTHON_PROJECT_DIR/reports/coverage.xml
```

### SonarQube analysis

If you're using the SonarQube template to analyse your Python code, here is a sample `sonar-project.properties` file:

```properties
# see: https://docs.sonarqube.org/latest/analysis/languages/python/
# set your source directory(ies) here (relative to the sonar-project.properties file)
sonar.sources=.
# exclude unwanted directories and files from being analysed
sonar.exclusions=**/test_*.py

# set your tests directory(ies) here (relative to the sonar-project.properties file)
sonar.tests=.
sonar.test.inclusions=**/test_*.py

# tests report: generic format
sonar.python.xunit.reportPath=reports/unittest/TEST-*.xml
# coverage report: XUnit format
sonar.python.coverage.reportPaths=reports/coverage.xml
```

More info:

* [Python language support](https://docs.sonarqube.org/latest/analysis/languages/python/)
* [test coverage & execution parameters](https://docs.sonarqube.org/latest/analysis/coverage/)
* [third-party issues](https://docs.sonarqube.org/latest/analysis/external-issues/)

### `py-bandit` job (SAST)

This job is **disabled by default** and performs a [Bandit](https://pypi.org/project/bandit/) analysis.
@@ -249,8 +199,12 @@ It is bound to the `test` stage, and uses the following variables:
| `BANDIT_ENABLED` | Set to `true` to enable Bandit analysis                                | _none_ (disabled) |
| `BANDIT_ARGS`    | Additional [Bandit CLI options](https://github.com/PyCQA/bandit#usage) | `--recursive .`   |

This job outputs a **textual report** in the console, and in case of failure also exports a JSON report in the `reports/`
directory _(relative to project root dir)_.
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-bandit.bandit.csv` | [CSV](https://bandit.readthedocs.io/en/latest/formatters/csv.html) | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/)<br/>_This report is generated only if SonarQube template is detected_ |
| `$PYTHON_PROJECT_DIR/reports/py-bandit.bandit.json` | [JSON](https://bandit.readthedocs.io/en/latest/formatters/json.html) | [DefectDojo integration](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/#bandit)<br/>_This report is generated only if DefectDojo template is detected_ |

### `py-safety` job (dependency check)

@@ -263,9 +217,6 @@ It is bound to the `test` stage, and uses the following variables:
| `SAFETY_ENABLED` | Set to `true` to enable Safety job                                      | _none_ (disabled) |
| `SAFETY_ARGS`    | Additional [Safety CLI options](https://github.com/pyupio/safety#usage) | `--full-report`   |

This job outputs a **textual report** in the console, and in case of failure also exports a JSON report in the `reports/`
directory _(relative to project root dir)_.

### `py-trivy` job (dependency check)

This job is **disabled by default** and performs a dependency check analysis using [Trivy](https://github.com/aquasecurity/trivy/).
@@ -277,8 +228,42 @@ It is bound to the `test` stage, and uses the following variables:
| `PYTHON_TRIVY_ENABLED` | Set to `true` to enable Trivy job                                 | _none_ (disabled) |
| `PYTHON_TRIVY_ARGS`    | Additional [Trivy CLI options](https://aquasecurity.github.io/trivy/v0.21.1/getting-started/cli/fs/) | `--vuln-type library`   |

This job outputs a **textual report** in the console, and in case of failure also exports a JSON report in the `reports/`
directory _(relative to project root dir)_.
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-trivy.trivy.json` | [JSON](https://aquasecurity.github.io/trivy/latest/docs/vulnerability/examples/report/#json) | [DefectDojo integration](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/#trivy)<br/>_This report is generated only if DefectDojo template is detected_ |

### SonarQube analysis

If you're using the SonarQube template to analyse your Python code, here is a sample `sonar-project.properties` file:

```properties
# see: https://docs.sonarqube.org/latest/analysis/languages/python/
# set your source directory(ies) here (relative to the sonar-project.properties file)
sonar.sources=.
# exclude unwanted directories and files from being analysed
sonar.exclusions=**/test_*.py

# set your tests directory(ies) here (relative to the sonar-project.properties file)
sonar.tests=.
sonar.test.inclusions=**/test_*.py

# tests report: xUnit format
sonar.python.xunit.reportPath=reports/unittest/TEST-*.xml
# coverage report: Cobertura format
sonar.python.coverage.reportPaths=reports/py-coverage.cobertura.xml
# pylint: parseable format (if enabled)
sonar.python.pylint.reportPaths=reports/py-lint.parseable.txt
# Bandit: CSV format (if enabled)
sonar.python.bandit.reportPaths=reports/py-bandit.bandit.csv
```

More info:

* [Python language support](https://docs.sonarqube.org/latest/analysis/languages/python/)
* [test coverage & execution parameters](https://docs.sonarqube.org/latest/analysis/coverage/)
* [third-party issues](https://docs.sonarqube.org/latest/analysis/external-issues/)

### `py-release` job

+52 −86
Original line number Diff line number Diff line
@@ -605,34 +605,19 @@ py-lint:
  extends: .python-base
  stage: build
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - _pip install pylint_gitlab
    - |
      if ! _run pylint --ignore=.cache --output-format=text  ${PYLINT_ARGS}  ${PYLINT_FILES:-$(find -type f -name "*.py")}
      then
        # failed: also generate codeclimate report
        _run pylint --ignore=.cache --output-format=pylint_gitlab.GitlabCodeClimateReporter  ${PYLINT_ARGS} ${PYLINT_FILES:-$(find -type f -name "*.py")} > reports/pylint-codeclimate.json
        exit 1
      else
        # success: generate empty codeclimate report (required by GitLab :( )
        echo "[]" > reports/pylint-codeclimate.json
      fi
    - |
      if [ -n "$SONAR_URL" ]
      then
        # SonarQube is configured, export analysis report
        _run pylint --ignore=.cache --output-format=parseable  ${PYLINT_ARGS} ${PYLINT_FILES:-$(find -type f -name "*.py")} > reports/pylint.txt
      fi
    - _pip install pylint_gitlab # codeclimate reports
    # run pylint and generate reports all at once
    - _run pylint --ignore=.cache --output-format=colorized,pylint_gitlab.GitlabCodeClimateReporter:reports/py-lint.codeclimate.json,parseable:reports/py-lint.parseable.txt ${PYLINT_ARGS} ${PYLINT_FILES:-$(find -type f -name "*.py")}
  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/pylint-codeclimate.json
      codequality: $PYTHON_PROJECT_DIR/reports/py-lint.codeclimate.json
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/py-lint.*"
  rules:
    # exclude if $PYLINT_ENABLED not set
    - if: '$PYLINT_ENABLED != "true"'
@@ -658,8 +643,7 @@ py-unittest:
  extends: .python-base
  stage: build
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    # code coverage
    - _pip install coverage
@@ -667,7 +651,7 @@ py-unittest:
    - _pip install unittest-xml-reporting
    - _run coverage run -m xmlrunner discover -o "reports/" $UNITTEST_ARGS
    - _run coverage report -m
    - _run coverage xml -o "reports/coverage.xml"
    - _run coverage xml -o "reports/py-coverage.cobertura.xml"
  coverage: /^TOTAL.+?(\d+\%)$/
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
@@ -675,16 +659,13 @@ py-unittest:
    when: always
    reports:
      junit:
        - $PYTHON_PROJECT_DIR/reports/TEST-*.xml
      # declaring the Cobertura report depends on the GitLab version :(
      # GitLab < 14.10
      # cobertura: $PYTHON_PROJECT_DIR/reports/coverage.xml
      # GitLab >= 14.10
      # coverage_report:
      #   ​coverage_format: cobertura
      #   path: ​$PYTHON_PROJECT_DIR/reports/coverage.xml
        - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      coverage_report:
        coverage_format: cobertura
        path: "$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml"
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      - "$PYTHON_PROJECT_DIR/reports/py-coverage.*"
  rules:
    # skip if $UNITTEST_ENABLED not set
    - if: '$UNITTEST_ENABLED != "true"'
@@ -695,11 +676,10 @@ py-pytest:
  extends: .python-base
  stage: build
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - _pip install pytest pytest-cov coverage
    - _python -m pytest --junit-xml=reports/TEST-pytests.xml --cov --cov-report term  --cov-report xml:reports/coverage.xml ${PYTEST_ARGS}
    - _python -m pytest --junit-xml=reports/TEST-pytests.xml --cov --cov-report term  --cov-report xml:reports/py-coverage.cobertura.xml ${PYTEST_ARGS}
  coverage: /^TOTAL.+?(\d+\%)$/
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
@@ -707,16 +687,13 @@ py-pytest:
    when: always
    reports:
      junit:
        - $PYTHON_PROJECT_DIR/reports/TEST-*.xml
      # declaring the Cobertura report depends on the GitLab version :(
      # GitLab < 14.10
      # cobertura: $PYTHON_PROJECT_DIR/reports/coverage.xml
      # GitLab >= 14.10
      # coverage_report:
      #   ​coverage_format: cobertura
      #   path: ​$PYTHON_PROJECT_DIR/reports/coverage.xml
        - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      coverage_report:
        coverage_format: cobertura
        path: "$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml"
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      - "$PYTHON_PROJECT_DIR/reports/py-coverage.*"
  rules:
    # skip if $PYTEST_ENABLED not set
    - if: '$PYTEST_ENABLED != "true"'
@@ -727,10 +704,9 @@ py-nosetests:
  extends: .python-base
  stage: build
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - _run nosetests --with-xunit --xunit-file=reports/TEST-nosetests.xml --with-coverage --cover-erase --cover-xml --cover-xml-file=reports/coverage.xml --cover-html --cover-html-dir=reports/coverage ${NOSETESTS_ARGS}
    - _run nosetests --with-xunit --xunit-file=reports/TEST-nosetests.xml --with-coverage --cover-erase --cover-xml --cover-xml-file=reports/py-coverage.cobertura.xml ${NOSETESTS_ARGS}
  coverage: /^TOTAL.+?(\d+\%)$/
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
@@ -738,16 +714,13 @@ py-nosetests:
    when: always
    reports:
      junit:
        - $PYTHON_PROJECT_DIR/reports/TEST-*.xml
      # declaring the Cobertura report depends on the GitLab version :(
      # GitLab < 14.10
      # cobertura: $PYTHON_PROJECT_DIR/reports/coverage.xml
      # GitLab >= 14.10
      # coverage_report:
      #   coverage_format: cobertura
      #   path: ​$PYTHON_PROJECT_DIR/reports/coverage.xml
        - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      coverage_report:
        coverage_format: cobertura
        path: "$PYTHON_PROJECT_DIR/reports/py-coverage.cobertura.xml"
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/TEST-*.xml"
      - "$PYTHON_PROJECT_DIR/reports/py-coverage.*"
  rules:
    # skip if $NOSETESTS_ENABLED not set
    - if: '$NOSETESTS_ENABLED != "true"'
@@ -761,23 +734,28 @@ py-bandit:
  # force no dependencies
  dependencies: []
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - _pip install bandit
    # CSV (for SonarQube)
    - |
      if ! _run bandit ${TRACE+--verbose} ${BANDIT_ARGS}
      if [[ "$SONAR_HOST_URL"]]
      then
        # failed: also generate JSON report
        _run bandit ${TRACE+--verbose} --format json --output reports/bandit.json ${BANDIT_ARGS}
        exit 1
        _run bandit ${TRACE+--verbose} --exit-zero --format csv --output reports/py-bandit.bandit.csv ${BANDIT_ARGS}
      fi
    # JSON (for DefectDojo)
    - |
      if [[ "$DEFECTDOJO_BANDIT_REPORTS"]]
      then
        _run bandit ${TRACE+--verbose} --exit-zero --format json --output reports/py-bandit.bandit.json ${BANDIT_ARGS}
      fi
    - _run bandit ${TRACE+--verbose} ${BANDIT_ARGS}
  artifacts:
    when: always
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/py-bandit.*"
  rules:
    # exclude if $BANDIT_ENABLED not set
    - if: '$BANDIT_ENABLED != "true"'
@@ -791,24 +769,10 @@ py-safety:
  # force no dependencies
  dependencies: []
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - _pip install safety
    - |
      if ! _pip freeze | _run safety check --stdin ${SAFETY_ARGS}
      then
        # failed: also generate JSON report

        _pip freeze | _run safety check --stdin --json --output reports/safety.json ${SAFETY_ARGS}
        exit 1
      fi
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    paths:
      - $PYTHON_PROJECT_DIR/reports/
    - _pip freeze | _run safety check --stdin ${SAFETY_ARGS}
  rules:
    # exclude if $SAFETY_ENABLED not set
    - if: '$SAFETY_ENABLED != "true"'
@@ -822,8 +786,7 @@ py-trivy:
  # force no dependencies
  dependencies: []
  script:
    - mkdir -p reports
    - chmod o+rwx reports
    - mkdir -p -m 777 reports
    - install_requirements
    - apt-get update
    - apt-get install -y wget apt-transport-https gnupg lsb-release
@@ -854,15 +817,18 @@ py-trivy:
        log_error "Could not find a file listing all dependencies with their versions."
        exit 1
      fi
      trivy fs ${PYTHON_TRIVY_ARGS} --format table --exit-code 0 ./reports/
      trivy fs ${PYTHON_TRIVY_ARGS} --format cyclonedx --output ./reports/sbom_cyclonedx.json --exit-code 0 ./reports/
      trivy fs ${PYTHON_TRIVY_ARGS} --format json --output reports/trivy-python.json --list-all-pkgs --exit-code 1 ./reports/
      if [[ "$DEFECTDOJO_TRIVY_REPORTS" ]]
      then
        trivy fs ${PYTHON_TRIVY_ARGS} --exit-code 0 --list-all-pkgs --format json --output reports/py-trivy.trivy.json ./reports/
      fi
      trivy fs ${PYTHON_TRIVY_ARGS} --format table ./reports/
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    paths:
      - $PYTHON_PROJECT_DIR/reports/
      - "$PYTHON_PROJECT_DIR/reports/py-trivy.*"
      - "$PYTHON_PROJECT_DIR/reports/requirements.txt"
  rules:
    # exclude if $PYTHON_TRIVY_ENABLED not set
    - if: '$PYTHON_TRIVY_ENABLED != "true"'