Skip to content

Commit d9e648b

Browse files
feat(deploy): PR labels and merge parameters
- optional PR labels for gitlab and github - optional merge parameters for gitlab
2 parents 43402b7 + 118cacd commit d9e648b

File tree

12 files changed

+121
-32
lines changed

12 files changed

+121
-32
lines changed

.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ valid-metaclass-classmethod-first-arg=cls
427427
max-args=5
428428

429429
# Maximum number of attributes for a class (see R0902).
430-
max-attributes=12
430+
max-attributes=14
431431

432432
# Maximum number of boolean expressions in an if statement (see R0916).
433433
max-bool-expr=5

docs/commands/deploy.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,13 @@ usage: gitopscli deploy [-h] --file FILE --values VALUES
135135
options:
136136
-h, --help show this help message and exit
137137
--file FILE YAML file path
138-
--values VALUES YAML/JSON object with the YAML path as key and the
139-
desired value as value
138+
--values VALUES YAML/JSON object with the YAML path as key and the desired value as value
140139
--single-commit [SINGLE_COMMIT]
141140
Create only single commit for all updates
142141
--commit-message COMMIT_MESSAGE
143142
Specify exact commit message of deployment commit
144-
--username USERNAME Git username (alternative: GITOPSCLI_USERNAME env
145-
variable)
146-
--password PASSWORD Git password or token (alternative: GITOPSCLI_PASSWORD
147-
env variable)
143+
--username USERNAME Git username (alternative: GITOPSCLI_USERNAME env variable)
144+
--password PASSWORD Git password or token (alternative: GITOPSCLI_PASSWORD env variable)
148145
--git-user GIT_USER Git Username
149146
--git-email GIT_EMAIL
150147
Git User Email
@@ -155,18 +152,19 @@ options:
155152
--git-provider GIT_PROVIDER
156153
Git server provider
157154
--git-provider-url GIT_PROVIDER_URL
158-
Git provider base API URL (e.g.
159-
https://bitbucket.example.tld)
155+
Git provider base API URL (e.g. https://bitbucket.example.tld)
160156
--create-pr [CREATE_PR]
161157
Creates a Pull Request
162158
--auto-merge [AUTO_MERGE]
163-
Automatically merge the created PR (only valid with
164-
--create-pr)
159+
Automatically merge the created PR (only valid with --create-pr)
165160
--merge-method MERGE_METHOD
166-
Merge Method (e.g., 'squash', 'rebase', 'merge')
167-
(default: merge)
168-
--json
169-
Print a JSON object containing deployment information
161+
Merge Method (e.g., 'squash', 'rebase', 'merge') (default: merge)
162+
--json [JSON] Print a JSON object containing deployment information
163+
--pr-labels PR_LABELS
164+
JSON array pr labels (Gitlab, Github supported)
165+
--merge-parameters MERGE_PARAMETERS
166+
JSON object pr parameters (only Gitlab supported)
170167
-v [VERBOSE], --verbose [VERBOSE]
171168
Verbose exception logging
169+
172170
```

gitopscli/cliparser.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ def __create_deploy_parser() -> ArgumentParser:
112112
type=__parse_bool,
113113
default=False,
114114
)
115+
parser.add_argument(
116+
"--pr-labels", help="JSON array pr labels (Gitlab, Github supported)", type=__parse_yaml, default=None
117+
)
118+
parser.add_argument(
119+
"--merge-parameters",
120+
help="JSON object pr parameters (only Gitlab supported)",
121+
type=__parse_yaml,
122+
default=None,
123+
)
115124
__add_verbose_arg(parser)
116125
return parser
117126

gitopscli/commands/deploy.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class Args(GitApiConfig):
2828
auto_merge: bool
2929
json: bool
3030

31+
pr_labels: Optional[List[str]]
32+
merge_parameters: Optional[Any]
3133
merge_method: Literal["squash", "rebase", "merge"] = "merge"
3234

3335
def __init__(self, args: Args) -> None:
@@ -53,9 +55,13 @@ def execute(self) -> None:
5355
if self.__args.create_pr:
5456
title, description = self.__create_pull_request_title_and_description(updated_values)
5557
pr_id = git_repo_api.create_pull_request_to_default_branch(pr_branch, title, description).pr_id
56-
58+
if self.__args.pr_labels:
59+
git_repo_api.add_pull_request_label(pr_id, self.__args.pr_labels)
5760
if self.__args.auto_merge:
58-
git_repo_api.merge_pull_request(pr_id, self.__args.merge_method)
61+
if self.__args.merge_parameters:
62+
git_repo_api.merge_pull_request(pr_id, self.__args.merge_method, self.__args.merge_parameters)
63+
else:
64+
git_repo_api.merge_pull_request(pr_id, self.__args.merge_method)
5965
git_repo_api.delete_branch(pr_branch)
6066

6167
if self.__args.json:

gitopscli/git_api/bitbucket_git_repo_api_adapter.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Literal
1+
from typing import List, Dict, Any, Optional, Literal
22
import requests
33

44
from atlassian import Bitbucket
@@ -74,7 +74,12 @@ def create_pull_request(
7474
raise GitOpsException(pull_request["errors"][0]["message"])
7575
return GitRepoApi.PullRequestIdAndUrl(pr_id=pull_request["id"], url=pull_request["links"]["self"][0]["href"])
7676

77-
def merge_pull_request(self, pr_id: int, merge_method: Literal["squash", "rebase", "merge"] = "merge") -> None:
77+
def merge_pull_request(
78+
self,
79+
pr_id: int,
80+
merge_method: Literal["squash", "rebase", "merge"] = "merge",
81+
merge_parameters: Dict[str, Any] = None,
82+
) -> None:
7883
pull_request = self.__bitbucket.get_pullrequest(self.__organisation, self.__repository_name, pr_id)
7984
self.__bitbucket.merge_pull_request(
8085
self.__organisation, self.__repository_name, pull_request["id"], pull_request["version"]
@@ -108,3 +113,6 @@ def get_pull_request_branch(self, pr_id: int) -> str:
108113
def __get_default_branch(self) -> str:
109114
default_branch = self.__bitbucket.get_default_branch(self.__organisation, self.__repository_name)
110115
return str(default_branch["id"])
116+
117+
def add_pull_request_label(self, pr_id: int, pr_labels: List[str]) -> None:
118+
pass

gitopscli/git_api/git_repo_api.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from abc import ABCMeta, abstractmethod
2-
from typing import NamedTuple, Optional, Literal
2+
from typing import Any, List, Dict, NamedTuple, Optional, Literal
33

44

55
class GitRepoApi(metaclass=ABCMeta):
@@ -32,7 +32,12 @@ def create_pull_request(
3232
...
3333

3434
@abstractmethod
35-
def merge_pull_request(self, pr_id: int, merge_method: Literal["squash", "rebase", "merge"] = "merge") -> None:
35+
def merge_pull_request(
36+
self,
37+
pr_id: int,
38+
merge_method: Literal["squash", "rebase", "merge"] = "merge",
39+
merge_parameters: Dict[str, Any] = None,
40+
) -> None:
3641
...
3742

3843
@abstractmethod
@@ -50,3 +55,7 @@ def get_branch_head_hash(self, branch: str) -> str:
5055
@abstractmethod
5156
def get_pull_request_branch(self, pr_id: int) -> str:
5257
...
58+
59+
@abstractmethod
60+
def add_pull_request_label(self, pr_id: int, pr_labels: List[str]) -> None:
61+
...

gitopscli/git_api/git_repo_api_logging_proxy.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Optional, Literal
2+
from typing import Any, List, Dict, Optional, Literal
33
from .git_repo_api import GitRepoApi
44

55

@@ -28,7 +28,12 @@ def create_pull_request(
2828
logging.info("Creating pull request from '%s' to '%s' with title: %s", from_branch, to_branch, title)
2929
return self.__api.create_pull_request(from_branch, to_branch, title, description)
3030

31-
def merge_pull_request(self, pr_id: int, merge_method: Literal["squash", "rebase", "merge"] = "merge") -> None:
31+
def merge_pull_request(
32+
self,
33+
pr_id: int,
34+
merge_method: Literal["squash", "rebase", "merge"] = "merge",
35+
merge_parameters: Dict[str, Any] = None,
36+
) -> None:
3237
logging.info("Merging pull request %s", pr_id)
3338
self.__api.merge_pull_request(pr_id, merge_method=merge_method)
3439

@@ -50,3 +55,7 @@ def get_branch_head_hash(self, branch: str) -> str:
5055

5156
def get_pull_request_branch(self, pr_id: int) -> str:
5257
return self.__api.get_pull_request_branch(pr_id)
58+
59+
def add_pull_request_label(self, pr_id: int, pr_labels: List[str]) -> None:
60+
logging.info("Adding labels for pull request %s with content: %s", pr_id, pr_labels)
61+
self.__api.add_pull_request_label(pr_id, pr_labels)

gitopscli/git_api/github_git_repo_api_adapter.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Literal
1+
from typing import Any, Dict, Union, Optional, Literal
22

33
from github import (
44
Github,
@@ -45,7 +45,12 @@ def create_pull_request(
4545
pull_request = repo.create_pull(title=title, body=description, head=from_branch, base=to_branch)
4646
return GitRepoApi.PullRequestIdAndUrl(pr_id=pull_request.number, url=pull_request.html_url)
4747

48-
def merge_pull_request(self, pr_id: int, merge_method: Literal["squash", "rebase", "merge"] = "merge") -> None:
48+
def merge_pull_request(
49+
self,
50+
pr_id: int,
51+
merge_method: Literal["squash", "rebase", "merge"] = "merge",
52+
merge_parameters: Dict[str, Any] = None,
53+
) -> None:
4954
pull_request = self.__get_pull_request(pr_id)
5055
pull_request.merge(merge_method=merge_method)
5156

@@ -88,3 +93,7 @@ def __get_repo(self) -> Repository.Repository:
8893
raise GitOpsException(
8994
f"Repository '{self.__organisation}/{self.__repository_name}' does not exist."
9095
) from ex
96+
97+
def add_pull_request_label(self, pr_id: int, pr_labels: Union[str, Any]) -> None:
98+
pull_request = self.__get_pull_request(pr_id)
99+
pull_request.set_labels(pr_labels)

gitopscli/git_api/gitlab_git_repo_api_adapter.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Literal
1+
from typing import Any, List, Dict, Optional, Literal
22
import logging
33
import time
44
import requests
@@ -59,16 +59,21 @@ def create_pull_request(
5959
)
6060
return GitRepoApi.PullRequestIdAndUrl(pr_id=merge_request.iid, url=merge_request.web_url)
6161

62-
def merge_pull_request(self, pr_id: int, merge_method: Literal["squash", "rebase", "merge"] = "merge") -> None:
62+
def merge_pull_request(
63+
self,
64+
pr_id: int,
65+
merge_method: Literal["squash", "rebase", "merge"] = "merge",
66+
merge_parameters: Dict[str, Any] = None,
67+
) -> None:
6368
merge_request = self.__project.mergerequests.get(pr_id)
6469

6570
max_retries = MAX_MERGE_RETRIES
6671
while max_retries > 0:
6772
try:
6873
if merge_method == "rebase":
69-
merge_request.rebase()
74+
merge_request.rebase(merge_parameters)
7075
return
71-
merge_request.merge()
76+
merge_request.merge(merge_parameters)
7277
return
7378
except gitlab.exceptions.GitlabMRClosedError as ex:
7479
# "Branch cannot be merged" error can occur if the server
@@ -97,8 +102,13 @@ def get_pull_request_branch(self, pr_id: int) -> str:
97102
return str(merge_request.source_branch)
98103

99104
def __get_default_branch(self) -> str:
100-
branches = self.__project.branches.list()
105+
branches = self.__project.branches.list(all=True)
101106
default_branch = next(filter(lambda x: x.default, branches), None)
102107
if default_branch is None:
103108
raise GitOpsException("Default branch does not exist")
104109
return str(default_branch.name)
110+
111+
def add_pull_request_label(self, pr_id: int, pr_labels: List[str]) -> None:
112+
merge_request = self.__project.mergerequests.get(pr_id)
113+
merge_request.labels = pr_labels
114+
merge_request.save()

mypy.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ exclude = (?x)(
1717
build/lib/*/*
1818
| tests/*
1919
| venv/Scripts/*
20+
| venv/bin/*
2021
)
2122

2223

0 commit comments

Comments
 (0)