CI/CD 环境搭建:Docker+Jenkins+Gerrit

前言

软件开发的连续方法旨在通过自动执行脚本,以最大限度地减少在开发应用程序时引入错误的可能性。从新代码的开发到部署,它们只需要较少的人为干预甚至根本不需要干预;它涉及在每次小迭代中不断构建,测试和部署代码更改,从而减少基于有缺陷或失败的先前版本开发新代码的机会。目前比较流行的软件开发方法主要有三种:

  • 持续集成(Continuous Integration, CI): 代码合并,构建,部署,测试都在一起,不断地执行这个过程,并对结果反馈。
  • 持续部署(Continuous Deployment, CD): 部署到测试环境、预生产环境/灰度环境、生产环境。
  • 持续交付(Continuous Delivery, CD): 将最终产品发布到生产环境、给用户使用。

掌握这些方法能够帮助团队提高开发和运维的效率,提升软件质量,快速响应市场和用户需求,从而增强竞争力。

准备

基本流程

  • 在本地使用 Docker 运行 Gerrit 和 Jenkins 服务。
  • 配置 Docker 的卷和端口,使其可以通过 Web 访问。
  • 在 Gerrit 中创建一个新的项目 “unit_test”,用于管理源代码。
  • 在 Jenkins 中创建一个任务来构建 “unit_test”项目。
  • 确保 Gerrit 中的补丁可以被 Jenkins 构建。
  • 在 “unit_test” 项目中添加单元测试。
  • 在 Jenkins 中添加一个任务来构建和运行单元测试。
  • 实现一个闭环流程,包括自动补丁构建、代码审查和测试结果反馈。

安装 Docker & Docker Compose

安装Docker

sudo apt-get update
​
#移除老版本的docker
sudo apt-get remove docker docker-engine docker.io containerd runc
​
#安装HTTPS相关包
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
​
#添加Docker的官方GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
​
#验证指纹
sudo apt-key fingerprint 0EBFCD88
​
#设置稳定版repo
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"#安装Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
​
#验证安装成功
sudo docker run hello-world

设置非root账户管理Docker

sudo groupadd docker
sudo usermod -aG docker $USER  #$USER替换为ubuntu当前用户名
newgrp docker
 
#验证非root账户运行docker hello-world容器
docker run hello-world

安装Docker Compose

#下载稳定版的Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#(因为下载慢等原因)安装失败时,可以参考 https://blog.csdn.net/alen_xiaoxin/article/details/104849962 解决#设置权限
sudo chmod +x /usr/local/bin/docker-compose
​
#验证安装成功
docker-compose --version

Docker 镜像下载

#获取 jenkins & gerrit 镜像
docker pull jenkins/jenkins
docker pull openfrontier/gerrit
​
#检查镜像
docker images

Docker 启动 Gerrit 镜像容器并进行配置

使用 docker compose 配置方式启动 Gerrit

  • 任意位置创建文件夹(如cicd),并在该目录下新建 docker-compose.yaml 文件
docker-compose.yaml
version: '3'services:
  gerrit:
    #image: gerritcodereview/gerrit
    image: openfrontier/gerrit
    ports:
      - "29418:29418"
      - "8091:8091"
    depends_on:
      - ldap
    volumes:
      - /usr/local/docker/gerrit/review_site:/var/gerrit/review_site
      - /usr/local/docker/gerrit/etc:/var/gerrit/etc
      - /usr/local/docker/gerrit/git:/var/gerrit/git
      - /usr/local/docker/gerrit/db:/var/gerrit/db
      - /usr/local/docker/gerrit/index:/var/gerrit/index
      - /usr/local/docker/gerrit/cache:/var/gerrit/cache
    environment:
      - CANONICAL_WEB_URL=http://localhost:8091
    # entrypoint: /entrypoint.sh initldap:
    image: osixia/openldap
    ports:
      - "389:389"
      - "636:636"
    environment:
      - LDAP_ADMIN_PASSWORD=secret
    volumes:
      - /usr/local/docker/gerrit/ldap/var:/var/lib/ldap
      - /usr/local/docker/gerrit/ldap/etc:/etc/ldap/slapd.d
​
  ldap-admin:
    image: osixia/phpldapadmin
    ports:
      - "6443:443"
    environment:
      - PHPLDAPADMIN_LDAP_HOSTS=ldap
  • 终端进入 docker-compose.yaml 所在目录,执行 docker-compose up 启动 Gerrit 容器
  • 浏览器打开http://localhost:8091,进入 Gerrit 站点

如果浏览器登录失败,可以尝试修改 gerrit.config 文件,将port 8080 修改为 8091
文件 gerrit.config 可通过 sudo find / -name “gerrit.config” 寻找

通过 docker run 启动 Gerrit

docker run \
--name mygerrit \
-v $PWD/gerrit_volume:/var/gerrit/review_site \
-p 9527:9527 -p 29418:29418 openfrontier/gerrit
 
