Skip to content
Snippets Groups Projects
Commit 4f194e21 authored by Jonas Höppner's avatar Jonas Höppner
Browse files

CI: Check: integration branch may have multiple commits

As all projects are commited in the same branch the 'up-to-date' check
may not only check if the first parent commit points to the
master/dunfell branch. Now it is needed to loop through the history
until the integration branch's commit is found.

On fail a message is displayed which merge request needs to be
retriggered manually. This can now also be the 'parent'-MR that
triggered the complete chain.

The check job is used pipeline again.

The retrigger job also looks in the .gitlab-ci project for check jobs to
retrigger.
parent 873ae97f
No related branches found
No related tags found
1 merge request!101CI: Create pipeline to deploy changes in gitlab-ci to all subprojects, include all CI implementations from there.
......@@ -19,8 +19,7 @@ default:
stages:
- analyze
- deploy
- integrate
- test
- check
workflow:
rules:
......@@ -70,6 +69,7 @@ workflow:
--manifest-project=${MANIFEST_PROJECT}
--submodule=.gitlab-ci
--revision=${CI_COMMIT_SHA}
--verbose
${MERGE}
${DEPLOY_TO}
......@@ -78,6 +78,7 @@ workflow:
--image=${CI_IMAGE_PYTHON}
--branch="integrate/${CI_PROJECT_NAME}/${CI_COMMIT_REF_NAME}"
--manifest-project=${MANIFEST_PROJECT}
--parent_merge_request="${CI_MERGE_REQUEST_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}"
--verbose
${DEPLOY_TO}
> integration.yml
......@@ -99,13 +100,41 @@ deploy-foobar:
${PROJECT_ROOT}/minimal-bar
trigger-foobar:
stage: integrate
stage: deploy
needs: [deploy-foobar]
trigger:
include:
- artifact: integration.yml
job: deploy-foobar
strategy: depend
# --------------------------------------------------------------------------------------
# Stage: check
# --------------------------------------------------------------------------------------
check:
stage: check
rules:
- if: $CI_MERGE_REQUEST_IID
tags:
- infrastructure
timeout: 2m
script:
- cd ${CI_PROJECT_DIR}
- MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
- PROJECT_ROOT=${CI_PROJECT_ROOT_NAMESPACE}/yocto/infrastructure/ci-test
- MANIFEST_PROJECT=${PROJECT_ROOT}/minimal-manifest
- MASTER_BRANCH=master
- ./check_if_integration_branch_is_up_to_date.py
--gitlab-url=${CI_SERVER_URL}
--token=${GITBOT_TOKEN}
--manifest-project=${MANIFEST_PROJECT}
--integration-base=${MASTER_BRANCH}
--project=${CI_PROJECT_PATH}
--merge-request=${MERGE_REQUEST}
--verbose
# TODO repeat this for yocto manifest
# ---------------------------------------------------------------------------------------
# Stage: deploy
......
......@@ -4,6 +4,7 @@ import common
import argparse
import sys
import tempfile
import logging
from furl import furl
from git import GitCommandError, Repo
from gitlab import Gitlab, GitlabGetError
......@@ -17,10 +18,6 @@ def check_if_integration_branch_is_up_to_date(
):
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
......@@ -31,17 +28,24 @@ def check_if_integration_branch_is_up_to_date(
# Checkout manifest
try:
manifest_repo = Repo.clone_from(
clone_url.url, manifest_dir, branch=integration_branch
clone_url.url, manifest_dir
)
except GitCommandError as e:
sys.exit("ERROR: could not clone manifest repository\n" + str(e))
branch = common.find_gitlab_ci_integration_branch(
# Handle gitlab-ci integration
integration_branch = common.find_gitlab_ci_integration_branch(
manifest_repo,
merge_request.source_branch
)
if branch is not None:
integration_branch = branch
if integration_branch is None:
integration_branch = common.integration_branch_name(
project.name, merge_request.source_branch
)
logging.debug("Checking integration branch: %s", integration_branch)
manifest_repo.git.checkout('-b', integration_branch, "origin/{}".format(integration_branch))
# Get branches
try:
......@@ -53,10 +57,20 @@ def check_if_integration_branch_is_up_to_date(
except IndexError:
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
logging.debug("Checking integration base: %s", integration_base)
parent = integration_branch.commit.parents[0]
while True:
logging.debug("Parent of integration branch: %s", parent)
# The integration branch is up to date if its parent is the integration base
if parent == integration_base.commit:
logging.debug("Found match")
return True
if len(parent.parents) > 0:
parent = parent.parents[0]
else:
return False
return up_to_date
return False
def main():
......@@ -97,11 +111,25 @@ def main():
dest="merge_request",
required=True,
)
parser.add_argument(
"--parent-merge-request",
help="""parent merge requests link, only used for a hint when the check failes""",
dest="parent_merge_request",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="""Increase verbosity.""",
)
args, _ = parser.parse_known_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
gitlab = Gitlab(args.gitlab_url, private_token=args.token)
logging.debug(args)
manifest_project = common.get_project(gitlab, args.manifest_project)
project = common.get_project(gitlab, args.project)
merge_request = common.get_merge_request( project, args.merge_request)
......@@ -119,11 +147,15 @@ def main():
):
print("Integration branch is up to date.")
else:
mr_url=merge_request.web_url + "/pipelines"
if args.parent_merge_request is not None:
mr_url=args.parent_merge_request + "/pipelines"
sys.exit(
"Integration branch is not up to date. Please re-run the MR pipeline:\n"
" 1. Open the MR pipelines page:\n"
" %s\n"
" 2. Click 'Run Pipeline'" % (merge_request.web_url + "/pipelines")
" 2. Click 'Run Pipeline'" % (mr_url)
)
......
......@@ -25,7 +25,7 @@ def update_rev_in_gitlab_ci(repo, submodule_project, submodule_revision):
repo.git.add(gitlab_ci_yml)
def deploy_into(project, submodule, revision, branch, replace_exising_branch=False):
def deploy_into(project, submodule, revision, branch, replace_existing_branch=False):
"""Update the submodule and include refs to the submodule in the given project.
Create mergerequest if needed.
......@@ -34,7 +34,7 @@ def deploy_into(project, submodule, revision, branch, replace_exising_branch=Fal
submodule_name (string): The name of the submodule to pull
submodule_revision (hex string): The sha hash of the commit to update the submodule to
branch (string): branch to update, if None, the projects default branch is used
replace_exising_branch: When an existing integration branch is found it is always replaced.
replace_existing_branch: When an existing integration branch is found it is always replaced.
Returns: tuple of:
branch (string): Name of the newly created integration branch
......@@ -47,7 +47,7 @@ def deploy_into(project, submodule, revision, branch, replace_exising_branch=Fal
revision,
branch,
pre_commit_hook=update_rev_in_gitlab_ci,
replace_exising_branch=replace_exising_branch,
replace_existing_branch=replace_existing_branch,
)
logging.debug("Integration branch: %s", integration_branch)
......@@ -156,7 +156,7 @@ def main():
args.submodule,
args.revision,
args.branch,
replace_exising_branch=len(args.projects) > 0,
replace_existing_branch=len(args.projects) > 0,
)
merge_request_manifest = mr
merge_requests = []
......
......@@ -84,9 +84,9 @@ integrate:
- printenv
- cd ${CI_PROJECT_DIR}
- if [ -n "${CI_MERGE_REQUEST_IID}" ];then
MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
else
MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
fi
- .gitlab-ci/integrate_into_manifest.py
--gitlab-url=${CI_SERVER_URL}
......@@ -148,18 +148,25 @@ check:
rules:
- if: $CI_MERGE_REQUEST_IID
# Explicitly allow externally triggered pipelines in every case
# TODO disabled for now, - if: $CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "api"
- if: $CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "api"
needs: ["integrate"]
tags:
- infrastructure
timeout: 2m
script:
- printenv
- cd ${CI_PROJECT_DIR}
- if [ -n "${CI_MERGE_REQUEST_IID}" ];then
MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
else
MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
fi
- if [ -n "${parent_merge_request}" ];then
PARENT_MR="--parent-merge-request=${parent_merge_request}";
fi
- echo "${parent_merge_request}"
- echo "${PARENT_MR}"
- echo "${MERGE_REQUEST}"
- .gitlab-ci/check_if_integration_branch_is_up_to_date.py
--gitlab-url=${CI_SERVER_URL}
--token=${GITBOT_TOKEN}
......@@ -167,3 +174,5 @@ check:
--integration-base=${MASTER_BRANCH}
--project=${CI_PROJECT_PATH}
--merge-request=${MERGE_REQUEST}
--verbose
${PARENT_MR}
......@@ -55,6 +55,10 @@ retrigger:
--manifest=default.xml
--remote=ci-test
)
# Add the gitlab-ci project
- PROJECTS="$PROJECTS ${CI_PROJECT_ROOT_NAMESPACE}/yocto/infrastructure/gitlab-ci"
# TODO retrigger gitlab-ci integration also
# Retrigger also project in SRCREV
- echo -e "Projects:\n${PROJECTS}"
- for PROJECT in ${PROJECTS}; do
.gitlab-ci/retrigger_mr_pipeline_jobs.py
......
......@@ -31,6 +31,10 @@ default:
{{ projectshort }}:
stage: integrate
needs: [ {{ projectneeds.project }} ]
{% if parent_merge_request is defined %}
variables:
parent_merge_request: {{ parent_merge_request }}
{% endif %}
trigger:
project: {{ project }}
branch: {{ branch }}
......
......@@ -17,7 +17,7 @@ def update_submodule(
submodule_revision,
branch=None,
pre_commit_hook=None,
replace_exising_branch=False,
replace_existing_branch=False,
):
"""Update submodule of gitlab project to given revision
......@@ -28,7 +28,7 @@ def update_submodule(
branch (string): branch to update, if None, the projects default branch is used
pre_commit_hook: Function to be called before the actual commit is done, to add additional changes.
Arguments passed: ( repo, submodule_project, submodule_revision)
replace_exising_branch: When an existing integration branch is found it is always replaced.
replace_existing_branch: When an existing integration branch is found it is always replaced.
Returns: tuple of:
branch (string): Name of the newly created integration branch
revision (string): hexsha of the new commit
......@@ -124,7 +124,7 @@ def update_submodule(
if existing_branch:
repo.head.set_reference(existing_branch)
submodule = common.get_submodule(repo, submodule_name)
if replace_exising_branch or submodule.hexsha != submodule_revision:
if replace_existing_branch or submodule.hexsha != submodule_revision:
print("Replacing outdated integration branch %s" % integration_branch)
repo.head.set_reference(branch)
submodule = common.get_submodule(repo, submodule_name)
......
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