Skip to content

Commit

Permalink
Merge pull request #147 from ochrstn/feat/gitlab
Browse files Browse the repository at this point in the history
feat(gitlab): added gitlab repository support
  • Loading branch information
christiansiegel committed Feb 1, 2021
2 parents c15cbdc + 139edf1 commit 089c4f2
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ docker run --rm -it baloise/gitopscli --help
For detailed installation and usage instructions, visit [https://baloise.github.io/gitopscli/](https://baloise.github.io/gitopscli/).

## Git Provider Support
Currently, we support both BitBucket Server and GitHub.
Currently, we support BitBucket Server, GitHub and Gitlab.

## License
[Apache-2.0](https://choosealicense.com/licenses/apache-2.0/)
4 changes: 3 additions & 1 deletion gitopscli/cliparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def __parse_yaml(value: str) -> Any:


def __parse_git_provider(value: str) -> GitProvider:
mapping = {"github": GitProvider.GITHUB, "bitbucket-server": GitProvider.BITBUCKET}
mapping = {"github": GitProvider.GITHUB, "bitbucket-server": GitProvider.BITBUCKET, "gitlab": GitProvider.GITLAB}
assert set(mapping.values()) == set(GitProvider), "git provider mapping not exhaustive"
lowercase_stripped_value = value.lower().strip()
if lowercase_stripped_value not in mapping:
Expand All @@ -270,6 +270,8 @@ def __deduce_empty_git_provider_from_git_provider_url(
updated_args["git_provider"] = GitProvider.GITHUB
elif "bitbucket" in git_provider_url.lower():
updated_args["git_provider"] = GitProvider.BITBUCKET
elif "gitlab" in git_provider_url.lower():
updated_args["git_provider"] = GitProvider.GITLAB
else:
error("Cannot deduce git provider from --git-provider-url. Please provide --git-provider")
return updated_args
Expand Down
1 change: 1 addition & 0 deletions gitopscli/git_api/git_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
class GitProvider(Enum):
GITHUB = auto()
BITBUCKET = auto()
GITLAB = auto()
12 changes: 12 additions & 0 deletions gitopscli/git_api/git_repo_api_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .git_repo_api import GitRepoApi
from .github_git_repo_api_adapter import GithubGitRepoApiAdapter
from .bitbucket_git_repo_api_adapter import BitbucketGitRepoApiAdapter
from .gitlab_git_repo_api_adapter import GitlabGitRepoApiAdapter
from .git_repo_api_logging_proxy import GitRepoApiLoggingProxy
from .git_api_config import GitApiConfig
from .git_provider import GitProvider
Expand All @@ -29,4 +30,15 @@ def create(config: GitApiConfig, organisation: str, repository_name: str) -> Git
organisation=organisation,
repository_name=repository_name,
)
elif config.git_provider is GitProvider.GITLAB:
provider_url = config.git_provider_url
if not provider_url:
provider_url = "https://www.gitlab.com"
git_repo_api = GitlabGitRepoApiAdapter(
git_provider_url=provider_url,
username=config.username,
password=config.password,
organisation=organisation,
repository_name=repository_name,
)
return GitRepoApiLoggingProxy(git_repo_api)
82 changes: 82 additions & 0 deletions gitopscli/git_api/gitlab_git_repo_api_adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from typing import Optional
import requests

import gitlab
from gitopscli.gitops_exception import GitOpsException

from .git_repo_api import GitRepoApi


class GitlabGitRepoApiAdapter(GitRepoApi):
def __init__(
self,
git_provider_url: str,
username: Optional[str],
password: Optional[str],
organisation: str,
repository_name: str,
) -> None:
try:
self.__gitlab = gitlab.Gitlab(git_provider_url, private_token=password)
project = self.__gitlab.projects.get(f"{organisation}/{repository_name}")
except requests.exceptions.ConnectionError as ex:
raise GitOpsException(f"Error connecting to '{git_provider_url}''") from ex
except gitlab.exceptions.GitlabAuthenticationError as ex:
raise GitOpsException("Bad Personal Access Token")
except gitlab.exceptions.GitlabGetError as ex:
if ex.response_code == 404:
raise GitOpsException(f"Repository '{organisation}/{repository_name}' does not exist")
raise GitOpsException(f"Error getting repository: '{ex.error_message}'")

self.__token_name = username
self.__access_token = password
self.__project = project

def get_username(self) -> Optional[str]:
return self.__token_name

def get_password(self) -> Optional[str]:
return self.__access_token

def get_clone_url(self) -> str:
return str(self.__project.http_url_to_repo)

def create_pull_request_to_default_branch(
self, from_branch: str, title: str, description: str
) -> GitRepoApi.PullRequestIdAndUrl:
to_branch = self.__get_default_branch()
return self.create_pull_request(from_branch, to_branch, title, description)

def create_pull_request(
self, from_branch: str, to_branch: str, title: str, description: str
) -> GitRepoApi.PullRequestIdAndUrl:
merge_request = self.__project.mergerequests.create(
{"source_branch": from_branch, "target_branch": to_branch, "title": title, "description": description}
)
return GitRepoApi.PullRequestIdAndUrl(pr_id=merge_request.iid, url=merge_request.web_url)

def merge_pull_request(self, pr_id: int) -> None:
merge_request = self.__project.mergerequests.get(pr_id)
merge_request.merge()

def add_pull_request_comment(self, pr_id: int, text: str, parent_id: Optional[int] = None) -> None:
merge_request = self.__project.mergerequests.get(pr_id)
merge_request.notes.create({"body": text})

def delete_branch(self, branch: str) -> None:
self.__project.branches.delete(branch)

def get_branch_head_hash(self, branch: str) -> str:
branch_instance = self.__project.branches.get(branch)
return str(branch_instance.commit["id"])

def get_pull_request_branch(self, pr_id: int) -> str:
merge_request = self.__project.mergerequests.get(pr_id)
return str(merge_request.source_branch)

def __get_default_branch(self) -> str:
branches = self.__project.branches.list()
default_branch = next(filter(lambda x: x.default, branches), None)
if default_branch is None:
raise GitOpsException(f"Default branch does not exist")
return str(default_branch.name)
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@
packages=find_packages(),
entry_points={"console_scripts": ["gitopscli = gitopscli.__main__:main"]},
setup_requires=["wheel"],
install_requires=["GitPython==3.0.6", "ruamel.yaml==0.16.5", "atlassian-python-api==1.14.5", "PyGithub==1.53",],
install_requires=[
"GitPython==3.0.6",
"ruamel.yaml==0.16.5",
"atlassian-python-api==1.14.5",
"PyGithub==1.53",
"python-gitlab==2.6.0",
],
)

0 comments on commit 089c4f2

Please sign in to comment.