diff --git a/check_if_integration_branch_is_up_to_date.py b/check_if_integration_branch_is_up_to_date.py new file mode 100755 index 0000000000000000000000000000000000000000..1dbeddebbdd5702cc95b46a3b8b26dfb83213cdc --- /dev/null +++ b/check_if_integration_branch_is_up_to_date.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +import common + +import argparse +import sys +import tempfile +from furl import furl +from git import GitCommandError, Repo +from gitlab import Gitlab, GitlabGetError + + +def check_if_integration_branch_is_up_to_date( + manifest_project, + integration_base, + project, + merge_request, +): + gitlab = manifest_project.manager.gitlab + + integration_branch = common.integration_branch_name( + project.name, merge_request.source_branch + ) + + with tempfile.TemporaryDirectory() as manifest_dir: + + # Construct clone url containing access token + clone_url = furl(manifest_project.http_url_to_repo) + clone_url.username = "gitlab-ci" + clone_url.password = gitlab.private_token + + # Checkout manifest + try: + manifest_repo = Repo.clone_from( + clone_url.url, manifest_dir, branch=integration_branch + ) + except GitCommandError as e: + sys.exit("ERROR: could not clone manifest repository\n" + str(e)) + + # Get branches + try: + integration_branch = manifest_repo.heads[integration_branch] + except IndexError as e: + sys.exit("ERROR: branch '%s' not found" % integration_branch) + try: + integration_base = manifest_repo.remote().refs[integration_base] + except IndexError as e: + sys.exit("ERROR: branch '%s' not found" % integration_base) + + # The integration branch is up to date if its parent is the integration base + up_to_date = integration_branch.commit.parents[0] == integration_base.commit + + return up_to_date + + +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( + "--manifest-project", + help="""name of the manifest project""", + dest="manifest_project", + required=True, + ) + parser.add_argument( + "--integration-base", + help="""manifest branch to branch off from""", + dest="integration_base", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the project, as specified in the manifest""", + dest="project", + required=True, + ) + parser.add_argument( + "--merge-request", + help="""project merge request IID containing the changes to be integrated""", + dest="merge_request", + required=True, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + + manifest_project = common.get_project(gitlab, args.manifest_project) + project = common.get_project(gitlab, args.project) + try: + merge_request = project.mergerequests.get( + args.merge_request, retry_transient_errors=True + ) + except GitlabGetError as e: + sys.exit( + "ERROR: could not get %s!%s: %s" + % (project.name, args.merge_request, e.error_message) + ) + + if check_if_integration_branch_is_up_to_date( + manifest_project=manifest_project, + integration_base=args.integration_base, + project=project, + merge_request=merge_request, + ): + print("Integration branch is up to date.") + else: + sys.exit("Integration branch is not up to date. Please re-run the pipeline.") + + +if __name__ == "__main__": + main()