# 其中9527为web访问端口,29418为ssh端口,执行该命令后review_site 总的内容将和gerrit_volume中内容同步;
# gerrit_volume中会产生一个gerrit.config (位置 gerrit_volume/etc/gerrit.config)的配置文件内容,该内容可以根据需要修改:
[gerrit]
  basePath = git
  serverId = 0871a228-bd59-4f69-a8b9-504f65b6ddb6
  canonicalWebUrl = http://yourIP:9527/
[httpd]
  listenUrl = http://*:9527/
 
# 默认生成的canoicalWebUrl是个Containor ID,必须要修改为自己的宿主机IP,否则 注册邮箱的时候,发送的验证位置前部分就是一个乱码WebUrl;
# 注:其他目录也会生成gerrit.config文件,除非清楚调用关系,建议都统一修改。
# 查找命令:sudo find / -name gerrit.config
# 如我的目录为:/var/lib/docker/volumes/1ffcae852b0225161ccb60c37252f9635da1c1d2fe0d7c0f0bc7c2cc10a5e4cb/_data/etc/gerrit.config
  • 网页成功进入后点击登录,使用【Sign in with a Launchpad ID】登录 Gerrit(需要注册两个账号,admin 权限的账号以及 Jenkins 中要用到的账号
    • gerrit 默认第一个站点账号为管理员账号 1000000

      注册完帐号之后点击Sign in with a Launchpad ID,进行登录,会跳转到ubuntu one第三方认证,输入注册的邮箱和密码,点击登录时会有以下提示:
      You are logging in to http://bd886cda56b3:8080/
      The site has requested some personal information, please choose what you would like to share:
      》Full name: your_name
      》Email address: your_email@xxxx.com
      .注意到这里的服务器地址是个奇怪的地址,可以通过修改gerrit的配置文件gerrit.config进行修正。将canonicalWrbUrl改成 .>canonicalWebUrl = http://localhost:8091/。
      如果不修改gerrit.config配置文件,也可以修改系统的/etc/hosts文件,添加该地址到localhost的映射。

    • 配置ssh密钥

      • ssh-keygen -t rsa -C "yourEmail",连续三次回车键,会在~/.ssh下生成公钥 id_rsa.pub 和私钥 id_rsa,其中公钥需要添加到 gerrit 的SSH Keys 中。添加完成后就可以正确执行 git clone 命令,只要不删除更改 .ssh 文件夹中的内容就可以一次设置长期使用了。
      • 终端下 ssh -p 29418 admin@localhost 验证ssh连接,其中 admin 为 gerrit 管理员账号的 Username
    • 注册用于 jenkins 的账号,然后网页登录 gerrit 管理员账号

      • 进入 Browser->Repo->Groups->Non-Interactive Users->Members,将2个账户添加到 Non-Interactive 账户组中(注意:gerrit 3.3 版本以后 Non-Interactive Users 被命名为 Service Users

      如果误操作,比如将 gerrit 的管理员权限删除了,可以通过删除 /usr/local/docker/gerrit/review_site 清除 gerrit 已有的数据, /usr/local/docker/gerrit/review_site 是 docker-compose.yaml 文件之指定的 gerrit 容器数据保存位置

在本机的 Gerrit 上创建软件仓库,并能成功上传和拉取代码

本地检出 All-Project (1)

git clone ssh://user@hostip:29418/All-Projects.git

如果提示错误为 agent fail,执行以下命令:

eval "$(ssh-agent -s)" 
ssh-add

检查检出的目录,修改 project.config,新增以下脚本:

[label "Verified"]
    function = MaxWithBlock
    value = -1 Fails
    value = 0 No score
    value = +1 Verified
    copyAllScoresIfNoCodeChange = true

提交更新,注意本地 git 邮件地址必须和 Gerrit 上的一致,一定不要 push 到错误的分支,要按照如下分支 push

git commit -am "add label verified"
git push origin HEAD:refs/meta/config

网页登录 gerrit 管理员,增加 All-Project 的 Label Verified 权限。
Browser->Repo->All-Projects->Access->Edit,为 refs/for/ 和 refs/heads/ 增加 Label Verified,并添加 Non-Interactive Users 用户组

  • 新建仓库并提交修改,看看是否出现了review
    Browser->Repo->Create New
  • 填入仓库名称 unit_test

clone 仓库并进行修改

  • 使用如下命令 clone 仓库到本地,因为如果没有后面的 scp 拷贝 commit-msg,那么生产的 commit 是不带 Changed-Id 的,会造成 push 的时候报错(missing Change-Id in commit message footer)
git clone ssh://user@hostip:29418/project && scp -p -P 29418 user@hostip:hooks/commit-msg project/.git/hooks

修改 .git/config 文件,在 [remote “origin”] 下增加

push = refs/heads/*:refs/for/*

避免每次提交都需要执行 git push 远程地址 本地分支:refs/for/远程分支

替代方法:git config remote.origin.push refs/heads/:refs/for/ ,效果相同。
需要该修改的原因是gerrit默认不允许直接提交到master分支。

在仓库中增加 readme.md

提交修改

git add .
git commit -m "add readme.md"
git push origin master

最终结果:查看网页 Gerrit 主页,出现一个需要 Review 的 Change。

Docker 启动 Jenkins 并配置

启动命令

docker run -d --name jenkins -vjenkins_home:/var/jenkins_home-p 8092:8080 -p 50000:50000 jenkins/jenkins

查找 jenkins 容器位置

sudo find / -name "jenkins_home"

在浏览器中打开 http://localhost:8092

  • 解锁Jenkins,插件安装选择 jenkins 的推荐安装
    • 执行命令 docker exec -it jenkins /bin/bash进入容器内部
    • 执行命令 cat /var/jenkins_home/secrets/initialAdminPassword查看 Jenkins 的 admin 密码
  • 进入Jenkins后,安装插件,主页 → Manage Jenkins → Manage Plugins → available plugins
  • 安装 Gerrit-Trigger 插件
    • 安装插件失败时的解决方案,参考
      • https://www.cnblogs.com/ninefish/p/9818080.html
      • http://localhost:9527/pluginManager/advanced
      • http://mirror.esuni.jp/jenkins/updates/update-center.json
  • 在 Gerrit Trigger 中配置一个用于构建的服务器
    相关参数填写
    • HostName 中的ip:通过 ifconfig 查看 docker0 的ip
    • SSH keyfile:进入 Jenkins 容器在~目录通过 ssh-keygen -t rsa -C xxxx@xx.com 命令生成,并将公钥(id_rsa.pud文件的内容)输入到前面注册的用于 jenkins 的 gerrit 账号
    • 如果 jinkins 配置 gerrit_trigger 服务是提示: “/var/jenkins_home/.ssh/id_rsa” is not a valid key file.,可用 ssh-keygen -m PEM 重新生成密钥,修改文件后需要重启容器,不然 jenkin 流水线配置这里URL可能找不到

    • 正确配置后可通过jenkins容器下 ssh -p 29418 cqh@172.17.0.1 验证 ssh 连接,其中 cqh 为用于 jenkins 的 gerrit 账号 Username
    • 若出现 auth 错误,表明 user 信息和 gerrit 用于 jenkins 账户的不一致,应确保名字和邮箱均相同,且 ssh 已添加到 gerrit 中.请添加图片描述
    • 点击 Test Connection 测试是否正常连接

Jenkins 搭建自动构建流水线

  • 下载 gtest 框架, jenkins 容器目录下:git clone https://github.com/google/googletest
  • 进入 gtest 框架目录,编译,这里需要root权限,以 root 权限进入 jenkins 容器:docker exec -it --user root 容器 id /bin/bash
# 以root权限进入 jenkins 容器,执行
root@13161464c3fe:apt-get update
root@13161464c3fe:apt-get install g++
root@13161464c3fe:apt-get install cmake
  • 进入gtest目录,执行
cmake CMakeList.txt
make
make install
  • 添加 jenkins 构建任务,选择“流水线”,jenkins 网页站点 New iteam → pipeline请添加图片描述
    -请添加图片描述
    请添加图片描述
    请添加图片描述
  • 如果仓库存在但 repo url 提示 Failed to connect to repository : Command “git ls-remote -h – ssh://cqh@172.17.0.1:29418/unit_tests HEAD” returned status code 128: ,考虑重新生成ssh密钥并重启容器
  • 添加 repo url 出现 Jenkins: stderr: Permission denied 权限问题参考 https://blog.csdn.net/lusyoe/article/details/52782368

测试自动触发构建

  • 进入 gerrit 仓库目录,如我的 chenqinhu@chenqinhu:~/cicd/uint_test$
  • 新建三个文件并提交 hello_gtest.c、 Jenkinsfile 、Makefile

hello_gtest.c

hello_gtest.c
#include <stdio.h>
  
int main(int argc,char** argv)
{
    printf("hello world!\r\n\r\n");
}

Makefile

test:hello_gtest.o
    gcc -o test hello_gtest.o
  
hello_gtest.o:
    gcc -c hello_gtest.c
  
clean:
    rm -f *.o test

Jenkins file

pipeline {
   agent any

   stages {
       stage('Build') {
           steps {
               echo 'clean and bulid..'
               sh 'make clean && make'
           }
       }
       stage('Test') {
           steps {
               echo 'Testing...'
               sh './test --gtest_output=xml:gtestreport.xml'
           }
       }
       stage('Deploy') {
           steps {
               echo 'Deploy..'
           }
       }
   }
}
  • 最终执行效果:修改 gerrit 项目,提交触发 jenkins 构建,jenkins 构建结果反馈于 gerrit 的 verify 结果。

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述


  1. 在 Gerrit 中,All-Projects 是一个特殊的项目,用于管理整个 Gerrit 实例的配置。你可以在 All-Projects 项目中设置全局访问权限、项目配置和其他重要设置。 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值