diff --git a/common.py b/common.py index f48a95753653abe17518c2a9b464000baf8e8dda..8eb60dedb7f492d34411ba97db61c35f8997d852 100755 --- a/common.py +++ b/common.py @@ -52,34 +52,6 @@ def get_latest_commit(gitlab, project, branch_name): return branch.commit -def get_merge_request( - gitlab, project, state, source_branch=None, target_branch=None, commit=None -): - """Get merge request by source and target branch and optionally commit sha""" - merge_request = None - with gitlab: - try: - merge_requests = project.mergerequests.list( - source_branch=source_branch, - target_branch=target_branch, - state=state, - all=True, - retry_transient_errors=True, - ) - except GitlabGetError as e: - sys.exit( - "ERROR: could not list merge requests for project '%s': %s" - % (project.name, e) - ) - if commit: - for mr in merge_requests: - if mr.sha == commit: - merge_request = mr - elif merge_requests: - merge_request = merge_requests[0] - return merge_request - - def rebase_merge_request(gitlab, project, merge_request): """Attempt to rebase a merge request and return the updated merge request object""" # Rebasing takes more than one API call, see: diff --git a/get_manifest_projects.py b/get_manifest_projects.py new file mode 100755 index 0000000000000000000000000000000000000000..39e600179129f1c033f6698717e27a105b8635e0 --- /dev/null +++ b/get_manifest_projects.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import argparse +import sys +from lxml import etree + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--manifest", + help="""manifest file to parse projects from""", + dest="manifest", + required=True, + ) + parser.add_argument( + "--remote", + help="""get only projects with this remote""", + dest="remote", + required=False, + ) + + args, _ = parser.parse_known_args() + + # Parse manifest file + try: + manifest = etree.parse(args.manifest) + except FileNotFoundError: + sys.exit("ERROR: file '%s' not found" % args.manifest) + + # Find project references in manifest + if args.remote: + find_expression = "project[@remote='%s']" % args.remote + else: + find_expression = "project" + projects = manifest.findall(find_expression) + + for project in projects: + print(project.get("name")) + + +if __name__ == "__main__": + main() diff --git a/get_merge_requests.py b/get_merge_requests.py new file mode 100755 index 0000000000000000000000000000000000000000..3f2fdb3f8c8035df147b1b76c20558580bcee71a --- /dev/null +++ b/get_merge_requests.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +import common + +import argparse +import sys +from gitlab import Gitlab, GitlabGetError + + +def get_merge_requests( + gitlab, project, state, source_branch=None, target_branch=None, commit=None +): + """Get merge request by source and target branch and optionally commit sha""" + merge_requests = [] + with gitlab: + try: + all_merge_requests = project.mergerequests.list( + source_branch=source_branch, + target_branch=target_branch, + state=state, + all=True, + retry_transient_errors=True, + ) + except GitlabGetError as e: + sys.exit( + "ERROR: could not list merge requests for project '%s': %s" + % (project.name, e) + ) + if commit: + for mr in all_merge_requests: + if mr.sha == commit: + merge_requests.append(mr) + elif all_merge_requests: + merge_requests = all_merge_requests + return merge_requests + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="token", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the GitLab project""", + dest="project", + required=True, + ) + parser.add_argument( + "--state", + help="""state of the merge request (opened, closed, locked, or merged)""", + dest="state", + required=True, + ) + parser.add_argument( + "--source-branch", + help="""source branch of the merge request""", + dest="source_branch", + required=False, + ) + parser.add_argument( + "--target-branch", + help="""target branch of the merge request""", + dest="target_branch", + required=False, + ) + parser.add_argument( + "--commit", + help="""commit sha of the merge request""", + dest="commit", + required=False, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + + mrs = get_merge_requests( + gitlab, + project, + state=args.state, + source_branch=args.source_branch, + target_branch=args.target_branch, + commit=args.commit, + ) + + for mr in mrs: + print(mr.iid) + + +if __name__ == "__main__": + main() diff --git a/merge_into_manifest.py b/merge_into_manifest.py index 98a87beca091073443d60ba6a79e018ad2e69e8c..7f530d63bdb1e17262cd10a693bb067fdf9723a4 100755 --- a/merge_into_manifest.py +++ b/merge_into_manifest.py @@ -8,6 +8,7 @@ from gitlab import ( GitlabGetError, ) from accept_merge_request import accept_merge_request +from get_merge_requests import get_merge_requests from integrate_into_manifest import integrate_into_manifest @@ -63,18 +64,19 @@ def main(): manifest_project = common.get_project(gitlab, args.manifest_project) # Get source merge request - source_mr = common.get_merge_request( + mrs = get_merge_requests( gitlab, project, target_branch=args.master_branch, state="merged", commit=args.commit, ) - if not source_mr: + if not mrs: sys.exit( "ERROR: could not determine source merge request for commit %s" % args.commit ) + source_mr = mrs[0] # Get original branch for commit original_branch = source_mr.source_branch @@ -82,15 +84,15 @@ def main(): target_branch = args.master_branch # Check if merge request already exists - mr = common.get_merge_request( + mrs = get_merge_requests( gitlab, manifest_project, source_branch=integration_branch, target_branch=target_branch, state="opened", ) - if mr: - sys.exit("ERROR: There is already an open merge request:\n%s" % mr.web_url) + if mrs: + sys.exit("ERROR: There is already an open merge request:\n%s" % mrs[0].web_url) with gitlab: diff --git a/retrigger_mr_pipeline.py b/retrigger_mr_pipeline.py new file mode 100755 index 0000000000000000000000000000000000000000..635cd84fec7886ca7ad125a24c4a7ad2eef59f6f --- /dev/null +++ b/retrigger_mr_pipeline.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +import common + +import argparse +import sys +from gitlab import Gitlab, GitlabGetError, GitlabHttpError + + +def retrigger_mr_pipeline(gitlab, project, mr): + with gitlab: + # Creating a merge request pipeline is not implemented in python-gitlab, so we + # have to construct the HTTP request manually. + # https://github.com/python-gitlab/python-gitlab/issues/1239 + # https://docs.gitlab.com/ce/api/merge_requests.html#create-mr-pipeline + path = "%s/%s/pipelines" % (mr.manager.path, mr.iid) + try: + pipeline = gitlab.http_post(path) + except GitlabHttpError as e: + sys.exit( + "ERROR: could not create pipeline for merge request %s!%s: %s" + % (project.name, mr.iid, e) + ) + + print("Created new pipeline for %s :" % mr.web_url) + print(pipeline.get("web_url")) + + return pipeline + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="token", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the GitLab project""", + dest="project", + required=True, + ) + parser.add_argument( + "--iid", + help="""iid of the merge request""", + dest="iid", + required=True, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + try: + mr = project.mergerequests.get(args.iid) + except GitlabGetError as e: + sys.exit( + "ERROR: could not get merge request %s:!%s: %s" + % (project.name, args.iid, e) + ) + if not mr: + sys.exit("ERROR: could not find merge request %s!%s" % (project.name, args.iid)) + + retrigger_mr_pipeline(gitlab, project, mr) + + +if __name__ == "__main__": + main() diff --git a/retrigger_mr_pipelines.py b/retrigger_mr_pipelines.py new file mode 100755 index 0000000000000000000000000000000000000000..7944f4d576a8d5d9f9e39bb57a56968ef542370c --- /dev/null +++ b/retrigger_mr_pipelines.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +import common + +import argparse +from gitlab import Gitlab + +from get_merge_requests import get_merge_requests +from retrigger_mr_pipeline import retrigger_mr_pipeline + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="token", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the GitLab project""", + dest="project", + required=True, + ) + parser.add_argument( + "--state", + help="""state of the merge request (opened, closed, locked, or merged)""", + dest="state", + required=True, + ) + parser.add_argument( + "--source-branch", + help="""source branch of the merge request""", + dest="source_branch", + required=False, + ) + parser.add_argument( + "--target-branch", + help="""target branch of the merge request""", + dest="target_branch", + required=False, + ) + parser.add_argument( + "--commit", + help="""commit sha of the merge request""", + dest="commit", + required=False, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + + mrs = get_merge_requests( + gitlab, + project, + state=args.state, + source_branch=args.source_branch, + target_branch=args.target_branch, + commit=args.commit, + ) + + for mr in mrs: + retrigger_mr_pipeline(gitlab, project, mr) + + +if __name__ == "__main__": + main()