Skip to content

Commit

Permalink
Merge pull request #138 from baloise/feat/default-branch
Browse files Browse the repository at this point in the history
feat: support default branches other than master
  • Loading branch information
christiansiegel committed Dec 14, 2020
2 parents ea0dc35 + ce40475 commit 9ecee31
Show file tree
Hide file tree
Showing 19 changed files with 164 additions and 144 deletions.
Binary file modified docs/assets/images/teaser.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/commands/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ backend:
value: foo # <- and even one in a list
```
With the following command GitOps CLI will update both values to `1.1.0` on the `master` branch.
With the following command GitOps CLI will update both values to `1.1.0` on the default branch.

```bash
gitopscli deploy \
Expand Down
2 changes: 1 addition & 1 deletion gitopscli/commands/common/gitops_config_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
def load_gitops_config(git_api_config: GitApiConfig, organisation: str, repository_name: str) -> GitOpsConfig:
git_repo_api = GitRepoApiFactory.create(git_api_config, organisation, repository_name)
with GitRepo(git_repo_api) as git_repo:
git_repo.checkout("master")
git_repo.clone()
gitops_config_file_path = git_repo.get_full_file_path(".gitops.config.yaml")
try:
gitops_config_yaml = yaml_file_load(gitops_config_file_path)
Expand Down
8 changes: 4 additions & 4 deletions gitopscli/commands/create_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def execute(self,) -> None:

team_config_git_repo_api = self.__create_team_config_git_repo_api(gitops_config)
with GitRepo(team_config_git_repo_api) as team_config_git_repo:
team_config_git_repo.checkout("master")
team_config_git_repo.clone()

