Skip to content

Commit 2015180

Browse files
Automatically generate documentation for CLI args
1 parent 642d2ee commit 2015180

File tree

3 files changed

+218
-1
lines changed

3 files changed

+218
-1
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

generate_cli_documentation.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
"""Script to generate CLI documentation from the argument parser."""
3+
4+
import sys
5+
import os
6+
import argparse
7+
from pathlib import Path
8+
9+
# Add the src directory to the path so we can import the modules
10+
sys.path.insert(0, str(Path(__file__).parent / "src"))
11+
12+
from pysonar_scanner.configuration.cli import CliConfigurationLoader
13+
14+
def generate_cli_docs():
15+
"""Generate markdown documentation for CLI arguments."""
16+
# Use monkey patching to capture the parser without modifying the original code
17+
original_parse_known_args = argparse.ArgumentParser.parse_known_args
18+
captured_parser = None
19+
20+
def capture_parser(self, *args, **kwargs):
21+
nonlocal captured_parser
22+
captured_parser = self
23+
# Return a mock result that won't be used
24+
return argparse.Namespace(), []
25+
26+
try:
27+
# Replace the parse_known_args method temporarily
28+
argparse.ArgumentParser.parse_known_args = capture_parser
29+
30+
# Call the method which will create the parser
31+
# The parser will be captured by our monkey patched method
32+
CliConfigurationLoader._CliConfigurationLoader__parse_cli_args()
33+
finally:
34+
# Restore original method
35+
argparse.ArgumentParser.parse_known_args = original_parse_known_args
36+
37+
parser = captured_parser
38+
39+
# Group arguments by category
40+
categories = {
41+
"Authentication": ["token", "sonar_host_url", "sonar_region"],
42+
"Project Configuration": ["sonar_project_key", "sonar_project_name", "sonar_project_version",
43+
"sonar_project_description", "sonar_project_base_dir", "sonar_sources", "sonar_tests"],
44+
"Analysis Configuration": ["verbose", "sonar_python_version", "sonar_filesize_limit"],
45+
"Report Integration": [
46+
"sonar_python_coverage_report_paths",
47+
"sonar_python_pylint_report_path",
48+
"sonar_sarif_report_paths",
49+
"sonar_python_xunit_report_path",
50+
"sonar_python_xunit_skip_details",
51+
"sonar_python_mypy_report_paths",
52+
"sonar_python_bandit_report_paths",
53+
"sonar_python_flake8_report_paths",
54+
"sonar_python_ruff_report_paths",
55+
"sonar_external_issues_report_paths",
56+
"coverage_report_paths",
57+
"pylint_report_path",
58+
"xunit_report_path",
59+
"xunit_skip_details",
60+
"mypy_report_paths",
61+
"bandit_report_paths",
62+
"flake8_report_paths",
63+
"ruff_report_paths"
64+
],
65+
"Other": [] # Will contain everything else
66+
}
67+
68+
grouped_actions = {category: [] for category in categories}
69+
70+
# Group actions by category
71+
for action in parser._actions:
72+
if action.dest == "help":
73+
continue
74+
75+
categorized = False
76+
for category, dest_prefixes in categories.items():
77+
for prefix in dest_prefixes:
78+
if action.dest.startswith(prefix):
79+
grouped_actions[category].append(action)
80+
categorized = True
81+
break
82+
if categorized:
83+
break
84+
85+
if not categorized:
86+
grouped_actions["Other"].append(action)
87+
88+
# Generate markdown
89+
lines = ["# Sonar Scanner Python CLI Arguments", ""]
90+
91+
for category, actions in grouped_actions.items():
92+
if not actions:
93+
continue
94+
95+
lines.append(f"## {category}")
96+
lines.append("")
97+
lines.append("| Option | Description |")
98+
lines.append("| ------ | ----------- |")
99+
100+
for action in sorted(actions, key=lambda a: a.option_strings[0] if a.option_strings else ""):
101+
options = ", ".join(f"`{opt}`" for opt in action.option_strings)
102+
help_text = action.help or ""
103+
lines.append(f"| {options} | {help_text} |")
104+
105+
lines.append("")
106+
107+
return "\n".join(lines)
108+
109+
if __name__ == "__main__":
110+
docs = generate_cli_docs()
111+
112+
with open("CLI_ARGS.md", "w") as f:
113+
f.write(docs)

0 commit comments

Comments
 (0)