头图

Introduction: The gitlab server of NetEase Yunxin is built on the external network, and the Jenkins server is built on the internal network, so gitlab cannot directly send the webhook to Jenkins, and the pipeline is built using a third-party relay forwarding method, but this relay often "strikes" ". According to the landing practice of NetEase Yunxin, this article introduces in detail how to use Gitlab-ci to replace webhook to trigger Jenkins job.

Text|Zou Liyong NetEase Yunxin Senior C++ Development/DevOps Engineer

Background

How does Gitlab trigger a Jenkins job?

When we push code or submit a merge request, gitlab will send a webhook (simply understood as an http request or restful api) to Jenkins to request the execution of a job.

The gitlab service used by NetEase Yunxin is maintained by Hangyan, and the server is built on the external network. Our Jenkins server is built on the intranet, which means that gitlab cannot directly send the webhook to Jenkins, and our pipeline adopts a third-party relay forwarding method at the beginning of the construction to forward the gitlab webhook to Jenkins. While sending the webhook from gitlab to Jenkins serves its purpose, this free 3rd party relay may "strike" often.

-ci to replace webhook to trigger Jenkins job

gitlab-ci

In short, gitlab-ci is a feature that comes with gitlab, and is configured through the .gitlab-ci.yml file in the source root directory. Automatically run when code pushes or merge requests.

following is the official explanation:

GitLab Auto DevOps is a collection of pre-configured features and integrations that work together to support your software delivery process.

GitLab CI/CD can automatically build, test, deploy, and monitor your applications by using Auto DevOps.

To use GitLab CI/CD, you need:

  • Application code hosted in a Git repository.
  • A file called .gitlab-ci.yml in the root of your repository, which contains the CI/CD configuration.

There is actually a little less in the official you need - GitLab runner, where GitLab-ci jobs are run, that is, all jobs defined in .gitlab-ci.yml will be distributed here.

In our practice, we will build a python environment and python-jenkins module in GitLab runner, then trigger Jenkins job through python script, and finally deploy the python script that triggers Jenkins job to gitlab-ci.

So the whole practice is divided into 3 parts.

  1. Build the Gitlab runner
  2. Trigger Jenkins job via python-jenkins
  3. Use gitlab-ci to call python scripts on push code and merge request

build gitlab runner

install gitlab runner client

Official: GitLab Runner can be installed and used on GNU/Linux, macOS, FreeBSD, and Windows.

Therefore, you can choose any long-term online baler. The author recommends to choose GNU/Linux first. Usually, it is more convenient to build a resident service on linux than other systems, followed by MacOS, and finally Windows.

The following is a port of the installation method for the GNU/Linux platform:

For example, for Debian or Ubuntu:

# Replace ${arch} with any of the supported architectures, e.g. amd64, arm, arm64# A full list of architectures can be found here https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.htmlcurl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_${arch}.deb"

For example, for CentOS or Red Hat Enterprise Linux:

​​​​​​​

# Replace ${arch} with any of the supported architectures, e.g. amd64, arm, arm64# A full list of architectures can be found here https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.htmlcurl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/rpm/gitlab-runner_${arch}.rpm"
  • Install

    • Install the package for your system as follows.

    For example, for Debian or Ubuntu:

dpkg -i gitlab-runner_<arch>.deb

For example, for CentOS or Red Hat Enterprise Linux:

rpm -i gitlab-runner_<arch>.rpm

For installation schemes on other platforms, please click on the official tutorial portal:

https://docs.gitlab.com/runner/install/

Usually as a trigger agent, the task overhead is small, we can change the concurrent in the /etc/gitlab-runner/config.toml configuration to be larger to support higher concurrency.

register gitlab runner

  • Note

    • Build gitlab runner Each runner only needs to be executed once
    • Register gitlab runner Each git repository needs to be registered separately for each runner

<!---->

  • - Log in to gitlab first and enter the corresponding git repository (project)

    - Expand Settings -> CI/CD at the bottom of the left sidebar. Click Expand on the right side of the Runners column on the page, and scroll down the page to see something like the following, pay attention to the content in the red box.

  • Register

    Taking the official GNU/Linux as an example, other platforms are highly similar.

    1. Run the following command:

sudo gitlab-runner register

2. Enter your GitLab instance URL.

The content below the Register the runner with this URL in the red box above.

3. Enter the token you obtained to register the runner.

The content below And this registration token in the red box above.

4. Enter a description for the runner. You can change this value later in the GitLab user interface.

The description of the runner displayed in gitlab, in practice we use him as a name, called scapegoat-01.

5. Enter the tags associated with the runner, separated by commas. You can change this value later in the GitLab user interface.

tag is equivalent to label in Jenkins, used for runner classification. Enter scapegoat for this practice.

6. Provide the runner executor. For most use cases, enter docker.

Here we choose shell, window is optional powershell.

Other platform commands are the same, the official portal:

https://docs.gitlab.com/runner/register/index.html

After successful registration, you can see the runner we just registered in Available specific runners below the red box, similar to the figure below. in:

  • scapegoat-01 is the description of the runner
  • scapegoat corresponds to the tag of the runner, and the tag can be more than one

Trigger Jenkins job via python-jenkins

environment installation

  • install python in gitlab er

    It is usually included in the Linux distribution. The Debian series can use the following commands, and other platforms can be viewed on Google.

sudo apt install python或sudo apt install python3
  • install pip

    python3 usually comes with it, and python needs to be installed by itself.

sudo apt install python-pip
  • install python-jenkins
python -m pip install python-jenkinsor python3 -m pip install python-jenkins
  • get gitlab access token

    Log in to jenkins and click the user icon on the right side of the menu bar.

    Click Configure in the left sidebar that pops up.

    Click Add new token in the APT Token column, enter the token name, and click Generate.

The content in the red box below is the newly generated token, which is used in the following python script.

Writing python scripts

#!/usr/bin/python# file name: Jenkins-Compile-trigger.py
import jenkinsimport requestsimport timeimport sysimport os
jenkins_url = "http://yunxin-jenkins.netease.im:8080"# gitlab的登录账号jenkins_user = "zouliyong" #获取gitlab access token章节获取到的tokenjenkins_token = "xxxxxxxxxxxxxxxxx" #Jenkins job namejob_name = "Lava-CI"#从gitlab-ci中获取Jenkins job的参数,按需修改job_parameters = {                      "_GitlabSourceBranch"    : os.getenv("CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"),                    "_GitlabTargetBranch"    : os.getenv("CI_MERGE_REQUEST_TARGET_BRANCH_NAME"),                    "_GitlabMergeRequestLastCommit"  : os.getenv("CI_COMMIT_SHA"),                    "_GitlabSourceRepoHomepage"  : os.getenv("CI_PROJECT_URL"),                    "_GitlabMergeRequestIid"  : os.getenv("CI_MERGE_REQUEST_IID"),                    "_GitlabPipelineId"  : os.getenv("CI_PIPELINE_ID"),                    "_GitlabPipelineUrl" : os.getenv("CI_PIPELINE_URL"),                    "_GitlabJobId"  : os.getenv("CI_JOB_ID"),                    "_GitlabUserName"  : os.getenv("GITLAB_USER_NAME"),                    "_GitlabUserEmail"   : os.getenv("GITLAB_USER_EMAIL")}
build_number = 0build_info = {"building" : False}                 print("jenkins job name: ", job_name)print("jenkins job parameters: ", job_parameters)
#连接Jenkins服务server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token)
#获取Jenkins job最后一次build的build numberdef last_build_number(server, job):    last_build = server.get_job_info(job)['lastBuild']    return 1 if None == last_build else last_build['number']

last_build = server.get_job_info(job_name)['lastBuild']next_build_number = last_build_number(server, job_name) + 1
#触发Jenkinsjobqueue_id = server.build_job(job_name, parameters=job_parameters)print("Jenkins build is waiting for running [queue id = %d] ..." % queue_id)sys.stdout.flush()
#到这里,Jenkins job已经被放到执行队列里了,#只是触发不用等待Jenkins job结束的话,python脚本可以到此为止
#等待Jenkins job开始执行while True:    if next_build_number <= last_build_number(server, job_name):        try:            build_info = server.get_build_info(job_name, next_build_number)        except requests.exceptions.RequestException as e:            print(e)            server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token)            build_info = server.get_build_info(job_name, next_build_number)        if queue_id == build_info["queueId"]:            build_number = next_build_number            print("build number: %d" % build_number)            break        next_build_number = next_build_number + 1    time.sleep(0.1)
print("Jenkins build is running [build number = %d] ..." % build_number)print("Jenkins job URL: %s/job/%s/%d/display/redirect" % (jenkins_url, job_name, build_number))sys.stdout.flush()
#到这里Jenkins job已经被正式调度,并开始执行
#等待Jenkins job执行结束while build_info["building"]:    try:        build_info = server.get_build_info(job_name, build_number)    except requests.exceptions.RequestException as e:        print(e)        server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token)        build_info = server.get_build_info(job_name, build_number)    time.sleep(1)
# 获取执行结果result = server.get_build_info(job_name, build_number)["result"]print("jenkins build result: %s" % result)assert("SUCCESS" == result)

Run the above script to trigger the corresponding Jenkins job,

python Jenkins-Compile-trigger.py

Use gitlab-ci to call the python script write the .gitlab-ci.yml file when pushing code and merge request.

#file name: .gitlab-ci.yml
stages:    - build
# 在代码push的时候触发Compilation:    stage: build    tags:        - scapegoat # runner tag 参照上面注册gitlab runner章节    script:        - python Jenkins-Compile-trigger.py
# 只在merge request的时候触发CI:    stage: build    tags:        - scapegoat    script:        # 这个脚本可以根据情况参照Jenkins-Compile-trigger.py自行修改        - python Jenkins-CI-trigger.py     only:        - merge_requests

Put the above .gitlab-ci.yml and the python that triggers the Jenkins job in the root directory of the source code, and upload the repository together with the code. The function of triggering Jenkins job through gitlab-ci is realized.

author

Zou Liyong, senior C++ development/DevOps engineer at NetEase Yunxin. RTC SDK development on Linux platform, responsible for DevOps system development and operation and maintenance.


网易数智
619 声望140 粉丝

欢迎关注网易云信 GitHub: