Skip to content
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: 2 additions & 0 deletions CLI_ARGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
| `--sonar-pullrequest-base`, `-Dsonar.pullrequest.base` | Base branch of the pull request being analyzed |
| `--sonar-pullrequest-branch`, `-Dsonar.pullrequest.branch` | Branch of the pull request being analyzed |
| `--sonar-pullrequest-key`, `-Dsonar.pullrequest.key` | Key of the pull request being analyzed |
| `--sonar-python-analysis-parallel`, `--no-sonar-python-analysis-parallel`, `--analysis-in-parallel`, `--no-analysis-in-parallel`, `-Dsonar.python.analysis.parallel` | When set to False the analysis will be single threaded |
| `--sonar-python-analysis-threads`, `--nr-analysis-threads`, `-Dsonar.python.analysis.threads` | Set the number of threads to use during analysis. This property is ignored if --sonar-python-analysis-parallel is set to False |
| `--sonar-python-skip-unchanged`, `--no-sonar-python-skip-unchanged` | Override the SonarQube configuration of skipping or not the analysis of unchanged Python files |
| `--sonar-qualitygate-timeout`, `-Dsonar.qualitygate.timeout` | The number of seconds that the scanner should wait for a report to be processed |
| `--sonar-qualitygate-wait`, `--no-sonar-qualitygate-wait` | Forces the analysis step to poll the server instance and wait for the Quality Gate status |
Expand Down
16 changes: 16 additions & 0 deletions src/pysonar_scanner/configuration/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ def __create_parser(cls):
"--sonar-modules", "-Dsonar.modules", type=str, help="Comma-delimited list of modules to analyze"
)

parser.add_argument(
"--sonar-python-analysis-parallel",
"--analysis-in-parallel",
"-Dsonar.python.analysis.parallel",
type=bool,
action=argparse.BooleanOptionalAction,
help="When set to False the analysis will be single threaded",
)
parser.add_argument(
"--sonar-python-analysis-threads",
"--nr-analysis-threads",
"-Dsonar.python.analysis.threads",
type=int,
help="Set the number of threads to use during analysis. This property is ignored if --sonar-python-analysis-parallel is set to False",
)

server_connection_group = parser.add_argument_group("SonarQube Connection")
server_connection_group.add_argument(
"--sonar-host-url",
Expand Down
14 changes: 13 additions & 1 deletion src/pysonar_scanner/configuration/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
SONAR_WORKING_DIRECTORY: Key = "sonar.working.directory"
SONAR_SCM_FORCE_RELOAD_ALL: Key = "sonar.scm.forceReloadAll"
SONAR_MODULES: Key = "sonar.modules"
SONAR_PYTHON_ANALYSIS_PARALLEL: Key = "sonar.python.analysis.parallel"
SONAR_PYTHON_ANALYSIS_THREADS: Key = "sonar.python.analysis.threads"
SONAR_PYTHON_XUNIT_REPORT_PATH: Key = "sonar.python.xunit.reportPath"
SONAR_PYTHON_XUNIT_SKIP_DETAILS: Key = "sonar.python.xunit.skipDetails"
SONAR_PYTHON_MYPY_REPORT_PATHS: Key = "sonar.python.mypy.reportPaths"
Expand Down Expand Up @@ -541,6 +543,16 @@ def env_variable_name(self) -> str:
default_value=None,
cli_getter=None,
deprecation_message="SONAR_SCANNER_OPTS is deprecated, please use SONAR_SCANNER_JAVA_OPTS instead."
)
),
Property(
name=SONAR_PYTHON_ANALYSIS_PARALLEL,
default_value=None,
cli_getter=lambda args: args.sonar_python_analysis_parallel
),
Property(
name=SONAR_PYTHON_ANALYSIS_THREADS,
default_value=None,
cli_getter=lambda args: args.sonar_python_analysis_threads
),
]
# fmt: on
39 changes: 39 additions & 0 deletions tests/unit/test_configuration_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
from pysonar_scanner.configuration.properties import (
SONAR_HOST_URL,
SONAR_ORGANIZATION,
SONAR_PYTHON_ANALYSIS_PARALLEL,
SONAR_PYTHON_ANALYSIS_THREADS,
SONAR_PYTHON_BANDIT_REPORT_PATHS,
SONAR_PYTHON_FLAKE8_REPORT_PATHS,
SONAR_PYTHON_MYPY_REPORT_PATHS,
Expand Down Expand Up @@ -159,6 +161,8 @@
SONAR_PYTHON_COVERAGE_REPORT_PATHS: "path/to/coverage1,path/to/coverage2",
SONAR_COVERAGE_EXCLUSIONS: "*/.local/*,/usr/*,utils/tirefire.py",
SONAR_PYTHON_SKIP_UNCHANGED: True,
SONAR_PYTHON_ANALYSIS_PARALLEL: True,
SONAR_PYTHON_ANALYSIS_THREADS: 2,
SONAR_PYTHON_XUNIT_REPORT_PATH: "path/to/xunit/report",
SONAR_PYTHON_XUNIT_SKIP_DETAILS: True,
SONAR_PYTHON_MYPY_REPORT_PATHS: "path/to/mypy/reports",
Expand Down Expand Up @@ -207,6 +211,36 @@ def test_alternative_cli_args(self):
}
self.assertDictEqual(configuration, expected_configuration)

def test_alternative_analysis_threads_cli_args(self):
base_args = ["myscript.py", "-t", "myToken", "--sonar-project-key", "myProjectKey"]
report_args = ["--nr-analysis-threads", "3"]

expected_configuration = {
SONAR_TOKEN: "myToken",
SONAR_PROJECT_KEY: "myProjectKey",
SONAR_PYTHON_ANALYSIS_THREADS: 3,
}

with patch("sys.argv", base_args + report_args), patch("sys.stderr", new=StringIO()):
configuration = CliConfigurationLoader.load()
self.assertDictEqual(configuration, expected_configuration)

def test_alternative_analysis_single_threaded_cli_args(self):
base_args = ["myscript.py", "-t", "myToken", "--sonar-project-key", "myProjectKey"]
report_args = [
"--no-analysis-in-parallel",
]

expected_configuration = {
SONAR_TOKEN: "myToken",
SONAR_PROJECT_KEY: "myProjectKey",
SONAR_PYTHON_ANALYSIS_PARALLEL: False,
}

with patch("sys.argv", base_args + report_args), patch("sys.stderr", new=StringIO()):
configuration = CliConfigurationLoader.load()
self.assertDictEqual(configuration, expected_configuration)

def test_alternative_report_cli_args(self):
base_args = ["myscript.py", "-t", "myToken", "--sonar-project-key", "myProjectKey"]
report_args = [
Expand Down Expand Up @@ -404,6 +438,9 @@ def test_impossible_os_choice(self):
"module1,module2",
"--sonar-scanner-java-heap-size",
"8000Mb",
"--analysis-in-parallel",
"--nr-analysis-threads",
"2",
],
)
def test_all_cli_args(self):
Expand Down Expand Up @@ -474,6 +511,8 @@ def test_all_cli_args(self):
"-Dsonar.python.pylint.reportPath=path/to/pylint/report",
"-Dsonar.python.coverage.reportPaths=path/to/coverage1,path/to/coverage2",
"-Dsonar.coverage.exclusions=*/.local/*,/usr/*,utils/tirefire.py",
"-Dsonar.python.analysis.parallel",
"-Dsonar.python.analysis.threads=2",
"-Dsonar.python.skipUnchanged=true",
"-Dsonar.python.xunit.reportPath=path/to/xunit/report",
"-Dsonar.python.xunit.skipDetails=true",
Expand Down