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

projects_cli tests #1554

Merged
merged 28 commits into from
Jan 5, 2025
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
27 changes: 11 additions & 16 deletions cli/projects_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,16 @@ def __export_projects(endpoint: platform.Platform, **kwargs) -> None:

def __check_sq_environments(import_sq: platform.Platform, export_sq: dict[str, str]) -> None:
"""Checks if export and import environments are compatibles"""
imp_version = utilities.version_to_string(import_sq.version(digits=2))
if imp_version != export_sq["version"]:
raise exceptions.UnsupportedOperation("Export was not performed with same SonarQube version, aborting...")
for export_plugin in export_sq["plugins"]:
e_name = export_plugin["name"]
e_vers = export_plugin["version"]
found = False
for import_plugin in import_sq.plugins():
if import_plugin["name"] == e_name and import_plugin["version"] == e_vers:
found = True
break
if not found:
raise exceptions.UnsupportedOperation(
f"Plugin '{e_name}' version '{e_vers}' was not found or not in same version on import platform, aborting..."
)
imp_version = import_sq.version()[:2]
exp_version = tuple(int(n) for n in export_sq["version"].split(".")[:2])
if imp_version != exp_version:
raise exceptions.UnsupportedOperation(
f"Export was not performed with same SonarQube version, aborting... ({utilities.version_to_string(exp_version)} vs {utilities.version_to_string(imp_version)})"
)
if export_sq["plugins"] != import_sq.plugins():
raise exceptions.UnsupportedOperation(
f"Plugin list is different on the import and export platforms ({str(export_sq['plugins'])} vs {str(import_sq.plugins())}), aborting..."
)


def __import_projects(endpoint: platform.Platform, **kwargs) -> None:
Expand Down Expand Up @@ -99,7 +94,7 @@ def __import_projects(endpoint: platform.Platform, **kwargs) -> None:
else:
statuses[s] = 1
i += 1
log.info("%d/%d exports (%d%%) - Latest: %s - %s", i, nb_projects, int(i * 100 / nb_projects), project["key"], status)
log.info("%d/%d exports (%d%%) - Latest: %s - %s", i, nb_projects, int(i * 100 / nb_projects), project["key"], s)
log.info("%s", ", ".join([f"{k}:{v}" for k, v in statuses.items()]))


Expand Down
11 changes: 6 additions & 5 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
sonar.organization=okorach
sonar.projectKey=okorach_sonar-tools
sonar.projectName=Sonar Tools
sonar.python.version=3.9

# Comma-separated paths to directories with sources (required)
sonar.sources=.
sonar.sources=sonar, cli, migration, setup.py, setup_migration.py

# Encoding of the source files
sonar.sourceEncoding=UTF-8
sonar.exclusions=**/*.csv, **/*.xls*, tests-it/*, tmp/*, **/*.json
sonar.python.version=3.9
sonar.exclusions=doc/api/**/*, build/**/*
sonar.python.flake8.reportPaths=build/flake8-report.out
sonar.python.pylint.reportPaths=build/pylint-report.out
sonar.sarifReportPaths=build/results_sarif.sarif
# sonar.externalIssuesReportPaths=build/shellcheck.json,build/trivy.json
# sonar.python.bandit.reportPaths=build/bandit-report.json

