diff --git a/scripts/create_delete_integration_branch.py b/scripts/create_delete_integration_branch.py new file mode 100644 index 0000000000000000000000000000000000000000..e02187d661c04c6ba2a35ebb60ded2b03f6d042a --- /dev/null +++ b/scripts/create_delete_integration_branch.py @@ -0,0 +1,186 @@ +import gitlab +import argparse + +def create_new_branch(project, start_branch, end_branch): + try: + project.branches.create({'branch': end_branch, 'ref': start_branch}) + project.protectedbranches.create({'name': end_branch, 'push_access_level': gitlab.MAINTAINER_ACCESS}) + print(f"Successfully created branch '{end_branch}' from '{start_branch}' in project '{project.name}'") + except gitlab.exceptions.GitlabCreateError as e: + print(f"Failed to create branch '{end_branch}' from '{start_branch}' in project '{project.name}': {e}") + except Exception as e: + print(f"An error occurred while creating branch '{end_branch}' from '{start_branch}' in project '{project.name}': {e}") + +def delete_branch(project, branch_name): + try: + project.branches.delete(branch_name) + project.protectedbranches.get(branch_name).delete() + print(f"Successfully deleted branch '{branch_name}' in project '{project.name}'") + except gitlab.exceptions.GitlabCreateError as e: + print(f"Failed to delete branch '{branch_name}'' in project '{project.name}': {e}") + except Exception as e: + print(f"An error occurred while deleting branch '{branch_name}' in project '{project.name}': {e}") + +def update_variable(project, variable_name, action, value): + try: + variables = project.variables.list(all=True) + for variable in variables: + if variable.key == variable_name: + if action == 'create': + variable.value += f'\n{value}' + elif action == 'delete': + variable.value = variable.value.replace(value, '') + # Remove any trailing newline characters + variable.value = variable.value.rstrip('\n') + variable.save() + print(f"Successfully updated variable '{variable_name}' in project '{project.name}'") + break + except gitlab.exceptions.GitlabUpdateError as e: + print(f"Failed to update variable '{variable_name}' in project '{project.name}': {e}") + except Exception as e: + print(f"An error occurred while updating variable '{variable_name}' in project '{project.name}': {e}") + +def update_ci_variable(manifest_repo, start_branch, end_branch): + try: + # Fetch the .gitlab-ci.yml file + file = manifest_repo.files.get(file_path='.gitlab-ci.yml', ref=end_branch) + content = file.decode().decode('utf-8') + + # Update the value of the MASTER_BRANCH variable + new_content = content.replace(f'MASTER_BRANCH: {start_branch}', f'MASTER_BRANCH: {end_branch}') + + # Commit the changes perfomrm inside .gitlab-ci.yml + commit_data = { + 'branch': end_branch, + 'commit_message': f"Update MASTER_BRANCH variable in .gitlab-ci.yml to {end_branch}", + 'actions': [ + { + 'action': 'update', + 'file_path': '.gitlab-ci.yml', + 'content': new_content, + 'encoding': 'text' + } + ] + } + manifest_repo.commits.create(commit_data) + print(f"Successfully updated .gitlab-ci.yml in {manifest_repo.name} to use {end_branch}") + except Exception as e: + print(f"Error updating .gitlab-ci.yml in {manifest_repo.name}: {str(e)}") + +def main(): + + parser = argparse.ArgumentParser(description="GitLab Branch and CI/CD Variable Manager") + + parser.add_argument( + "--url", + help="URL of the GitLab instance", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="access_token", + required=True, + ) + parser.add_argument( + "--group", + help="Name of the GitLab group where the repo that integrates into the manifest are located", + dest="group_name", + required=True, + ) + parser.add_argument( + "--other-repos", + nargs='+', + help="Name of other GitLab repositories external to the group", + dest="other_repos", + required=True, + ) + parser.add_argument( + "--start-branch", + help="Name of the starting branch", + dest="start_branch", + required=True, + ) + parser.add_argument( + "--end-branch", + help="Name of the ending branch", + dest="end_branch", + required=True, + ) + parser.add_argument( + "--manifest-repo", + help="Name of the manifest repository", + dest="manifest_repo", + required=True, + ) + parser.add_argument( + "--variable", + help="Name of the CI/CD variable to be changed", + dest="variable_name", + required=True, + ) + parser.add_argument( + "--action", + help="Action to perform: 'create' or 'delete'", + dest="action", + required=True, + ) + + args = parser.parse_args() + + gl = gitlab.Gitlab(args.gitlab_url, private_token=args.access_token) + gl.auth() + + group = gl.groups.get(args.group_name) + + # Iterate over projects in the group + for group_project in group.projects.list(all=True, include_subgroups=True): + project = gl.projects.get(group_project.id) + print(project.name) + ## Layers projects first, then separately manifest repo + if not "manifest" in project.name: + if args.action == 'create': + # Create new branch in project + create_new_branch(project, args.start_branch, args.end_branch) + elif args.action == 'delete': + # Delete old branch in project + delete_branch(project, args.end_branch) + # Update CI/CD variable + value = f"{args.end_branch}:{args.manifest_repo}:{args.end_branch}" + update_variable(project, args.variable_name, args.action, value) + + # Iterate over spot projects in other groups + for project in args.other_repos: + project_group_name, project_name = project.rsplit('/', 1) + project_group = gl.groups.get(project_group_name) + project_project_id = project_group.projects.list(search=project_name)[0] + project_repo = gl.projects.get(project_project_id.id) + print(project_repo.name) + if args.action == 'create': + # Create new branch in project + create_new_branch(project_repo, args.start_branch, args.end_branch) + elif args.action == 'delete': + # Delete old branch in project + delete_branch(project_repo, args.end_branch) + # Update CI/CD variable + value = f"{args.end_branch}:{args.manifest_repo}:{args.end_branch}" + update_variable(project_repo, args.variable_name, args.action, value) + + # Performing modifications on manifest repo + manifest_group_name, manifest_name = args.manifest_repo.rsplit('/', 1) + manifest_group = gl.groups.get(manifest_group_name) + manifest_project_id = manifest_group.projects.list(search=manifest_name)[0] + manifest_project = gl.projects.get(manifest_project_id.id) + + if args.action == 'create': + # Create new branch in project + create_new_branch(manifest_project, args.start_branch, args.end_branch) + # Change .gitlab-ci.yml MASTER_BRANCH reference + update_ci_variable(manifest_project, args.start_branch, args.end_branch) + elif args.action == 'delete': + # Delete old branch in project + delete_branch(manifest_project, args.end_branch) + +if __name__ == "__main__": + main()