Skip to content
Snippets Groups Projects
Commit 6c707e38 authored by Lorenzo Pagliai's avatar Lorenzo Pagliai
Browse files

Include integrate_into_layer.py script

* The script is derived from the integrate_into_manifest file and is
used to create the integration branch on layers
* The script create a new branch with the modifications on the
SRCREV.conf indicated as parameter and on the bitbake recipe indicated
* In a future this file could be merged with the integrate_inot_manifest
one
parent 9998c3dd
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python3
import common
import argparse
import logging
import sys
import tempfile
import re
from pathlib import Path
from furl import furl
from git import GitCommandError, Repo
from gitlab import Gitlab
from gitlab.v4.objects import Project
from lxml import etree
def update_srcrev(srcrev, recipe_name, new_revision):
# Check if project is referenced in SRCREV.conf
# Match "...RECIPE_NAME ="
pattern = re.compile("{}[ ,\t]{{0,}}?=".format(recipe_name))
project_line = None
for line in srcrev.splitlines():
if pattern.search(line):
project_line = line
break
if project_line is None:
return None
# Get current project revision from SRCREV file
# Assuming notation: <project> = "<hash>"
old_revision = project_line.split('"')[1]
# Update SRCREV file
srcrev = srcrev.replace(old_revision, new_revision)
return srcrev
def integrate_into_layer(
layer_project: Project,
layer_branch,
srcrev_file,
recipe_name,
project: Project,
merge_request,
):
gitlab = layer_project.manager.gitlab
with tempfile.TemporaryDirectory() as layer_dir:
srcrev_filepath = Path(layer_dir) / srcrev_file
# Construct clone url containing access token
clone_url = furl(layer_project.http_url_to_repo)
print("This is the url to clone", clone_url.url)
clone_url.username = "gitlab-ci"
clone_url.password = gitlab.private_token
# Checkout layer
# TODO replace checkout with gitlab api access
print("Cloning layer repo: %s" % layer_project.http_url_to_repo)
try:
layer_repo = Repo.clone_from(
clone_url.url, layer_dir, branch=layer_branch
)
except GitCommandError as e:
sys.exit("ERROR: could not clone layer repository\n" + str(e))
except IndexError:
sys.exit("ERROR: branch '%s' not found" % layer_branch)
# Special handling for the gitlab-ci integration
# When the branch 'merge_request.source_branch' already starts with
# integrate/gitlab-ci we add our new commit to this branch
# Otherwise (normal behaviour) a new integration branch is created
integration_branch = common.find_gitlab_ci_integration_branch(
layer_repo, merge_request.source_branch
)
if integration_branch is not None:
layer_repo.git.checkout(
"-b", integration_branch, "origin/{}".format(integration_branch)
)
logging.debug("Heads: %s", layer_repo.heads)
layer_repo.heads[integration_branch].checkout()
logging.debug(layer_repo.git.log("--oneline", "-n", "5"))
print("Using existing integration branch: %s" % integration_branch)
else:
# Create integration branch (delete former one if already exists)
integration_branch = recipe_name + "/" + merge_request.source_branch
for ref in layer_repo.references:
if integration_branch == ref.name:
layer_repo.delete_head(ref)
print("Creating integration branch: %s" % integration_branch)
layer_repo.head.set_reference(
layer_repo.create_head(integration_branch)
)
with open('integration_branch_file', "w", encoding="utf-8") as file:
file.write(integration_branch)
# Get new project revision from merge request
new_revision = merge_request.sha
with open(srcrev_filepath, "r", encoding="utf8") as fp:
srcrev = fp.read()
new_srcrev = update_srcrev(srcrev, recipe_name, new_revision)
# write file
if new_srcrev is None:
sys.exit(
"ERROR: project '%s' not found in layer and "
"no recipe name is specified" % project.path
)
with open(srcrev_filepath.as_posix(), "w", encoding="utf8") as fp:
fp.write(new_srcrev)
layer_repo.index.add([srcrev_file])
# Make an API request to create the gitlab.user object
gitlab.auth()
# Construct commit message and commit the change
message = "Integrate %s/%s\n%s" % (
project.path,
merge_request.source_branch,
common.list_commits(merge_request.commits()),
)
layer_revision = common.commit_and_push(
layer_project,
layer_repo,
message,
gitlab.user.username,
gitlab.user.email,
)
logging.debug("New revision in layer: %s", layer_revision)
return layer_revision
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 for the layer group""",
dest="token",
required=True,
)
parser.add_argument(
"--layer-project",
help="""name of the yocto layer project""",
dest="layer_project",
required=True,
)
parser.add_argument(
"--layer-branch",
help="""yocto layer branch to branch off from""",
dest="layer_branch",
required=True,
)
parser.add_argument(
"--srcrev-file",
help="""source revision file name (default: 'SRCREV.conf')""",
dest="srcrev_file",
default=common.srcrev_file,
required=False,
)
parser.add_argument(
"--recipe-name",
help="""recipe name to resolve project in 'SRCREV.conf'""",
dest="recipe_name",
default=None,
required=False,
)
parser.add_argument(
"--project",
help="""name of the project, as specified in the layer""",
dest="project",
required=True,
)
parser.add_argument(
"--merge-request",
help="""project merge request IID or link containing the
changes to be integrated""",
dest="merge_request",
required=True,
)
parser.add_argument(
"--save-revision-to",
help="""path to a file where the new layer revision is stored""",
dest="revision_file",
required=False,
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="""Increase verbosity.""",
)
args, _ = parser.parse_known_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
logging.debug(args)
gitlab = Gitlab(args.gitlab_url, private_token=args.token)
layer_project = common.get_project(gitlab, args.layer_project)
project = common.get_project(gitlab, args.project)
logging.debug("Project: %s", project.name)
logging.debug("Merge Request: %s", args.merge_request)
gitlab = Gitlab(args.gitlab_url, private_token=args.token)
merge_request = common.get_merge_request(project, args.merge_request)
if merge_request is None:
sys.exit("ERROR: could not get %s %s" % (project.name, args.merge_request))
layer_revision = integrate_into_layer(
layer_project=layer_project,
layer_branch=args.layer_branch,
srcrev_file=args.srcrev_file,
recipe_name=args.recipe_name,
project=project,
merge_request=merge_request,
)
if args.revision_file:
with open(args.revision_file, "w", encoding="utf-8") as file:
file.write(layer_revision)
if __name__ == "__main__":
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