created_new_preview = self.__create_preview_from_template_if_not_existing(
team_config_git_repo, gitops_config
Expand All @@ -58,7 +58,7 @@ def execute(self,) -> None:
logging.info("The preview is already up-to-date. I'm done here.")
return

self.__commit_and_push_to_master(
self.__commit_and_push(
team_config_git_repo,
f"{'Create new' if created_new_preview else 'Update'} preview environment for "
f"'{gitops_config.application_name}' and git hash '{self.__args.git_hash}'.",
Expand All @@ -69,9 +69,9 @@ def execute(self,) -> None:
else:
self.__deployment_updated_callback(route_host)

def __commit_and_push_to_master(self, git_repo: GitRepo, message: str) -> None:
def __commit_and_push(self, git_repo: GitRepo, message: str) -> None:
git_repo.commit(self.__args.git_user, self.__args.git_email, message)
git_repo.push("master")
git_repo.push()

def __get_gitops_config(self) -> GitOpsConfig:
return load_gitops_config(self.__args, self.__args.organisation, self.__args.repository_name)
Expand Down
8 changes: 4 additions & 4 deletions gitopscli/commands/delete_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def execute(self) -> None:

team_config_git_repo_api = self.__create_team_config_git_repo_api(gitops_config)
with GitRepo(team_config_git_repo_api) as team_config_git_repo:
team_config_git_repo.checkout("master")
team_config_git_repo.clone()

preview_namespace = gitops_config.get_preview_namespace(preview_id)
logging.info("Preview folder name: %s", preview_namespace)
Expand All @@ -46,7 +46,7 @@ def execute(self) -> None:
)
return

self.__commit_and_push_to_master(
self.__commit_and_push(
team_config_git_repo,
f"Delete preview environment for '{gitops_config.application_name}' and preview id '{preview_id}'.",
)
Expand All @@ -57,9 +57,9 @@ def __get_gitops_config(self) -> GitOpsConfig:
def __create_team_config_git_repo_api(self, gitops_config: GitOpsConfig) -> GitRepoApi:
return GitRepoApiFactory.create(self.__args, gitops_config.team_config_org, gitops_config.team_config_repo)

def __commit_and_push_to_master(self, git_repo: GitRepo, message: str) -> None:
def __commit_and_push(self, git_repo: GitRepo, message: str) -> None:
git_repo.commit(self.__args.git_user, self.__args.git_email, message)
git_repo.push("master")
git_repo.push()

@staticmethod
def __delete_folder_if_exists(git_repo: GitRepo, folder_name: str) -> bool:
Expand Down
13 changes: 6 additions & 7 deletions gitopscli/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,26 @@ def __init__(self, args: Args) -> None:
def execute(self) -> None:
git_repo_api = self.__create_git_repo_api()
with GitRepo(git_repo_api) as git_repo:
branch = "master"
git_repo.checkout(branch)
git_repo.clone()

if self.__args.create_pr:
branch = f"gitopscli-deploy-{str(uuid.uuid4())[:8]}"
git_repo.new_branch(branch)
pr_branch = f"gitopscli-deploy-{str(uuid.uuid4())[:8]}"
git_repo.new_branch(pr_branch)

updated_values = self.__update_values(git_repo)
if not updated_values:
logging.info("All values already up-to-date. I'm done here.")
return

git_repo.push(branch)
git_repo.push()

if self.__args.create_pr:
title, description = self.__create_pull_request_title_and_description(updated_values)
pr_id = git_repo_api.create_pull_request(branch, "master", title, description).pr_id
pr_id = git_repo_api.create_pull_request_to_default_branch(pr_branch, title, description).pr_id

if self.__args.auto_merge:
git_repo_api.merge_pull_request(pr_id)
git_repo_api.delete_branch(branch)
git_repo_api.delete_branch(pr_branch)

def __create_git_repo_api(self) -> GitRepoApi:
return GitRepoApiFactory.create(self.__args, self.__args.organisation, self.__args.repository_name)
Expand Down
10 changes: 5 additions & 5 deletions gitopscli/commands/sync_apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __sync_apps(team_config_git_repo: GitRepo, root_config_git_repo: GitRepo, gi

logging.info("Sync applications in root repository's %s.", apps_config_file_name)
merge_yaml_element(apps_config_file, "applications", {repo_app: {} for repo_app in repo_apps})
__commit_and_push_to_master(team_config_git_repo, root_config_git_repo, git_user, git_email, apps_config_file_name)
__commit_and_push(team_config_git_repo, root_config_git_repo, git_user, git_email, apps_config_file_name)


def __find_apps_config_from_repo(
Expand Down Expand Up @@ -100,16 +100,16 @@ def __get_applications_from_app_config(app_config: Any) -> Set[str]:
return set(apps)


def __commit_and_push_to_master(
def __commit_and_push(
team_config_git_repo: GitRepo, root_config_git_repo: GitRepo, git_user: str, git_email: str, app_file_name: str
) -> None:
author = team_config_git_repo.get_author_from_last_commit()
root_config_git_repo.commit(git_user, git_email, f"{author} updated " + app_file_name)
root_config_git_repo.push("master")
root_config_git_repo.push()


def __get_bootstrap_entries(root_config_git_repo: GitRepo) -> Any:
root_config_git_repo.checkout("master")
root_config_git_repo.clone()
bootstrap_values_file = root_config_git_repo.get_full_file_path("bootstrap/values.yaml")
try:
bootstrap_yaml = yaml_file_load(bootstrap_values_file)
Expand All @@ -121,7 +121,7 @@ def __get_bootstrap_entries(root_config_git_repo: GitRepo) -> Any:


def __get_repo_apps(team_config_git_repo: GitRepo) -> Set[str]:
team_config_git_repo.checkout("master")
team_config_git_repo.clone()
repo_dir = team_config_git_repo.get_full_file_path(".")
return {
name
Expand Down
10 changes: 10 additions & 0 deletions gitopscli/git/bitbucket_git_repo_api_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ def get_clone_url(self) -> str:
raise GitOpsException("Couldn't determine repository URL.")
return str(repo_url)

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:
Expand Down Expand Up @@ -98,3 +104,7 @@ def get_pull_request_branch(self, pr_id: int) -> str:
if "errors" in pull_request:
raise GitOpsException(pull_request["errors"][0]["message"])
return str(pull_request["fromRef"]["displayId"])

def __get_default_branch(self) -> str:
default_branch = self.__bitbucket.get_default_branch(self.__organisation, self.__repository_name)
return str(default_branch["id"])
14 changes: 5 additions & 9 deletions gitopscli/git/git_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def get_full_file_path(self, relative_path: str) -> str:
def get_clone_url(self) -> str:
return self.__api.get_clone_url()

def checkout(self, branch: str) -> None:
def clone(self) -> None:
self.__delete_tmp_dir()
self.__tmp_dir = create_tmp_dir()
git_options = []
Expand All @@ -52,12 +52,6 @@ def checkout(self, branch: str) -> None:
except GitError as ex:
raise GitOpsException(f"Error cloning '{url}'") from ex

logging.info("Checking out branch: %s", branch)
try:
self.__repo.git.checkout(branch)
except GitError as ex:
raise GitOpsException(f"Error checking out branch '{branch}'") from ex

def new_branch(self, branch: str) -> None:
logging.info("Creating new branch: %s", branch)
repo = self.__get_repo()
Expand All @@ -78,9 +72,11 @@ def commit(self, git_user: str, git_email: str, message: str) -> None:
except GitError as ex:
raise GitOpsException(f"Error creating commit.") from ex

def push(self, branch: str) -> None:
logging.info("Pushing branch: %s", branch)
def push(self, branch: Optional[str] = None) -> None:
repo = self.__get_repo()
if not branch:
branch = repo.git.branch("--show-current")
logging.info("Pushing branch: %s", branch)
try:
repo.git.push("--set-upstream", "origin", branch)
except GitCommandError as ex:
Expand Down
6 changes: 6 additions & 0 deletions gitopscli/git/git_repo_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ def get_password(self) -> Optional[str]:
def get_clone_url(self) -> str:
...

@abstractmethod
def create_pull_request_to_default_branch(
self, from_branch: str, title: str, description: str
) -> "PullRequestIdAndUrl":
...

@abstractmethod
def create_pull_request(
self, from_branch: str, to_branch: str, title: str, description: str
Expand Down
6 changes: 6 additions & 0 deletions gitopscli/git/git_repo_api_logging_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ def get_password(self) -> Optional[str]:
def get_clone_url(self) -> str:
return self.__api.get_clone_url()

def create_pull_request_to_default_branch(
self, from_branch: str, title: str, description: str
) -> GitRepoApi.PullRequestIdAndUrl:
logging.info("Creating pull request from '%s' to default branch with title: %s", from_branch, title)
return self.__api.create_pull_request_to_default_branch(from_branch, title, description)

def create_pull_request(
self, from_branch: str, to_branch: str, title: str, description: str
) -> GitRepoApi.PullRequestIdAndUrl:
Expand Down
8 changes: 7 additions & 1 deletion gitopscli/git/github_git_repo_api_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ def get_password(self) -> Optional[str]:
def get_clone_url(self) -> str:
return self.__get_repo().clone_url

def create_pull_request_to_default_branch(
self, from_branch: str, title: str, description: str
) -> GitRepoApi.PullRequestIdAndUrl:
to_branch = self.__get_repo().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:
repo = self.__get_repo()
pull_request = repo.create_pull(title=title, body=description, head=from_branch, base=to_branch)
return GitRepoApi.PullRequestIdAndUrl(pr_id=pull_request.id, url=pull_request.html_url)
return GitRepoApi.PullRequestIdAndUrl(pr_id=pull_request.number, url=pull_request.html_url)

def merge_pull_request(self, pr_id: int) -> None:
pull_request = self.__get_pull_request(pr_id)
Expand Down
6 changes: 3 additions & 3 deletions tests/commands/common/test_gitops_config_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def setUp(self):
self.git_repo_mock.return_value = self.git_repo_mock
self.git_repo_mock.__enter__.return_value = self.git_repo_mock
self.git_repo_mock.__exit__.return_value = False
self.git_repo_mock.checkout.return_value = None
self.git_repo_mock.clone.return_value = None
self.git_repo_mock.get_full_file_path.side_effect = lambda x: f"/repo-dir/{x}"

self.seal_mocks()
Expand All @@ -47,7 +47,7 @@ def test_happy_flow(self):
assert self.mock_manager.method_calls == [
call.GitRepoApiFactory.create(self.git_api_config, "ORGA", "REPO"),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path(".gitops.config.yaml"),
call.yaml_file_load("/repo-dir/.gitops.config.yaml"),
call.GitOpsConfig.from_yaml({"dummy": "gitopsconfig"}),
Expand All @@ -64,7 +64,7 @@ def test_file_not_found(self):
assert self.mock_manager.method_calls == [
call.GitRepoApiFactory.create(self.git_api_config, "ORGA", "REPO"),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path(".gitops.config.yaml"),
call.yaml_file_load("/repo-dir/.gitops.config.yaml"),
]
22 changes: 11 additions & 11 deletions tests/commands/test_create_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def setUp(self):
self.git_repo_mock.__enter__.return_value = self.git_repo_mock
self.git_repo_mock.__exit__.return_value = False
self.git_repo_mock.get_full_file_path.side_effect = lambda x: f"/tmp/created-tmp-dir/{x}"
self.git_repo_mock.checkout.return_value = None
self.git_repo_mock.clone.return_value = None
self.git_repo_mock.commit.return_value = None
self.git_repo_mock.push.return_value = None

Expand Down Expand Up @@ -92,7 +92,7 @@ def test_create_new_preview(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Create new folder for preview: %s", "my-app-685912d3-preview"),
Expand Down Expand Up @@ -125,7 +125,7 @@ def test_create_new_preview(self):
"GIT_EMAIL",
"Create new preview environment for 'my-app' and git hash '3361723dbd91fcfae7b5b8b8b7d462fbc14187a9'.",
),
call.GitRepo.push("master"),
call.GitRepo.push(),
]

def test_update_existing_preview(self):
Expand All @@ -149,7 +149,7 @@ def test_update_existing_preview(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Use existing folder for preview: %s", "my-app-685912d3-preview"),
Expand All @@ -172,7 +172,7 @@ def test_update_existing_preview(self):
"GIT_EMAIL",
"Update preview environment for 'my-app' and git hash '3361723dbd91fcfae7b5b8b8b7d462fbc14187a9'.",
),
call.GitRepo.push("master"),
call.GitRepo.push(),
]

def test_preview_already_up_to_date(self):
Expand All @@ -198,7 +198,7 @@ def test_preview_already_up_to_date(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Use existing folder for preview: %s", "my-app-685912d3-preview"),
Expand Down Expand Up @@ -233,7 +233,7 @@ def test_create_preview_for_unknown_template(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Create new folder for preview: %s", "my-app-685912d3-preview"),
Expand All @@ -254,7 +254,7 @@ def test_create_preview_values_yaml_not_found(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Use existing folder for preview: %s", "my-app-685912d3-preview"),
Expand All @@ -279,7 +279,7 @@ def test_create_preview_values_yaml_parse_error(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Use existing folder for preview: %s", "my-app-685912d3-preview"),
Expand All @@ -304,7 +304,7 @@ def test_create_preview_with_invalid_replacement_path(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Use existing folder for preview: %s", "my-app-685912d3-preview"),
Expand Down Expand Up @@ -334,7 +334,7 @@ def test_create_new_preview_invalid_chart_template(self):
call.load_gitops_config(ARGS, "ORGA", "REPO",),
call.GitRepoApiFactory.create(ARGS, "TEAM_CONFIG_ORG", "TEAM_CONFIG_REPO",),
call.GitRepo(self.git_repo_api_mock),
call.GitRepo.checkout("master"),
call.GitRepo.clone(),
call.GitRepo.get_full_file_path("my-app-685912d3-preview"),
call.os.path.isdir("/tmp/created-tmp-dir/my-app-685912d3-preview"),
call.logging.info("Create new folder for preview: %s", "my-app-685912d3-preview"),
Expand Down
Loading

0 comments on commit 9ecee31

Please sign in to comment.