Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PYSCAN-41 Implement and test handling of duplicate arguments #26

Merged
merged 2 commits into from
Dec 22, 2023

Conversation

guillaume-dequenne-sonarsource
Copy link
Contributor

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource commented Dec 21, 2023

In the sonar-scanner-cli, CLI arguments take precedence over the ones located in sonar-project.properties files. Also when duplicated CLI arguments are provided, the last one to be defined takes precedence over the older ones.

Because arguments derived from pyproject.toml files are passed from the wrapper to the sonar-scanner-cli as command line arguments, they will naturally take precedence over the ones in sonar-project.properties. Since only arguments under the tool.sonar key are considered, this should provide a good user experience.

To ensure CLI arguments to the wrapper keep their precedence over pyproject.toml ones, they are passed last to the sonar-scanner-cli.

We might want to revisit this logic if we decide to derive analysis properties from other elements from pyproject.toml files that are not under the tool.sonar key (e.g: project name, etc...), as we don't want to force users to provide CLI arguments to override these.

Copy link

sonarcloud bot commented Dec 21, 2023

Copy link
Contributor

@jdodinh jdodinh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I suggested a refactor. LMKWYT.

self.scan_arguments = self._read_toml_args()
# If duplicate properties are provided, newer values will override older ones.
# We therefore read CLI arguments last so that they have priority over toml configuration.
self.scan_arguments.extend(sys.argv[1:])
Copy link
Contributor

@jdodinh jdodinh Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to mention something I meant to mention in Maksim's PR, but that I didn't have a chance to. It is a bit unrelated to this PR, however the fix is small, therefore I think it might still be worth to incorporate this.

Currently, we have that sys.argv[1:] is being parsed in _read_wrapper_arguments, and relevant argument are fetched there. Therefore I don't really see why self.scan_arguments needs to be extended by the entire sys.argv[1:], because I think that we would be passing irrelevant argument to the scanner (such as the .toml, or the debug property, which I believe are only relevant for the wrapper).

Therefore as a refactor I suggest making use of the fact that ArgumentParser.parse_known_args's second return value is all the arguments that couldn't be parsed, and therefore the only ones necessary to be passed down to the cli. I suggest the following:

    def setup(self) -> None:
        """This is executed when run from the command line"""
        self. wrapper_arguments, remaining_args = self._read_wrapper_arguments()
        ApplicationLogger.set_debug(self.is_debug())
        self.scan_arguments = self._read_toml_args()
        # If duplicate properties are provided, newer values will override older ones.
        # We therefore read CLI arguments last so that they have priority over toml configuration.
        self.scan_arguments.extend(remaining_args)

    def _read_wrapper_arguments(self):
        argument_parser = argparse.ArgumentParser()
        argument_parser.add_argument("-toml.path", "-Dtoml.path", "--toml.path", dest="toml_path")
        argument_parser.add_argument("-project.home", "-Dproject.home", "--project.home", dest="project_home")
        argument_parser.add_argument("-X", action="store_true", dest="debug")
        return argument_parser.parse_known_args(args=sys.argv[1:])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good point.

However we should remember some arguments are actually used by both the wrapper and the sonar-scanner-cli, for instance the project.home or the -X flag. Also we should make sure that we don't risk filtering out properties that may one day become relevant for sonar-scanner-cli (for instance, what if toml files were eventually supported natively by the sonar-scanner-cli?).

As discussed, I created PYSCAN-43 to ensure we are at least intentional on this point.

configuration.setup()
self.assertListEqual(
configuration.scan_arguments,
[f"-Dtoml.path={CURRENT_DIR}/resources/pyproject.toml", "-Dsonar.a=b", "-Dsonar.c=d"],
["-Dsonar.a=b", "-Dsonar.c=d", f"-Dtoml.path={CURRENT_DIR}/resources/pyproject.toml"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to my comment about refactoring, I don't really see why the toml path needs to be passed down to the scanner. It seems only relevant to the wrapper, and therefore I think some of the test cases might need to be changed to reflect this logic.

toml_file_path = os.path.join(CURRENT_DIR, "resources", TEST_TOML_FILE)
mock_sys.argv = [SAMPLE_SCANNER_PATH, f"-Dtoml.path={toml_file_path}", "-Dsonar.property1=value1"]
configuration.setup()
self.assertListEqual(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, and same for line 173

toml_file_path = os.path.join(CURRENT_DIR, "resources", "test_toml_file.toml")
mock_sys.argv = ["path/to/scanner/py-sonar-scanner", f"-Dtoml.path={toml_file_path}"]
toml_file_path = os.path.join(CURRENT_DIR, "resources", TEST_TOML_FILE)
mock_sys.argv = [SAMPLE_SCANNER_PATH, f"-Dtoml.path={toml_file_path}"]
configuration.setup()
self.assertListEqual(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource merged commit 83c7b37 into master Dec 22, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants