Exemple #1
0
def update_github_statuses(self, trigger):
    descriptions = {
        "pending": "Pipeline in-progress",
        "success": "Pipeline success",
        "error": "Pipeline in error or canceled",
        "failure": "Pipeline failed"
    }

    gitlab_project_id = trigger['ci_project_id']
    github_repo = trigger['github_repo']
    sha = trigger['sha']
    installation_id = trigger['installation_id']
    context = trigger['context']
    ref = trigger['ci_ref']
    pending = False
    gitlabclient = GitlabClient()
    githubclient = GithubClient(installation_id=installation_id)
    try:
        pipelines = {}
        project = gitlabclient.get_project(gitlab_project_id)
        project_url = project['web_url']
        pipelines = gitlabclient.get_pipelines(int(gitlab_project_id), ref=ref)
        if not pipelines:
            logger.info('no pipelines')
            raise self.retry(countdown=60)
        pipe = pipelines[0]
        state = GITHUB_STATUS_MAP[pipe['status']]
        pending = state == "pending"
        pipeline_body = {
            "state": state,
            "target_url": project_url + "/pipelines/%s" % pipe['id'],
            "description": descriptions[state],
            "context": "%s/pipeline" % context
        }
        resp = []
        resp.append(githubclient.post_status(pipeline_body, github_repo, sha))
        builds = gitlabclient.get_jobs(project['id'], pipe['id'])
        if not builds:
            logger.info('no builds')
            raise self.retry(countdown=60)
        pdict = {'builds': {}}
        for build in builds:
            if build['name'] not in pdict['builds']:
                pdict[build['name']] = []
            pdict[build['name']].append(build)

        for _, builds in pdict['builds'].items():
            build = sorted(builds, key=lambda x: x['id'], reverse=True)[0]
            if build['status'] not in ['skipped', 'created']:
                resp.append(
                    update_github_status(project, build, github_repo, sha,
                                         installation_id, context))
        if pending:
            logger.info('still pending: retry')
            time.sleep(10)
            raise self.retry(exc=None, countdown=60)
        return resp
    except requests.exceptions.RequestException as exc:
        logger.error('Error request')
        raise self.retry(countdown=60, exc=exc)
Exemple #2
0
def update_pipeline_status(gitlab_project_id, pipeline_id):
    '''
    Queries GitLab to get the pipeline status and then update the GitHub statuses
    '''
    gitlabclient = GitlabClient()
    project = gitlabclient.get_project(gitlab_project_id)
    pipeline_attr = gitlabclient.get_pipeline_status(gitlab_project_id,
                                                     pipeline_id)

    return post_pipeline_status(project, pipeline_attr)
Exemple #3
0
def update_build_status(self, params):
    try:
        gitlab_project_id = params['ci_project_id']
        github_repo = params['github_repo']
        sha = params['sha']
        installation_id = params['installation_id']
        build_id = params['build_id']
        gitlabclient = GitlabClient()
        project = gitlabclient.get_project(gitlab_project_id)
        build = gitlabclient.get_job(project['id'], build_id)
        return update_github_status(project, build, github_repo, sha,
                                    installation_id)
    except Exception as exc:
        self.retry(countdown=60, exc=exc)
Exemple #4
0
def retry_build(self, external_id, sha=None):
    project_id = external_id['project_id']
    object_id = external_id['object_id']
    kind = external_id['object_kind']
    gitlabclient = GitlabClient()
    try:
        if kind == "build":
            return gitlabclient.retry_build(project_id, object_id)
        elif kind == "pipeline":
            return gitlabclient.retry_pipeline(project_id, sha)

    except requests.exceptions.RequestException as exc:
        logger.error('Error request')
        raise self.retry(countdown=60, exc=exc)
Exemple #5
0
def update_github_check(event):
    gitlabclient = GitlabClient()
    checkstatus = CheckStatus(event)
    installation_id = gitlabclient.get_variable(
        checkstatus.project_id, 'GITHUB_INSTALLATION_ID')['value']
    github_repo = gitlabclient.get_variable(checkstatus.project_id,
                                            'GITHUB_REPO')['value']
    githubclient = GithubClient(installation_id=installation_id)

    # Skip queued builds as they could be 'manual'
    if checkstatus.status == "queued" and checkstatus.object_kind == "build":
        return None

    if checkstatus.object_kind == "pipeline":
        githubclient.post_status(checkstatus.render_pipeline_status(),
                                 github_repo, checkstatus.sha)
    return githubclient.create_check(github_repo, checkstatus.render_check())
Exemple #6
0
def post_pipeline_status(project, pipeline_attr):
    '''
    POST the pipeline status on GitHub
    '''
    descriptions = {
        "pending": "Pipeline in-progress",
        "success": "Pipeline success",
        "error": "Pipeline in error or canceled",
        "failure": "Pipeline failed"
    }
    gitlabclient = GitlabClient()
    installation_id = gitlabclient.get_variable(
        project['id'], 'GITHUB_INSTALLATION_ID')['value']
    github_repo = gitlabclient.get_variable(project['id'],
                                            'GITHUB_REPO')['value']

    githubclient = GithubClient(installation_id=installation_id)
    sha = pipeline_attr['sha']
    context = FFCONFIG.github['context']
    state = GITHUB_STATUS_MAP[pipeline_attr['status']]
    pipeline_body = {
        "state":
            state,
        "target_url":
            project['web_url'] + "/pipelines/%s" % pipeline_attr['id'],
        "description":
            descriptions[state],
        "context":
            "%s/pipeline" % context
    }
    resync_body = {
        "state":
            "success",
        "target_url":
            FFCONFIG.failfast['failfast_url'] + "/api/v1/resync/%s/%s" %
            (project['id'], pipeline_attr['id']),
        "description":
            "resync-gitlab status",
        "context":
            "%s/resync-gitlab" % context
    }
    githubclient.post_status(resync_body, github_repo, sha)
    return githubclient.post_status(pipeline_body, github_repo, sha)
Exemple #7
0
def migrate_variables(project_source_id, project_target_id):
    client = GitlabClient()
    variables = client.get_variables(project_source_id)
Exemple #8
0
    def trigger_pipeline(self):
        gevent = self.ghevent
        gitlab_user = self.config.gitlab['robot-user']
        dirpath = tempfile.mkdtemp()
        repo_path = os.path.join(dirpath, "repo")
        gitbin = self._checkout_repo(gevent, repo_path)

        try:
            ci_file = self._get_ci_file(repo_path)
        except ResourceNotFound:
            raise Unexpected("Could not find a CI config file in: %s" %
                             (repo_path))

        try:
            content = self._parse_ci_file(ci_file['content'], ci_file['file'])
        except YAMLComposeError:
            raise Unexpected("Could not parse CI file: %s" % (ci_file['file']),
                             {})

        lint_resp = GitlabClient().gitlabci_lint(ci_file['content'])
        logger.error(lint_resp)
        logger.error(content)
        if 'status' not in lint_resp or lint_resp['status'] != 'valid':
            raise Unexpected(".gitlab-ci.yml syntax error", {})

        variables = content.get('variables', dict())

        namespace = variables.get('FAILFASTCI_NAMESPACE',
                                  self.config.gitlab.get('namespace', None))
        repo = variables.get('GITLAB_REPOSITORY', None)
        reponame = gevent.repo.replace("/", "_")
        if repo:
            namespace, reponame = repo.split('/')
        gitlab_endpoint = variables.get(
            'GITLAB_URL', self.config.gitlab.get('gitlab_url', None))
        self.gitlab = GitlabClient(gitlab_endpoint, config=self.config)

        ci_project = self.gitlab.initialize_project(reponame, namespace)

        # @Todo(ant31) check if clone_url is required
        # clone_url = clone_url_with_auth(gevent.clone_url, "bot:%s" % self.github.token)
        target_url = clone_url_with_auth(
            ci_project['http_url_to_repo'],
            "%s:%s" % (gitlab_user, self.gitlab.gitlab_token))
        gitbin.remote('add', 'target', target_url)

        variables.update({
            'EVENT':
            gevent.event_type,
            'PR_ID':
            str(gevent.pr_id),
            'SHA':
            gevent.head_sha,
            'SHA8':
            gevent.head_sha[0:8],
            'FAILFASTCI_STATUS_API':
            ('%s/api/v1/github_status' %
             (self.config.failfast['failfast_url'], )),
            'SOURCE_REF':
            gevent.refname,
            'REF_NAME':
            gevent.refname,
            'CI_REF':
            gevent.target_refname,
            'GITHUB_INSTALLATION_ID':
            str(gevent.installation_id),
            'GITHUB_REPO':
            gevent.repo
        })

        content['variables'] = variables

        self.gitlab.set_variables(
            ci_project['id'], {
                'GITHUB_INSTALLATION_ID': str(gevent.installation_id),
                'GITHUB_REPO': gevent.repo
            })
        perform_sync = variables.get("FAILFAST_SYNC_REPO", "false")

        if ((perform_sync == "true") or (DEFAULT_MODE == "sync")):
            # Full synchronize the repo)
            gitbin.push("target", 'HEAD:%s' % gevent.target_refname, "-f")
            ci_sha = str(gitbin.rev_parse('HEAD'))
            return {  # NOTE: the GitHub reference details for subsequent tasks.
                'sha': gevent.head_sha,
                'ci_sha': ci_sha,
                'ref': gevent.refname,
                'ci_ref': gevent.target_refname,
                'ci_project_id': ci_project['id'],
                'installation_id': gevent.installation_id,
                'github_repo': gevent.repo,
                'context': self.config.github['context']
            }
        else:
            self.sync_only_ci_file(gevent, content, ci_project, ci_file)
Exemple #9
0
class Pipeline(object):
    def __init__(self, git_event, config=None):
        if config is None:
            config = FFCONFIG
        self.ghevent = git_event
        self.config = config
        self.github = GithubClient(
            installation_id=self.ghevent.installation_id)

    def _parse_ci_file(self, content, filepath):
        if filepath == ".gitlab-ci.yml":
            return yaml.safe_load(content)

    def _checkout_repo(self, gevent, repo_path):
        clone_url = clone_url_with_auth(gevent.clone_url,
                                        "bot:%s" % self.github.token)
        try_count = 0
        while try_count < 3:
            try:
                time.sleep(1)
                gitbin = Repo.clone_from(clone_url, repo_path).git
                break
            except Exception:
                try_count = try_count + 1
                if try_count >= 3:
                    raise

        gitbin.config("http.postBuffer", "1524288000")
        gitbin.config("--local", "user.name", "FailFast-ci Bot")
        gitbin.config("--local", "user.email", "*****@*****.**")
        if gevent.pr_id == "":
            gitbin.checkout(gevent.refname)
        else:
            pr_branch = "pr-%s" % gevent.pr_id
            gitbin.fetch('origin',
                         "pull/%s/head:%s" % (gevent.pr_id, pr_branch))
            gitbin.checkout(pr_branch)
        if not gitbin.rev_parse('HEAD') == gevent.head_sha:
            raise Unexpected("git sha don't match", {
                'expected_sha': gevent.head_sha,
                'sha': gitbin.rev_parse('HEAD')
            })
        return gitbin

    def _get_ci_file(self, repo_path):
        content = None
        for filepath in [".gitlab-ci.yml", ".failfast-ci.jsonnet"]:
            path = os.path.join(repo_path, filepath)
            if not os.path.exists(path):
                continue
            with open(path, 'r') as f:
                content = f.read()
                return {"content": content, "file": filepath}
        if content is None:
            raise ResourceNotFound("no .gitlab-ci.yml or .failfast-ci.jsonnet")

    def trigger_pipeline(self):
        gevent = self.ghevent
        gitlab_user = self.config.gitlab['robot-user']
        dirpath = tempfile.mkdtemp()
        repo_path = os.path.join(dirpath, "repo")
        gitbin = self._checkout_repo(gevent, repo_path)

        try:
            ci_file = self._get_ci_file(repo_path)
        except ResourceNotFound:
            raise Unexpected("Could not find a CI config file in: %s" %
                             (repo_path))

        try:
            content = self._parse_ci_file(ci_file['content'], ci_file['file'])
        except YAMLComposeError:
            raise Unexpected("Could not parse CI file: %s" % (ci_file['file']),
                             {})

        lint_resp = GitlabClient().gitlabci_lint(ci_file['content'])
        logger.error(lint_resp)
        logger.error(content)
        if 'status' not in lint_resp or lint_resp['status'] != 'valid':
            raise Unexpected(".gitlab-ci.yml syntax error", {})

        variables = content.get('variables', dict())

        namespace = variables.get('FAILFASTCI_NAMESPACE',
                                  self.config.gitlab.get('namespace', None))
        repo = variables.get('GITLAB_REPOSITORY', None)
        reponame = gevent.repo.replace("/", "_")
        if repo:
            namespace, reponame = repo.split('/')
        gitlab_endpoint = variables.get(
            'GITLAB_URL', self.config.gitlab.get('gitlab_url', None))
        self.gitlab = GitlabClient(gitlab_endpoint, config=self.config)

        ci_project = self.gitlab.initialize_project(reponame, namespace)

        # @Todo(ant31) check if clone_url is required
        # clone_url = clone_url_with_auth(gevent.clone_url, "bot:%s" % self.github.token)
        target_url = clone_url_with_auth(
            ci_project['http_url_to_repo'],
            "%s:%s" % (gitlab_user, self.gitlab.gitlab_token))
        gitbin.remote('add', 'target', target_url)

        variables.update({
            'EVENT':
            gevent.event_type,
            'PR_ID':
            str(gevent.pr_id),
            'SHA':
            gevent.head_sha,
            'SHA8':
            gevent.head_sha[0:8],
            'FAILFASTCI_STATUS_API':
            ('%s/api/v1/github_status' %
             (self.config.failfast['failfast_url'], )),
            'SOURCE_REF':
            gevent.refname,
            'REF_NAME':
            gevent.refname,
            'CI_REF':
            gevent.target_refname,
            'GITHUB_INSTALLATION_ID':
            str(gevent.installation_id),
            'GITHUB_REPO':
            gevent.repo
        })

        content['variables'] = variables

        self.gitlab.set_variables(
            ci_project['id'], {
                'GITHUB_INSTALLATION_ID': str(gevent.installation_id),
                'GITHUB_REPO': gevent.repo
            })
        perform_sync = variables.get("FAILFAST_SYNC_REPO", "false")

        if ((perform_sync == "true") or (DEFAULT_MODE == "sync")):
            # Full synchronize the repo)
            gitbin.push("target", 'HEAD:%s' % gevent.target_refname, "-f")
            ci_sha = str(gitbin.rev_parse('HEAD'))
            return {  # NOTE: the GitHub reference details for subsequent tasks.
                'sha': gevent.head_sha,
                'ci_sha': ci_sha,
                'ref': gevent.refname,
                'ci_ref': gevent.target_refname,
                'ci_project_id': ci_project['id'],
                'installation_id': gevent.installation_id,
                'github_repo': gevent.repo,
                'context': self.config.github['context']
            }
        else:
            self.sync_only_ci_file(gevent, content, ci_project, ci_file)

    # @TODO this is a partial implem
    def sync_only_ci_file(self, gevent, content, ci_project, ci_file):
        """ Push only the .failfast-ci.yaml and set token to clone """
        tokenkey = "GH_TOKEN_%s" % str.upper(uuid.uuid4().hex)
        clone_url = gevent.clone_url.replace("https://",
                                             "https://bot:$%s:" % tokenkey)
        ci_branch = gevent.refname
        content['variables'].update({'SOURCE_REPO': clone_url})
        self.gitlab.set_variables(ci_project['id'],
                                  {tokenkey: self.github.token})
        return self.gitlab.push_file(project_id=ci_project['id'],
                                     file_path=ci_file['file'],
                                     file_content=yaml.safe_dump(content),
                                     branch=ci_branch,
                                     message=gevent.commit_message)
Exemple #10
0
class Pipeline(object):
    def __init__(self, git_event):
        self.ghevent = git_event
        self.github = GithubClient(
            installation_id=self.ghevent.installation_id)

    def _parse_ci_file(self, content, filepath):
        if filepath == ".gitlab-ci.yml":
            return yaml.safe_load(content)

    def _checkout_repo(self, gevent, repo_path):
        clone_url = clone_url_with_auth(gevent.clone_url,
                                        "bot:%s" % self.github.token)
        try_count = 0
        while try_count < 3:
            try:
                time.sleep(1)
                gitbin = Repo.clone_from(clone_url, repo_path).git
                break
            except Exception:
                try_count = try_count + 1
                if try_count >= 3:
                    raise

        gitbin.config("http.postBuffer", "1524288000")
        gitbin.config("--local", "user.name", "FailFast-ci Bot")
        gitbin.config("--local", "user.email", "*****@*****.**")
        if gevent.pr_id == "":
            gitbin.checkout(gevent.refname)
        else:
            pr_branch = "pr-%s" % gevent.pr_id
            gitbin.fetch('origin',
                         "pull/%s/head:%s" % (gevent.pr_id, pr_branch))
            gitbin.checkout(pr_branch)
        if not gitbin.rev_parse('HEAD') == gevent.head_sha:
            raise Unexpected("git sha don't match", {
                'expected_sha': gevent.head_sha,
                'sha': gitbin.rev_parse('HEAD')
            })
        return gitbin

    def _get_ci_file(self, repo_path):
        content = None
        for filepath in [".gitlab-ci.yml", ".failfast-ci.jsonnet"]:
            path = os.path.join(repo_path, filepath)
            if not os.path.exists(path):
                continue
            with open(path, 'r') as f:
                content = f.read()
                return {"content": content, "file": filepath}
        if content is None:
            raise ResourceNotFound(
                "n o .gitlab-ci.yml or .failfail-ci.jsonnet")

    def _append_update_stage(self, content):
        stage_name = "github-status-update"
        url = FAILFASTCI_API + "/api/v1/github_statuses"
        update_status = {
            "ci_project_id": "$CI_PROJECT_ID",
            "ci_sha": "$CI_BUILD_REF",
            "sha": "$SHA",
            "ci_ref": "$CI_COMMIT_REF_NAME",
            "github_repo": "$GITHUB_REPO",
            "installation_id": "$GITHUB_INSTALLATION_ID",
            "delay": 150
        }
        update_status_30 = deepcopy(update_status)
        update_status_30['delay'] = 30
        params_150 = json.dumps(update_status)
        params_30 = json.dumps(update_status_30)
        job = {
            "image":
            "python:2.7",
            "stage":
            stage_name,
            "before_script": [],
            "after_script": [
                "curl -XPOST %s -d \"%s\" || true" %
                (url, params_30.replace('"', '\\\"')),
                "curl -XPOST %s -d \"%s\" || true" %
                (url, params_150.replace('"', '\\\"'))
            ],
            "script": [
                "echo curl -XPOST %s -d \"%s\" || true" %
                (url, params_30.replace('"', '\\\"')),
                "echo curl -XPOST %s -d \"%s\" || true" %
                (url, params_150.replace('"', '\\\"'))
            ],
            "when":
            "always"
        }

        if isinstance(FAILFASTCI_REQUIRE_RUNNER_TAG, str) and \
                bool(FAILFASTCI_REQUIRE_RUNNER_TAG):
            job['tags'] = [FAILFASTCI_REQUIRE_RUNNER_TAG]

        content['stages'].append(stage_name)
        content['report-status'] = job

    def _append_update_build(self, content):
        params = json.dumps({
            "ci_project_id": "$CI_PROJECT_ID",
            "ci_sha": "$CI_BUILD_REF",
            "sha": "$SHA",
            "build_id": "$CI_BUILD_ID",
            "github_repo": "$GITHUB_REPO",
            "installation_id": "$GITHUB_INSTALLATION_ID",
            "delay": 45
        })
        url = FAILFASTCI_API + "/api/v1/github_status"
        task = "curl -m 45 --connect-timeout 45 -XPOST %s -d \"%s\" || true" % (
            url, params.replace('"', '\\\"'))
        for key, job in content.items():
            if key in GITLAB_CI_KEYS or key[0] == ".":
                continue
            if "after_script" not in job:
                job['after_script'] = []
            if task not in job:
                if task not in job['after_script']:
                    job['after_script'].append(task)

    def trigger_pipeline(self):
        gevent = self.ghevent
        gitlab_user = GITLAB_USER
        dirpath = tempfile.mkdtemp()
        repo_path = os.path.join(dirpath, "repo")
        gitbin = self._checkout_repo(gevent, repo_path)

        try:
            ci_file = self._get_ci_file(repo_path)
        except ResourceNotFound as e:
            raise Unexpected("Could not find a CI config file in: %s" %
                             (repo_path, ))

        try:
            content = self._parse_ci_file(ci_file['content'], ci_file['file'])
        except YAMLComposeError as e:
            raise Unexpected("Could not parse CI file: %s" %
                             (ci_file['file'], ))

        variables = content.get('variables', dict())

        namespace = variables.get('FAILFASTCI_NAMESPACE', None)
        gitlab_endpoint = variables.get('GITLAB_URL', None)
        self.gitlab = GitlabClient(gitlab_endpoint)

        ci_project = self.gitlab.initialize_project(
            gevent.repo.replace("/", "_"), namespace)

        # @Todo(ant31) check if clone_url is required
        # clone_url = clone_url_with_auth(gevent.clone_url, "bot:%s" % self.github.token)
        target_url = clone_url_with_auth(
            ci_project['http_url_to_repo'],
            "%s:%s" % (gitlab_user, self.gitlab.gitlab_token))
        gitbin.remote('add', 'target', target_url)

        variables.update({
            'EVENT':
            gevent.event_type,
            'PR_ID':
            str(gevent.pr_id),
            'SHA':
            gevent.head_sha,
            'SHA8':
            gevent.head_sha[0:8],
            'FAILFASTCI_STATUS_API':
            ('%s/api/v1/github_status' % (FAILFASTCI_API, )),
            'SOURCE_REF':
            gevent.refname,
            'REF_NAME':
            gevent.refname,
            'CI_REF':
            gevent.target_refname,
            'GITHUB_INSTALLATION_ID':
            str(gevent.installation_id),
            'GITHUB_REPO':
            gevent.repo
        })

        content['variables'] = variables

        self._append_update_stage(content)

        perform_sync = variables.get("FAILFAST_SYNC_REPO", "false")

        if ((perform_sync == "true") or (DEFAULT_MODE == "sync")):
            # Full synchronize the repo
            path = os.path.join(repo_path, ".gitlab-ci.yml")
            with open(path, 'w') as gitlabcifile:
                gitlabcifile.write(
                    yaml.safe_dump(content,
                                   default_style='"',
                                   width=float("inf")))
            gitbin.commit(
                "-a", "-m",
                "build %s \n\n @ %s" % (gevent.head_sha, gevent.commit_url))
            gitbin.push("target", 'HEAD:%s' % gevent.target_refname, "-f")
            ci_sha = str(gitbin.rev_parse('HEAD'))
            return {  # NOTE: the GitHub reference details for subsequent tasks.
                'sha': gevent.head_sha,
                'ci_sha': ci_sha,
                'ref': gevent.refname,
                'ci_ref': gevent.target_refname,
                'ci_project_id': ci_project['id'],
                'installation_id': gevent.installation_id,
                'github_repo': gevent.repo
            }
        else:
            self.sync_only_ci_file(gevent, content, ci_project, ci_file)

    # @TODO this is a partial implem
    def sync_only_ci_file(self, gevent, content, ci_project, ci_file):
        """ Push only the .failfast-ci.yaml and set token to clone """
        tokenkey = "GH_TOKEN_%s" % str.upper(uuid.uuid4().hex)
        clone_url = gevent.clone_url.replace("https://",
                                             "https://bot:$%s:" % tokenkey)
        ci_branch = gevent.refname
        content['variables'].update({'SOURCE_REPO': clone_url})
        self.gitlab.set_variables(ci_project['id'],
                                  {tokenkey: self.github.token})
        return self.gitlab.push_file(project_id=ci_project['id'],
                                     file_path=ci_file['file'],
                                     file_content=yaml.safe_dump(content),
                                     branch=ci_branch,
                                     message=gevent.commit_message)
Exemple #11
0
    def trigger_pipeline(self):
        gevent = self.ghevent
        gitlab_user = GITLAB_USER
        dirpath = tempfile.mkdtemp()
        repo_path = os.path.join(dirpath, "repo")
        gitbin = self._checkout_repo(gevent, repo_path)

        try:
            ci_file = self._get_ci_file(repo_path)
        except ResourceNotFound as e:
            raise Unexpected("Could not find a CI config file in: %s" %
                             (repo_path, ))

        try:
            content = self._parse_ci_file(ci_file['content'], ci_file['file'])
        except YAMLComposeError as e:
            raise Unexpected("Could not parse CI file: %s" %
                             (ci_file['file'], ))

        variables = content.get('variables', dict())

        namespace = variables.get('FAILFASTCI_NAMESPACE', None)
        gitlab_endpoint = variables.get('GITLAB_URL', None)
        self.gitlab = GitlabClient(gitlab_endpoint)

        ci_project = self.gitlab.initialize_project(
            gevent.repo.replace("/", "_"), namespace)

        # @Todo(ant31) check if clone_url is required
        # clone_url = clone_url_with_auth(gevent.clone_url, "bot:%s" % self.github.token)
        target_url = clone_url_with_auth(
            ci_project['http_url_to_repo'],
            "%s:%s" % (gitlab_user, self.gitlab.gitlab_token))
        gitbin.remote('add', 'target', target_url)

        variables.update({
            'EVENT':
            gevent.event_type,
            'PR_ID':
            str(gevent.pr_id),
            'SHA':
            gevent.head_sha,
            'SHA8':
            gevent.head_sha[0:8],
            'FAILFASTCI_STATUS_API':
            ('%s/api/v1/github_status' % (FAILFASTCI_API, )),
            'SOURCE_REF':
            gevent.refname,
            'REF_NAME':
            gevent.refname,
            'CI_REF':
            gevent.target_refname,
            'GITHUB_INSTALLATION_ID':
            str(gevent.installation_id),
            'GITHUB_REPO':
            gevent.repo
        })

        content['variables'] = variables

        self._append_update_stage(content)

        perform_sync = variables.get("FAILFAST_SYNC_REPO", "false")

        if ((perform_sync == "true") or (DEFAULT_MODE == "sync")):
            # Full synchronize the repo
            path = os.path.join(repo_path, ".gitlab-ci.yml")
            with open(path, 'w') as gitlabcifile:
                gitlabcifile.write(
                    yaml.safe_dump(content,
                                   default_style='"',
                                   width=float("inf")))
            gitbin.commit(
                "-a", "-m",
                "build %s \n\n @ %s" % (gevent.head_sha, gevent.commit_url))
            gitbin.push("target", 'HEAD:%s' % gevent.target_refname, "-f")
            ci_sha = str(gitbin.rev_parse('HEAD'))
            return {  # NOTE: the GitHub reference details for subsequent tasks.
                'sha': gevent.head_sha,
                'ci_sha': ci_sha,
                'ref': gevent.refname,
                'ci_ref': gevent.target_refname,
                'ci_project_id': ci_project['id'],
                'installation_id': gevent.installation_id,
                'github_repo': gevent.repo
            }
        else:
            self.sync_only_ci_file(gevent, content, ci_project, ci_file)