Skip to content
Snippets Groups Projects
Commit aaf6331d authored by Tim Jaacks's avatar Tim Jaacks
Browse files

Move merge_into_manifest to dedicated function and add some documentation

parent 82e71669
No related branches found
No related tags found
1 merge request!6Move merge_into_manifest to dedicated function and add some documentation
Pipeline #8057 passed with stage
...@@ -12,6 +12,125 @@ from get_merge_requests import get_merge_requests ...@@ -12,6 +12,125 @@ from get_merge_requests import get_merge_requests
from integrate_into_manifest import integrate_into_manifest from integrate_into_manifest import integrate_into_manifest
def merge_into_manifest(gitlab, manifest_project, master_branch, project, commit):
"""
Create a merge request on the manifest for a given merged project commit and merge
it immediately. Update the integration branch before, if it is not up to date with
the current manifest master.
"""
# Get source merge request
mrs = get_merge_requests(
gitlab,
project,
target_branch=master_branch,
state="merged",
commit=commit,
)
if not mrs:
sys.exit(
"ERROR: could not determine source merge request for commit %s" % commit
)
source_mr = mrs[0]
# Get original branch for commit
original_branch = source_mr.source_branch
integration_branch = common.integration_branch_name(project.name, original_branch)
target_branch = master_branch
# Check if merge request already exists
mrs = get_merge_requests(
gitlab,
manifest_project,
source_branch=integration_branch,
target_branch=target_branch,
state="opened",
)
# If there already is a merge request, we assume that it has been opened manually
# and thus will be merged manually as well, so we exit with a failure here.
if mrs:
sys.exit("ERROR: There is already an open merge request:\n%s" % mrs[0].web_url)
# Check if branches exist
try:
manifest_project.branches.get(integration_branch)
except GitlabGetError:
sys.exit("ERROR: source branch '%s' does not exist." % integration_branch)
try:
manifest_project.branches.get(target_branch)
except GitlabGetError:
sys.exit("ERROR: target branch '%s' does not exist." % target_branch)
# Create new merge request
mr = manifest_project.mergerequests.create(
{
"source_branch": integration_branch,
"target_branch": target_branch,
"remove_source_branch": True,
"title": "Merge " + integration_branch,
}
)
print("Created new merge request:")
print(mr.web_url)
# Insert cross-links in both merge requests
mr.notes.create({"body": "Source merge request: %s" % source_mr.web_url})
source_mr.notes.create({"body": "Integration merge request: %s" % mr.web_url})
# Attempt to merge, reintegrate if necessary
manifest_revision = mr.sha
merged = False
while not merged:
merged = accept_merge_request(gitlab, manifest_project, mr)
if not merged:
# Note: if reintegration is necessary here, the source merge request was
# merged without running the pipeline on the latest manifest, i.e. some
# other project has been merged in between. Automatic rebase is not
# possible, though, because the altered manifest lines are part of the
# diff context, so we have to create a new integration commit. This
# possibly might result in a failing pipeline state on the master. We
# deliberately put up with this, as it is quite unlikely to happen and
# we want a completely automated process in every case.
manifest_revision = integrate_into_manifest(
gitlab=gitlab,
manifest_project=manifest_project,
integration_base=target_branch,
manifest_file=common.manifest_file,
project=project,
branch=original_branch,
commit=commit,
)
print("Successfully merged")
# Check if there is a running pipeline on the integration branch and cancel it.
# This happens when a reintegration was necessary before merging. The instant
# merge afterwards deletes the integration branch, so the pipeline on the branch
# will fail, because repo cannot checkout the code anymore. In order not to
# confuse people, we better cancel it. Since there is a pipeline running on the
# master after merging, we don't need the branch results anyway.
try:
pipelines = manifest_project.pipelines.list(
sha=manifest_revision,
ref=integration_branch,
retry_transient_errors=True,
)
except GitlabGetError:
print("WARNING: could not list pipelines for project '%s'" % project.name)
if pipelines:
pipeline = pipelines[0]
if pipeline.status in common.pending_states:
pipeline.cancel()
print(
"Cancelling running pipeline for integration branch '%s':"
% integration_branch
)
print(pipeline.web_url)
return manifest_revision
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
...@@ -63,118 +182,18 @@ def main(): ...@@ -63,118 +182,18 @@ def main():
project = common.get_project(gitlab, args.project) project = common.get_project(gitlab, args.project)
manifest_project = common.get_project(gitlab, args.manifest_project) manifest_project = common.get_project(gitlab, args.manifest_project)
# Get source merge request manifest_revision = merge_into_manifest(
mrs = get_merge_requests( gitlab=gitlab,
gitlab, manifest_project=manifest_project,
project, master_branch=args.master_branch,
target_branch=args.master_branch, project=project,
state="merged",
commit=args.commit, commit=args.commit,
) )
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 # Write new manifest revision to file for next pipeline stage
original_branch = source_mr.source_branch if args.revision_file:
integration_branch = common.integration_branch_name(project.name, original_branch) with open(args.revision_file, "w") as file:
target_branch = args.master_branch file.write(manifest_revision)
# Check if merge request already exists
mrs = get_merge_requests(
gitlab,
manifest_project,
source_branch=integration_branch,
target_branch=target_branch,
state="opened",
)
if mrs:
sys.exit("ERROR: There is already an open merge request:\n%s" % mrs[0].web_url)
with gitlab:
# Check if branches exist
try:
manifest_project.branches.get(integration_branch)
except GitlabGetError:
sys.exit("ERROR: source branch '%s' does not exist." % integration_branch)
try:
manifest_project.branches.get(target_branch)
except GitlabGetError:
sys.exit("ERROR: target branch '%s' does not exist." % target_branch)
# Create new merge request
mr = manifest_project.mergerequests.create(
{
"source_branch": integration_branch,
"target_branch": target_branch,
"remove_source_branch": True,
"title": "Merge " + integration_branch,
}
)
print("Created new merge request:")
print(mr.web_url)
# Insert cross-links in both merge requests
mr.notes.create({"body": "Source merge request: %s" % source_mr.web_url})
source_mr.notes.create({"body": "Integration merge request: %s" % mr.web_url})
# Attempt to merge, reintegrate if necessary
manifest_revision = mr.sha
merged = False
while not merged:
merged = accept_merge_request(gitlab, manifest_project, mr)
if not merged:
# Note: if reintegration is necessary here, the source merge request was
# merged without running the pipeline on the latest manifest, i.e. some
# other project has been merged in between. Automatic rebase is not
# possible, though, because the altered manifest lines are part of the
# diff context, so we have to create a new integration commit. This
# possibly might result in a failing pipeline state on the master.
manifest_revision = integrate_into_manifest(
gitlab=gitlab,
manifest_project=manifest_project,
integration_base=target_branch,
manifest_file=common.manifest_file,
project=project,
branch=original_branch,
commit=args.commit,
)
print("Successfully merged")
# Check if there is a running pipeline on the integration branch and cancel it.
# This happens when a reintegration was necessary before merging. The instant
# merge afterwards deletes the integration branch, so the pipeline on the branch
# will fail, because repo cannot checkout the code anymore. In order not to
# confuse people, we better cancel it. Since there is a pipeline running on the
# master after merging, we don't need the branch results anyway.
try:
pipelines = manifest_project.pipelines.list(
sha=manifest_revision,
ref=integration_branch,
retry_transient_errors=True,
)
except GitlabGetError:
print("WARNING: could not list pipelines for project '%s'" % project.name)
if pipelines:
pipeline = pipelines[0]
if pipeline.status in common.pending_states:
pipeline.cancel()
print(
"Cancelling running pipeline for integration branch '%s':"
% integration_branch
)
print(pipeline.web_url)
# Write new manifest revision to file for next pipeline stage
if args.revision_file:
with open(args.revision_file, "w") as file:
file.write(manifest_revision)
if __name__ == "__main__": if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment