diff --git a/lifemonitor/api/models/issues/general/lm.py b/lifemonitor/api/models/issues/general/lm.py index 3e219d286..1d029b789 100644 --- a/lifemonitor/api/models/issues/general/lm.py +++ b/lifemonitor/api/models/issues/general/lm.py @@ -22,10 +22,12 @@ import logging -from lifemonitor.utils import get_validation_schema_url from lifemonitor.api.models.issues import IssueMessage, WorkflowRepositoryIssue +from lifemonitor.api.models.issues.general.repo_layout import \ + GitRepositoryWithoutMainBranch from lifemonitor.api.models.repositories import WorkflowRepository from lifemonitor.schemas.validators import ValidationError, ValidationResult +from lifemonitor.utils import get_validation_schema_url # set module level logger logger = logging.getLogger(__name__) @@ -36,6 +38,7 @@ class MissingLMConfigFile(WorkflowRepositoryIssue): description = "No lifemonitor.yaml configuration file found on this repository.
"\ "The lifemonitor.yaml should be placed on the root of this repository." labels = ['lifemonitor'] + depends_on = [GitRepositoryWithoutMainBranch] def check(self, repo: WorkflowRepository) -> bool: if repo.config is None: diff --git a/lifemonitor/api/models/issues/general/repo_layout.py b/lifemonitor/api/models/issues/general/repo_layout.py index 98624d045..556ffbb64 100644 --- a/lifemonitor/api/models/issues/general/repo_layout.py +++ b/lifemonitor/api/models/issues/general/repo_layout.py @@ -24,15 +24,34 @@ from lifemonitor.api.models.issues import WorkflowRepositoryIssue from lifemonitor.api.models.repositories import WorkflowRepository +from lifemonitor.api.models.repositories.local import \ + LocalGitWorkflowRepository # set module level logger logger = logging.getLogger(__name__) +class GitRepositoryWithoutMainBranch(WorkflowRepositoryIssue): + name = "Repository without main branch" + description = "This repository does not have a main branch." + labels = ['best-practices'] + + def check(self, repo: WorkflowRepository) -> bool: + """ + If the repository is a Git repository, check if it has a main branch. + """ + if not LocalGitWorkflowRepository.is_git_repo(repo.local_path): + return False + git_repo = LocalGitWorkflowRepository(repo.local_path) + logger.debug("Local Git repository: %r - branches: %r", git_repo, git_repo.heads) + return git_repo.heads is None or len(git_repo.heads) == 0 + + class RepositoryNotInitialised(WorkflowRepositoryIssue): name = "Repository not intialised" description = "No workflow and crate metadata found on this repository." labels = ['best-practices'] + depends_on = [GitRepositoryWithoutMainBranch] def check(self, repo: WorkflowRepository) -> bool: return repo.find_workflow() is None and repo.metadata is None diff --git a/lifemonitor/api/models/repositories/local.py b/lifemonitor/api/models/repositories/local.py index 6a8e9d2a5..b594868ab 100644 --- a/lifemonitor/api/models/repositories/local.py +++ b/lifemonitor/api/models/repositories/local.py @@ -301,7 +301,8 @@ def __init__(self, self._remote_repo_info = None try: self._remote_repo_info = RemoteGitRepoInfo.parse(self._git_repo.remotes.origin.url) - except git.exc.GitCommandError as e: + except (git.exc.GitCommandError, AttributeError) as e: + logger.warning("Unable to parse remote repository info: %s", e) if logger.isEnabledFor(logging.DEBUG): logger.exception(e) @@ -309,6 +310,14 @@ def __init__(self, def main_branch(self) -> str: return self._git_repo.active_branch.name + @property + def remotes(self) -> List[str]: + return [r.name for r in self._git_repo.remotes] + + @property + def heads(self) -> List[str]: + return [h.name for h in self._git_repo.heads] + @property def owner(self) -> str: return super().owner or \ diff --git a/lifemonitor/utils.py b/lifemonitor/utils.py index 830f6a557..d6b9187f2 100644 --- a/lifemonitor/utils.py +++ b/lifemonitor/utils.py @@ -807,7 +807,8 @@ class RemoteGitRepoInfo(giturlparse.result.GitUrlParsed): def __init__(self, parsed_info): # fix for giturlparse: protocols are not parsed correctly - del parsed_info['protocols'] + if 'protocols' in parsed_info: + del parsed_info['protocols'] super().__init__(parsed_info) @property