diff --git a/galaxy/core/exceptions.py b/galaxy/core/exceptions.py index d8f987a..ceafbcc 100644 --- a/galaxy/core/exceptions.py +++ b/galaxy/core/exceptions.py @@ -6,6 +6,10 @@ class GalaxyError(Exception): """Base class for all Galaxy errors.""" + @property + def error_type(self) -> str: + return self.__class__.__name__ + class GalaxyWarning(GalaxyError): """Base class for all Galaxy warnings.""" diff --git a/galaxy/core/main.py b/galaxy/core/main.py index 236419e..ec66da0 100644 --- a/galaxy/core/main.py +++ b/galaxy/core/main.py @@ -45,6 +45,9 @@ async def main( if dry_run is False: integration_config = await magneto_client.get_plugin(str(config.integration.id)) + # Get the properties from the integration config. Using `pop` to remove them from the original dict + integration_config_properties = integration_config.pop("properties", None) + logger.debug("Config entity from magneto: %r", integration_config) if integration_config["dataSource"].lower() != integration_type: logger.error( @@ -54,9 +57,8 @@ async def main( ) raise Exception("Integration type mismatch between the integration and magneto config") - config_entity_properties = integration_config.get("properties", None) - if config_entity_properties is not None: - for key, value in config_entity_properties.items(): + if integration_config_properties is not None: + for key, value in integration_config_properties.items(): # Only set the property if it doesn't already exist or is empty if not config.integration.properties.get(key) or ( # This OR is to handle the scenario of a nested dict with keys but no values @@ -65,7 +67,6 @@ async def main( ): config.integration.properties[key] = value - logger.debug("Config entity properties: %r", config.integration.properties) if integration_config is None: logger.error("Integration not found in magneto") raise Exception("Integration not found in magneto") diff --git a/galaxy/core/models.py b/galaxy/core/models.py index a5ecfb6..b2f87ce 100644 --- a/galaxy/core/models.py +++ b/galaxy/core/models.py @@ -24,6 +24,9 @@ class RelyConfig(BaseModel): token: str = Field(..., alias="token") url: str = Field(..., alias="url") + def __repr__(self) -> str: + return f"RelyConfig(url={self.url!r})" + class IntegrationConfig(BaseModel): model_config = ConfigDict(extra="forbid") @@ -39,6 +42,18 @@ class IntegrationConfig(BaseModel): wait_for_tasks_enabled: bool = Field(True, alias="waitForTasksEnabled") wait_for_tasks_timeout_seconds: int | None = Field(600, alias="waitForTasksTimeout") + def __repr__(self) -> str: + """Return a string representation of the IntegrationConfig. + + Properties are not included as they may contain sensitive information. + """ + return ( + f"IntegrationConfig(id={self.id}, type={self.type}, execution_type={self.execution_type}, " + f"scheduled_interval={self.scheduled_interval}, default_model_mappings={self.default_model_mappings}, " + f"dry_run={self.dry_run}, wait_for_tasks_enabled={self.wait_for_tasks_enabled}, " + f"wait_for_tasks_timeout_seconds={self.wait_for_tasks_timeout_seconds})" + ) + class Config(BaseModel): @classmethod @@ -52,6 +67,9 @@ def from_yaml(cls, file_path): rely: RelyConfig integration: IntegrationConfig + def __repr__(self) -> str: + return f"Config(rely={self.rely!r}, integration={self.integration!r})" + class FileCheck(BaseModel): path: str diff --git a/galaxy/integrations/gitlab/.rely/automations.json b/galaxy/integrations/gitlab/.rely/automations.json index 9ab6c6d..c3ba491 100644 --- a/galaxy/integrations/gitlab/.rely/automations.json +++ b/galaxy/integrations/gitlab/.rely/automations.json @@ -695,7 +695,8 @@ "updatedAt": "{{ data.properties.updatedAt if data.properties.updatedAt else none }}", "closedAt": "{{ data.properties.finishedAt if data.properties.finishedAt else none }}", "sourceCommit": "{{ data.properties.commit if data.properties.commit else none }}", - "triggeredBy": "{{ actions.fetch_author.output.title if actions.fetch_author else none }}" + "triggeredBy": "{{ actions.fetch_author.output.title if actions.fetch_author else none }}", + "successful": "{{ true if data.properties.status == 'SUCCESS' else false }}" }, "relations": { "service": { diff --git a/galaxy/integrations/gitlab/.rely/mappings.yaml b/galaxy/integrations/gitlab/.rely/mappings.yaml index 1c7885f..f09f8b8 100644 --- a/galaxy/integrations/gitlab/.rely/mappings.yaml +++ b/galaxy/integrations/gitlab/.rely/mappings.yaml @@ -66,7 +66,7 @@ resources: closedAt: .node.closedAt url: .node.webUrl state: .node.state - labels: '[.node.labels.edges[].node.title]' + labels: 'try [.node.labels.edges[].node.title] catch []' relations: repository: value: '"gitlab_repo_" + (.context.repository.id | split("/") | last)' @@ -90,7 +90,7 @@ resources: updatedAt: .node.updatedAt closedAt: .node.closedAt state: .node.state - labels: '[.node.labels.edges[].node.title]' + labels: 'try [.node.labels.edges[].node.title] catch []' sourceBranch: .node.sourceBranch targetBranch: .node.targetBranch mergedAt: .node.mergedAt diff --git a/galaxy/integrations/gitlab/client.py b/galaxy/integrations/gitlab/client.py index 8be9944..7c31808 100644 --- a/galaxy/integrations/gitlab/client.py +++ b/galaxy/integrations/gitlab/client.py @@ -178,16 +178,18 @@ async def get_environments(self, repository: dict) -> list[dict]: self.session, "POST", self.url_graphql, json=query, retry_policy=self.retry_policy ) - environments = data["data"]["project"]["environments"] + environments = data.get("data", {}).get("project", {}).get("environments") if not environments: return all_environments - edges = environments["edges"] + all_environments.extend(environments["edges"]) + page_info = environments["pageInfo"] - all_environments.extend(edges) if not page_info["hasNextPage"]: break + cursor = page_info["endCursor"] + return all_environments async def get_deployments(self, repository: dict, environment: str, history_days: int) -> list[dict]: @@ -294,7 +296,7 @@ async def get_user_by_username(self, username: str) -> dict: data = await make_request(self.session, "POST", self.url_graphql, json=query, retry_policy=self.retry_policy) - return data["data"]["user"] + return data.get("data", {}).get("user", {}) async def get_file(self, repository_path: str, file_path: str) -> dict: query = self.queries.get_file(repository_path, file_path) diff --git a/galaxy/integrations/gitlab/main.py b/galaxy/integrations/gitlab/main.py index 495fcf8..5ca2cf6 100644 --- a/galaxy/integrations/gitlab/main.py +++ b/galaxy/integrations/gitlab/main.py @@ -127,12 +127,12 @@ async def get_repo_files(self, repo_full_path: str) -> dict: if file_check["regex"]: result = re.search(file_check["regex"], file["content"]) if file_check["regex"] else None repo_file_checks[file_check["destination"]] = ( - result.group(1) if result else FileCheckStatus.FILE_FOUND_NO_MATCH + result.group(1) if result else FileCheckStatus.FILE_FOUND_NO_MATCH.value ) else: - repo_file_checks[file_check["destination"]] = FileCheckStatus.FILE_FOUND + repo_file_checks[file_check["destination"]] = FileCheckStatus.FILE_FOUND.value else: - repo_file_checks[file_check["destination"]] = FileCheckStatus.FILE_NOT_FOUND + repo_file_checks[file_check["destination"]] = FileCheckStatus.FILE_NOT_FOUND.value return repo_file_checks diff --git a/galaxy/integrations/snyk/client.py b/galaxy/integrations/snyk/client.py index 7dae2fd..1801dc7 100644 --- a/galaxy/integrations/snyk/client.py +++ b/galaxy/integrations/snyk/client.py @@ -38,7 +38,7 @@ def __init__(self, config: Config, logger: Logger): raise ValueError(f"Invalid Snyk hosting region: {region}") async def __aenter__(self) -> "SnykClient": - self._session = create_session(timeout=30, headers=self._headers, **self._session_kwargs) + self._session = create_session(timeout=60, headers=self._headers, **self._session_kwargs) return self async def __aexit__(self, exc_type: type, exc: Exception, tb: TracebackType) -> None: @@ -79,7 +79,7 @@ async def get_projects(self, org_id: str, target_id: str) -> list[dict]: f"/rest/orgs/{org_id}/projects", params={"target_id": [target_id], "meta.latest_issue_counts": "true"} ) - async def get_issues(self, org_id: str, project_id: str, history_start_date: datetime = None) -> list[dict]: + async def get_issues(self, org_id: str, project_id: str, history_start_date: datetime | None = None) -> list[dict]: params = {"scan_item.type": "project", "scan_item.id": project_id} if history_start_date is not None: params["created_after"] = history_start_date.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" diff --git a/galaxy/integrations/snyk/main.py b/galaxy/integrations/snyk/main.py index f910f0a..facedd2 100644 --- a/galaxy/integrations/snyk/main.py +++ b/galaxy/integrations/snyk/main.py @@ -14,7 +14,7 @@ def __init__(self, config: Config): super().__init__(config) self.client = SnykClient(self.config, self.logger) - self._organizations = [] + self._organizations = {} self._all_projects = [] async def __aenter__(self) -> "Snyk": @@ -66,7 +66,7 @@ async def projects(self) -> tuple[Any]: return mapped_projects @register(_methods, group=3) - async def issues(self) -> tuple[Any]: + async def issues(self) -> list[Any]: organization_target_project_triples = [ ( item["relationships"]["organization"]["data"]["id"],