sonar.exclusions=doc/api/**/*, build/**/*, test/**/*
sonar.tests=test/latest, test/lts
sonar.coverage.exclusions=setup*.py, test/**/*, conf/*2sonar.py, cli/cust_measures.py, sonar/custom_measures.py, cli/support.py, cli/projects_export.py, cli/projects_import.py

sonar.cpd.exclusions=setup*.py
sonar.tests=test/unit
35 changes: 17 additions & 18 deletions sonar/issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,20 +574,20 @@ def component_filter(endpoint: pf.Platform) -> str:
return COMPONENT_FILTER_OLD


def __search_all_by_directories(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
def search_by_directory(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
"""Searches issues splitting by directory to avoid exceeding the 10K limit"""
new_params = params.copy()
facets = _get_facets(endpoint=endpoint, project_key=new_params[component_filter(endpoint)], facets="directories", params=new_params)
issue_list = {}
log.info("Splitting search by directories")
for d in facets["directories"]:
new_params["directories"] = d["val"]
issue_list.update(search(endpoint=endpoint, params=new_params, raise_error=False))
issue_list.update(search(endpoint=endpoint, params=new_params, raise_error=True))
log.debug("Search by directory ALL: %d issues found", len(issue_list))
return issue_list


def __search_all_by_types(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
def search_by_type(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
"""Searches issues splitting by type to avoid exceeding the 10K limit"""
issue_list = {}
new_params = params.copy()
Expand All @@ -598,12 +598,12 @@ def __search_all_by_types(endpoint: pf.Platform, params: ApiParams) -> dict[str,
issue_list.update(search(endpoint=endpoint, params=new_params))
except TooManyIssuesError:
log.info(_TOO_MANY_ISSUES_MSG)
issue_list.update(__search_all_by_directories(endpoint=endpoint, params=new_params))
issue_list.update(search_by_directory(endpoint=endpoint, params=new_params))
log.debug("Search by type ALL: %d issues found", len(issue_list))
return issue_list


def __search_all_by_severities(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
def search_by_severity(endpoint: pf.Platform, params: ApiParams) -> dict[str, Issue]:
"""Searches issues splitting by severity to avoid exceeding the 10K limit"""
issue_list = {}
new_params = params.copy()
Expand All @@ -614,14 +614,12 @@ def __search_all_by_severities(endpoint: pf.Platform, params: ApiParams) -> dict
issue_list.update(search(endpoint=endpoint, params=new_params))
except TooManyIssuesError:
log.info(_TOO_MANY_ISSUES_MSG)
issue_list.update(__search_all_by_types(endpoint=endpoint, params=new_params))
issue_list.update(search_by_type(endpoint=endpoint, params=new_params))
log.debug("Search by severity ALL: %d issues found", len(issue_list))
return issue_list


def __search_all_by_date(
endpoint: pf.Platform, params: ApiParams, date_start: Optional[date] = None, date_stop: Optional[date] = None
) -> dict[str, Issue]:
def search_by_date(endpoint: pf.Platform, params: ApiParams, date_start: Optional[date] = None, date_stop: Optional[date] = None) -> dict[str, Issue]:
"""Searches issues splitting by date windows to avoid exceeding the 10K limit"""
new_params = params.copy()
if date_start is None:
Expand All @@ -648,15 +646,15 @@ def __search_all_by_date(
diff = (date_stop - date_start).days
if diff == 0:
log.info(_TOO_MANY_ISSUES_MSG)
issue_list = __search_all_by_severities(endpoint, new_params)
issue_list = search_by_severity(endpoint, new_params)
elif diff == 1:
issue_list.update(__search_all_by_date(endpoint=endpoint, params=new_params, date_start=date_start, date_stop=date_start))
issue_list.update(__search_all_by_date(endpoint=endpoint, params=new_params, date_start=date_stop, date_stop=date_stop))
issue_list.update(search_by_date(endpoint=endpoint, params=new_params, date_start=date_start, date_stop=date_start))
issue_list.update(search_by_date(endpoint=endpoint, params=new_params, date_start=date_stop, date_stop=date_stop))
else:
date_middle = date_start + timedelta(days=diff // 2)
issue_list.update(__search_all_by_date(endpoint=endpoint, params=new_params, date_start=date_start, date_stop=date_middle))
issue_list.update(search_by_date(endpoint=endpoint, params=new_params, date_start=date_start, date_stop=date_middle))
date_middle = date_middle + timedelta(days=1)
issue_list.update(__search_all_by_date(endpoint=endpoint, params=new_params, date_start=date_middle, date_stop=date_stop))
issue_list.update(search_by_date(endpoint=endpoint, params=new_params, date_start=date_middle, date_stop=date_stop))
if date_start is not None and date_stop is not None:
log.debug(
"Project '%s' has %d issues between %s and %s",
Expand All @@ -678,7 +676,7 @@ def __search_all_by_project(endpoint: pf.Platform, project_key: str, params: Api
issue_list.update(search(endpoint=endpoint, params=new_params))
except TooManyIssuesError:
log.info(_TOO_MANY_ISSUES_MSG)
issue_list.update(__search_all_by_date(endpoint=endpoint, params=new_params))
issue_list.update(search_by_date(endpoint=endpoint, params=new_params))
return issue_list


Expand Down Expand Up @@ -766,11 +764,10 @@ def search_first(endpoint: pf.Platform, **params) -> Union[Issue, None]:
"""
filters = pre_search_filters(endpoint=endpoint, params=params)
filters["ps"] = 1
data = json.loads(endpoint.get(Issue.API[c.SEARCH], params=filters).text)
data = json.loads(endpoint.get(Issue.API[c.SEARCH], params=filters).text)["issues"]
if len(data) == 0:
return None
i = data["issues"][0]
return get_object(endpoint=endpoint, key=i["key"], data=i)
return get_object(endpoint=endpoint, key=data[0]["key"], data=data[0])


def search(endpoint: pf.Platform, params: ApiParams = None, raise_error: bool = True, threads: int = 8) -> dict[str, Issue]:
Expand Down Expand Up @@ -821,6 +818,8 @@ def search(endpoint: pf.Platform, params: ApiParams = None, raise_error: bool =

def _get_facets(endpoint: pf.Platform, project_key: str, facets: str = "directories", params: ApiParams = None) -> dict[str, str]:
"""Returns the facets of a search"""
if not params:
params = {}
params.update({component_filter(endpoint): project_key, "facets": facets, "ps": Issue.MAX_PAGE_SIZE, "additionalFields": "comments"})
filters = pre_search_filters(endpoint=endpoint, params=params)
data = json.loads(endpoint.get(Issue.API[c.SEARCH], params=filters).text)
Expand Down
22 changes: 11 additions & 11 deletions sonar/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __init__(self, url: str, token: str, org: str = None, cert_file: Optional[st
self.__cert_file = cert_file
self.__user_data = None
self._version = None
self.__sys_info = None
self._sys_info = None
self.__global_nav = None
self._server_id = None
self._permissions = None
Expand Down Expand Up @@ -147,8 +147,8 @@ def server_id(self) -> str:
"""
if self._server_id is not None:
return self._server_id
if self.__sys_info is not None and _SERVER_ID_KEY in self.__sys_info["System"]:
self._server_id = self.__sys_info["System"][_SERVER_ID_KEY]
if self._sys_info is not None and _SERVER_ID_KEY in self._sys_info["System"]:
self._server_id = self._sys_info["System"][_SERVER_ID_KEY]
else:
self._server_id = json.loads(self.get("system/status").text)["id"]
return self._server_id
Expand Down Expand Up @@ -307,7 +307,7 @@ def sys_info(self) -> dict[str, any]:
"""
if self.is_sonarcloud():
return {"System": {_SERVER_ID_KEY: "sonarcloud"}}
if self.__sys_info is None:
if self._sys_info is None:
success, counter = False, 0
while not success:
try:
Expand All @@ -322,9 +322,9 @@ def sys_info(self) -> dict[str, any]:
else:
log.error("%s while getting system info", util.error_msg(e))
raise e
self.__sys_info = json.loads(resp.text)
self._sys_info = json.loads(resp.text)
success = True
return self.__sys_info
return self._sys_info

def global_nav(self) -> dict[str, any]:
"""
Expand All @@ -340,7 +340,7 @@ def database(self) -> str:
:return: the SonarQube platform backend database
"""
if self.is_sonarcloud():
return "postgres"
return "postgresql"
if self.version() < (9, 7, 0):
return self.sys_info()["Statistics"]["database"]["name"]
return self.sys_info()["Database"]["Database"]
Expand Down Expand Up @@ -395,7 +395,7 @@ def reset_setting(self, key: str) -> bool:
:param key: Setting key
:return: Whether the reset was successful or not
"""
return settings.reset_setting(self, key).ok
return settings.reset_setting(self, key)

def set_setting(self, key: str, value: any) -> bool:
"""Sets a platform global setting
Expand All @@ -415,7 +415,7 @@ def __urlstring(self, api: str, params: types.ApiParams, data: str = None) -> st
if isinstance(v, datetime.date):
good_params[k] = util.format_date(v)
elif isinstance(v, (list, tuple, set)):
good_params[k] = ",".join(list(v))
good_params[k] = ",".join([str(x) for x in v])
params_string = "&".join([f"{k}={requests.utils.quote(str(v))}" for k, v in good_params.items()])
if len(params_string) > 0:
url += f"?{params_string}"
Expand All @@ -442,7 +442,7 @@ def export(self, export_settings: types.ConfigSettings, full: bool = False) -> t
"""
log.info("Exporting platform global settings")
json_data = {}
for s in self.__settings(include_not_set=export_settings["EXPORT_DEFAULTS"]).values():
for s in self.__settings(include_not_set=export_settings.get("EXPORT_DEFAULTS", False)).values():
if s.is_internal():
continue
(categ, subcateg) = s.category()
Expand All @@ -451,7 +451,7 @@ def export(self, export_settings: types.ConfigSettings, full: bool = False) -> t
continue
if not s.is_global():
continue
util.update_json(json_data, categ, subcateg, s.to_json(export_settings["INLINE_LISTS"]))
util.update_json(json_data, categ, subcateg, s.to_json(export_settings.get("INLINE_LISTS", True)))

hooks = {}
for wb in self.webhooks().values():
Expand Down
4 changes: 2 additions & 2 deletions sonar/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def reload(self, data: types.ApiPayload) -> None:

def __hash__(self) -> int:
"""Returns object unique ID"""
return hash((self.key, self.component.key if self.component else "", self.endpoint.url))
return hash((self.key, self.component.key if self.component else None, self.endpoint.url))

def __str__(self) -> str:
if self.component is None:
Expand Down Expand Up @@ -548,7 +548,7 @@ def decode(setting_key: str, setting_value: any) -> any:
def reset_setting(endpoint: pf.Platform, setting_key: str, project_key: str = None) -> bool:
"""Resets a setting to its default"""
log.info("Resetting setting '%s", setting_key)
return endpoint.post("settings/reset", params={"key": setting_key, "component": project_key}).ok
return endpoint.post("settings/reset", params={"keys": setting_key, "component": project_key}).ok


def get_component_params(component: object, name: str = "component") -> types.ApiParamss:
Expand Down
Loading
Loading