Skip to content

Commit b148d21

Browse files
Automatically generate documentation for CLI args
1 parent 195304c commit b148d21

File tree

4 files changed

+226
-2
lines changed

4 files changed

+226
-2
lines changed

CLI_ARGS.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Sonar Scanner Python CLI Arguments
2+
3+
## Authentication
4+
5+
| Option | Description |
6+
| ------ | ----------- |
7+
| `--sonar-host-url`, `-Dsonar.host.url` | SonarQube Server base URL. For example, http://localhost:9000 for a local instance of SonarQube Server |
8+
| `--sonar-region`, `-Dsonar.region` | The region to contact, only for SonarQube Cloud |
9+
| `-t`, `--token`, `--sonar-token`, `-Dsonar.token` | Token used to authenticate against the SonarQube Server or SonarQube Cloud |
10+
11+
## Project Configuration
12+
13+
| Option | Description |
14+
| ------ | ----------- |
15+
| `--sonar-project-base-dir`, `-Dsonar.projectBaseDir` | Directory containing the project to be analyzed. Default is the current directory |
16+
| `--sonar-project-description`, `-Dsonar.projectDescription` | Description of the project |
17+
| `--sonar-project-key`, `-Dsonar.projectKey` | Key of the project that usually corresponds to the project name in SonarQube |
18+
| `--sonar-project-name`, `-Dsonar.projectName` | Name of the project in SonarQube |
19+
| `--sonar-project-version`, `-Dsonar.projectVersion` | Version of the project |
20+
| `--sonar-sources`, `-Dsonar.sources` | The analysis scope for main source code (non-test code) in the project |
21+
| `--sonar-tests`, `-Dsonar.tests` | The analysis scope for test source code in the project |
22+
23+
## Analysis Configuration
24+
25+
| Option | Description |
26+
| ------ | ----------- |
27+
| `--sonar-filesize-limit`, `-Dsonar.filesize.limit` | Sets the limit in MB for files to be discarded from the analysis scope if the size is greater than specified |
28+
| `--sonar-python-version`, `-Dsonar.python.version` | Python version used for the project |
29+
| `-v`, `--verbose`, `--no-verbose`, `--sonar-verbose`, `--no-sonar-verbose`, `-Dsonar.verbose` | Increase output verbosity |
30+
31+
## Report Integration
32+
33+
| Option | Description |
34+
| ------ | ----------- |
35+
| `--sonar-external-issues-report-paths`, `-Dsonar.externalIssuesReportPaths` | Comma-delimited list of paths to generic issue reports |
36+
| `--sonar-python-bandit-report-paths`, `--bandit-report-paths`, `-Dsonar.python.bandit.reportPaths` | Comma-separated bandit report paths, relative to project's root |
37+
| `--sonar-python-coverage-report-paths`, `--coverage-report-paths`, `-Dsonar.python.coverage.reportPaths` | Comma-delimited list of paths to coverage reports in the Cobertura XML format. |
38+
| `--sonar-python-flake8-report-paths`, `--flake8-report-paths`, `-Dsonar.python.flake8.reportPaths` | Comma-separated flake8 report paths, relative to project's root |
39+
| `--sonar-python-mypy-report-paths`, `--mypy-report-paths`, `-Dsonar.python.mypy.reportPaths` | Comma-separated mypy report paths, relative to project's root |
40+
| `--sonar-python-pylint-report-path`, `--pylint-report-path`, `-Dsonar.python.pylint.reportPath` | Path to third-parties issues report file for pylint |
41+
| `--sonar-python-ruff-report-paths`, `--ruff-report-paths`, `-Dsonar.python.ruff.reportPaths` | Comma-separated ruff report paths, relative to project's root |
42+
| `--sonar-python-xunit-report-path`, `--xunit-report-path`, `-Dsonar.python.xunit.reportPath` | Path to the report of test execution, relative to project's root |
43+
| `--sonar-python-xunit-skip-details`, `--no-sonar-python-xunit-skip-details`, `--xunit-skip-details`, `--no-xunit-skip-details` | When enabled, the test execution statistics is provided only on project level |
44+
| `--sonar-sarif-report-paths`, `-Dsonar.sarifReportPaths` | Comma-delimited list of paths to SARIF issue reports |
45+
46+
## Other
47+
48+
| Option | Description |
49+
| ------ | ----------- |
50+
| `--skip-jre-provisioning`, `-Dsonar.scanner.skipJreProvisioning` | If provided, the provisioning of the JRE will be skipped |
51+
| `--sonar-branch-name`, `-Dsonar.branch.name` | Name of the branch being analyzed |
52+
| `--sonar-build-string`, `-Dsonar.buildString` | The string passed with this property will be stored with the analysis and available in the results of api/project_analyses/search, thus allowing you to later identify a specific analysis and obtain its key for use with api/new_code_periods/set on the SPECIFIC_ANALYSIS type |
53+
| `--sonar-cpd-python-minimum-lines`, `-Dsonar.cpd.python.minimumLines` | Minimum number of tokens to be considered as a duplicated block of code |
54+
| `--sonar-cpd-python-minimum-tokens`, `-Dsonar.cpd.python.minimumTokens` | Minimum number of tokens to be considered as a duplicated block of code |
55+
| `--sonar-links-ci`, `-Dsonar.links.ci` | The URL of the continuous integration system used |
56+
| `--sonar-links-homepage`, `-Dsonar.links.homepage` | The URL of the build project home page |
57+
| `--sonar-links-issue`, `-Dsonar.links.issue` | The URL to the issue tracker being used |
58+
| `--sonar-links-scm`, `-Dsonar.links.scm` | The URL of the build project source code repository |
59+
| `--sonar-log-level`, `-Dsonar.log.level` | Log level during the analysis |
60+
| `--sonar-modules`, `-Dsonar.modules` | Comma-delimited list of modules to analyze |
61+
| `--sonar-newcode-reference-branch`, `-Dsonar.newCode.referenceBranch` | Reference branch for new code definition |
62+
| `--sonar-pullrequest-base`, `-Dsonar.pullrequest.base` | Base branch of the pull request being analyzed |
63+
| `--sonar-pullrequest-branch`, `-Dsonar.pullrequest.branch` | Branch of the pull request being analyzed |
64+
| `--sonar-pullrequest-key`, `-Dsonar.pullrequest.key` | Key of the pull request being analyzed |
65+
| `--sonar-python-skip-unchanged`, `--no-sonar-python-skip-unchanged` | Override the SonarQube configuration of skipping or not the analysis of unchanged Python files |
66+
| `--sonar-qualitygate-timeout`, `-Dsonar.qualitygate.timeout` | The number of seconds that the scanner should wait for a report to be processed |
67+
| `--sonar-qualitygate-wait`, `--no-sonar-qualitygate-wait` | Forces the analysis step to poll the server instance and wait for the Quality Gate status |
68+
| `--sonar-scanner-api-url`, `-Dsonar.scanner.apiUrl` | Base URL for all REST-compliant API calls, https://api.sonarcloud.io for example |
69+
| `--sonar-scanner-arch`, `-Dsonar.scanner.arch` | Architecture on which the scanner will be running |
70+
| `--sonar-scanner-cloud-url`, `-Dsonar.scanner.cloudUrl` | SonarQube Cloud base URL, https://sonarcloud.io for example |
71+
| `--sonar-scanner-connect-timeout`, `-Dsonar.scanner.connectTimeout` | Time period to establish connections with the server (in seconds) |
72+
| `--sonar-scanner-internal-dump-to-file`, `-Dsonar.scanner.internal.dumpToFile` | Filename where the input to the scanner engine will be dumped. Useful for debugging |
73+
| `--sonar-scanner-internal-sq-version`, `-Dsonar.scanner.internal.sqVersion` | Emulate the result of the call to get SQ server version. Useful for debugging with --sonar-scanner-internal-dump-to-file |
74+
| `--sonar-scanner-java-exe-path`, `-Dsonar.scanner.javaExePath` | If defined, the scanner engine will be run with this JRE |
75+
| `--sonar-scanner-java-opts`, `-Dsonar.scanner.javaOpts` | Arguments provided to the JVM when running the scanner |
76+
| `--sonar-scanner-keystore-password`, `-Dsonar.scanner.keystorePassword` | Password to access the keystore |
77+
| `--sonar-scanner-keystore-path`, `-Dsonar.scanner.keystorePath` | Path to the keystore containing the client certificates used by the scanner. By default, <sonar.userHome>/ssl/keystore.p12 |
78+
| `--sonar-scanner-metadata-filepath`, `-Dsonar.scanner.metadataFilepath` | Sets the location where the scanner writes the report-task.txt file containing among other things the ceTaskId |
79+
| `--sonar-scanner-os`, `-Dsonar.scanner.os` | OS running the scanner |
80+
| `--sonar-scanner-proxy-host`, `-Dsonar.scanner.proxyHost` | Proxy host |
81+
| `--sonar-scanner-proxy-password`, `-Dsonar.scanner.proxyPassword` | Proxy password |
82+
| `--sonar-scanner-proxy-port`, `-Dsonar.scanner.proxyPort` | Proxy port |
83+
| `--sonar-scanner-proxy-user`, `-Dsonar.scanner.proxyUser` | Proxy user |
84+
| `--sonar-scanner-response-timeout`, `-Dsonar.scanner.responseTimeout` | Time period required to process an HTTP call: from sending a request to receiving a response (in seconds) |
85+
| `--sonar-scanner-socket-timeout`, `-Dsonar.scanner.socketTimeout` | Maximum time of inactivity between two data packets when exchanging data with the server (in seconds) |
86+
| `--sonar-scanner-truststore-password`, `-Dsonar.scanner.truststorePassword` | Password to access the truststore |
87+
| `--sonar-scanner-truststore-path`, `-Dsonar.scanner.truststorePath` | Path to the keystore containing trusted server certificates, used by the Scanner in addition to OS and the built-in certificates |
88+
| `--sonar-scm-exclusions-disabled`, `--no-sonar-scm-exclusions-disabled` | Defines whether files ignored by the SCM, e.g., files listed in .gitignore, will be excluded from the analysis or not |
89+
| `--sonar-scm-force-reload-all`, `--no-sonar-scm-force-reload-all` | Set this property to true to load blame information for all files, which may significantly increase analysis duration |
90+
| `--sonar-scm-revision`, `-Dsonar.scm.revision` | Overrides the revision, for instance, the Git sha1, displayed in analysis results |
91+
| `--sonar-source-encoding`, `-Dsonar.sourceEncoding` | Encoding of the source files. For example, UTF-8, MacRoman, Shift_JIS |
92+
| `--sonar-user-home`, `-Dsonar.userHome` | Base sonar directory, ~/.sonar by default |
93+
| `--sonar-working-directory`, `-Dsonar.working.directory` | Path to the working directory used by the Sonar scanner during a project analysis to store temporary data |
94+
| `--toml-path` | Path to the pyproject.toml file. If not provided, it will look in the SONAR_PROJECT_BASE_DIR |
95+
| `-Dsonar.python.skipUnchanged` | Equivalent to --sonar-python-skip-unchanged |
96+
| `-Dsonar.python.xunit.skipDetails` | Equivalent to -Dsonar.python.xunit.skipDetails |
97+
| `-Dsonar.qualitygate.wait` | Equivalent to --sonar-qualitygate-wait |
98+
| `-Dsonar.scm.exclusions.disabled` | Equivalent to --sonar-scm-exclusions-disabled |
99+
| `-Dsonar.scm.forceReloadAll` | Equivalent to --sonar-scm-force-reload-all |

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ $ pysonar -Dsonar.token=myAuthenticationToken
4444
You can use all the arguments allowed by __SonarScanner__.
4545
For more information on __SonarScanner__ please refer to the [SonarScanner documentation](https://docs.sonarsource.com/sonarqube-server/2025.1/analyzing-source-code/analysis-parameters/).
4646

47-
Additionally, some common properties can be provided using
47+
Additionally, some common properties can be provided using a shorter alias, such as:
48+
```
49+
pysonar --token "MyToken"
50+
```
51+
52+
See [CLI_ARGS](CLI_ARGS.md) for more details.
4853

4954
### With a pyproject.toml file
5055

src/pysonar_scanner/configuration/cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ def load(cls) -> dict[str, any]:
5050

5151
@classmethod
5252
def __parse_cli_args(cls) -> tuple[argparse.Namespace, list[str]]:
53+
parser = cls.__create_parser()
54+
return parser.parse_known_args()
55+
56+
@classmethod
57+
def __create_parser(cls):
5358
parser = argparse.ArgumentParser(
5459
description="Sonar scanner CLI for Python",
5560
epilog="Analysis properties not listed here will also be accepted, as long as they start with the -D prefix.",
@@ -487,4 +492,4 @@ def __parse_cli_args(cls) -> tuple[argparse.Namespace, list[str]]:
487492
"--sonar-modules", "-Dsonar.modules", type=str, help="Comma-delimited list of modules to analyze"
488493
)
489494

490-
return parser.parse_known_args()
495+
return parser
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to generate CLI documentation from the argument parser.
4+
Usage:
5+
python generate_cli_documentation.py
6+
"""
7+
8+
import sys
9+
from pathlib import Path
10+
11+
12+
def generate_cli_docs():
13+
# Add the src directory to the path so we can import the modules
14+
sys.path.insert(0, str(find_project_root() / "src"))
15+
from pysonar_scanner.configuration.cli import CliConfigurationLoader
16+
17+
"""Generate markdown documentation for CLI arguments."""
18+
parser = CliConfigurationLoader._CliConfigurationLoader__create_parser()
19+
20+
# Group arguments by category
21+
categories = {
22+
"Authentication": ["token", "sonar_host_url", "sonar_region"],
23+
"Project Configuration": [
24+
"sonar_project_key",
25+
"sonar_project_name",
26+
"sonar_project_version",
27+
"sonar_project_description",
28+
"sonar_project_base_dir",
29+
"sonar_sources",
30+
"sonar_tests",
31+
],
32+
"Analysis Configuration": ["verbose", "sonar_python_version", "sonar_filesize_limit"],
33+
"Report Integration": [
34+
"sonar_python_coverage_report_paths",
35+
"sonar_python_pylint_report_path",
36+
"sonar_sarif_report_paths",
37+
"sonar_python_xunit_report_path",
38+
"sonar_python_xunit_skip_details",
39+
"sonar_python_mypy_report_paths",
40+
"sonar_python_bandit_report_paths",
41+
"sonar_python_flake8_report_paths",
42+
"sonar_python_ruff_report_paths",
43+
"sonar_external_issues_report_paths",
44+
"coverage_report_paths",
45+
"pylint_report_path",
46+
"xunit_report_path",
47+
"xunit_skip_details",
48+
"mypy_report_paths",
49+
"bandit_report_paths",
50+
"flake8_report_paths",
51+
"ruff_report_paths",
52+
],
53+
"Other": [], # Will contain everything else
54+
}
55+
56+
grouped_actions = {category: [] for category in categories}
57+
58+
# Group actions by category
59+
for action in parser._actions:
60+
if action.dest == "help":
61+
continue
62+
63+
categorized = False
64+
for category, dest_prefixes in categories.items():
65+
for prefix in dest_prefixes:
66+
if action.dest.startswith(prefix):
67+
grouped_actions[category].append(action)
68+
categorized = True
69+
break
70+
if categorized:
71+
break
72+
73+
if not categorized:
74+
grouped_actions["Other"].append(action)
75+
76+
# Generate markdown
77+
lines = ["# Sonar Scanner Python CLI Arguments", ""]
78+
79+
for category, actions in grouped_actions.items():
80+
if not actions:
81+
continue
82+
83+
lines.append(f"## {category}")
84+
lines.append("")
85+
lines.append("| Option | Description |")
86+
lines.append("| ------ | ----------- |")
87+
88+
for action in sorted(actions, key=lambda a: a.option_strings[0] if a.option_strings else ""):
89+
options = ", ".join(f"`{opt}`" for opt in action.option_strings)
90+
help_text = action.help or ""
91+
lines.append(f"| {options} | {help_text} |")
92+
93+
lines.append("")
94+
95+
return "\n".join(lines)
96+
97+
98+
def find_project_root():
99+
"""Find the project root by looking for pyproject.toml"""
100+
current_dir = Path(__file__).resolve().parent
101+
while current_dir != current_dir.parent:
102+
if (current_dir / "pyproject.toml").exists():
103+
return current_dir
104+
current_dir = current_dir.parent
105+
raise FileNotFoundError("Could not find project root (no pyproject.toml found)")
106+
107+
108+
if __name__ == "__main__":
109+
docs = generate_cli_docs()
110+
111+
project_root = find_project_root()
112+
output_path = project_root / "CLI_ARGS.md"
113+
114+
with open(output_path, "w") as f:
115+
f.write(docs)

0 commit comments

Comments
 (0)