背景
由于公司的项目A和项目B这2个项目使用的Angular版本不同,所以公共组件库也分为了2个分支,一个给项目A一个给项目B使用,公共组件库每次发布之前除了要同步部分相同的代码之外,还需要切换分支,才能进行发布。
以下是项目A和项目B版本、分支关系对照表
项目A | 项目B | |
|---|---|---|
| Angular版本 | 9.x | 11.x |
| gitlab发布分支 | 0.4.x | 0.5.x |
为了改变这一现状,决定将发布的工作交给jenkins去处理,即只要gitlab上有创建tag的操作,则触发Webhooks, 剩下的事情由Jenkins来实现代码获取、安装项目代码依赖、执行编译并发布。
准备工作
目前我的环境是一台宿主机服务器,上面有一个docker服务,其中jenkins服务是作为容器跑在docker上,所以,为了不影响现有的构建任务,我决定为jenkins单独添加一个执行发布任务的服务器作为节点,该节点可以是物理机、虚拟机或者docker容器,换句话说,只要是能够被jenkins可能访问到的机器都是可以的。在这里为了简单(其实是没有可以用的资源),我选择在同一台宿主机上使用docker容器作为节点,并且它将会和jenkins处于同一个虚拟网络,只要有正确的授权,Jenkins能够很容易访问到它。
准备一个docker镜像
首先,需要准备一个docker镜像,该镜像启动后将会作为Jenkins的一个执行构建任务的节点。其中必须预置一些软件或应用。
-
ubuntu
构建操作系统基于ubuntu,启动ubuntu后,需要在容器内准备发布环境。
-
nodejs v14
- nrm全局安装
npm i -g nrm- 添加发布账号和指定仓库镜像地址
npm adduser --registry http://10.6.32.13:4873/ #之后输入username passwrod- 添加发布仓库镜像地址
nrm add cy http://10.6.32.13:4873/- 指定镜像地址
nrm use cy -
openssh
jenkins需要远程登陆到代理节点上来完成任务。ssh是linux系统常用的登录方式。
-
java
jenkins在代理节点上执行任务是通过执行java程序来完成的,
需要注意的是默认情况下java要安装在指定的几个目录之一,jenkins会自动识别。也可以在Jenkins上配置节点的时候指定java的目录。
也可以直接写一个Dockerfile包含以上所有需要执行的命令。以下是一个Dockerfile示例
# '开始获取ubuntu'
FROM ubuntu
RUN apt-get update -y \
&& apt-get install curl -y \
&& cp /etc/apt/sources.list /etc/apt/sources.list.bak_`date "+%y_%m_%d"` \
&& sed -i 's/http://.*.ubuntu.com/https://mirrors.aliyun.com/g' /etc/apt/sources.list \
&& apt-get update -y \
&& apt-get install openssh-server -y \
&& apt-get upgrade -y \
&& curl -sL https://deb.nodesource.com/setup_14.x | bash -\
&& apt-get install nodejs -y \
&& apt-get install git -y \
&& npm config set registry https://registry.npm.taobao.org \
&& npm i -g yarn \
&& yarn config set registry https://registry.npm.taobao.org \
&& npm i -g @angular/cli \
&& mkdir -p /home/projects \
&& git clone http://10.6.3.15:82/mes/mes-lib.git /home/projects
CMD '/etc/init.d/ssh start'
EXPOSE 80 22
启动镜像
镜像启动后,会返回一个容器ID
docker run -itd [容器ID] /bin/bash
上面的命令执行成功后,会自动登陆到容器内,首先需要确保ssh服务是处于启动的状态,如果没有继续启动ssh服务,也将其设置为自动启动。
service ssh start
为了能够让jenkins能够登陆到本节点,需要将Jenkins服务器上的公钥追加到本节点服务器中的~/.ssh/auth/authorized_keys中
echo 'jenkins 服务器的公钥' >> ~/.ssh/authorized_keys
配置gitlab访问账号
本容器将来是作为发布公共组件库而创建的,因此拥有一个有访问权限的gitlab账号是必须的。通常获取gitlab仓库代码有http和ssh两种方式,http需要输入账号密码,而ssh登陆是比较方便的一种,与gitlab张傲绑定一次即可,与密码无关。
生成ssh密钥
做这一步之前,首先要确定~/.ssh/目录中是否存在 id_rsa id_rsa.pub, 其中id_rsa是私钥文件,id_ras.pub是私钥成对的公钥文件。如果不存在则执行:
ssh-keygen -m PEM -t rsa -b 4096 # 回车之后,一路回车就可以生成了
执行成功后会在~/.ssh/目录中产生id_rsa和id_rsa.pub文件
绑定gitlab账号
-
进入
~/.ssh目录,复制公钥文件id_rsa.pub中的文本。 -
使用有
访问权限的账号登陆gitlab页面,进入 用户设置Settings->SSH Keys在表单中填入id_rsa.pub中复制的文本,点击确定即可
以上准备完之后,就可以开始在Jenkins上操作了。
Jenkins
创建凭据
- 确保Jenkins服务器上存在ssh密钥
docker exec -it [jenkins 容器Id] bash # 在宿主机上执行该命令登陆jenkins服务器
执行命令进入ssh密钥文件存放目录,如果目录不存在则意味着jenkins没有创建过ssh密钥
cd ~/.ssh/
执行ls命令查看~/.ssh/目录中是否存在文件id_rsa id_rsa.pub, 其中id_rsa是私钥文件,id_ras.pub是私钥成对的公钥文件。
如果不存在则需要执行下列命令生成密钥文件, 执行成功后会在~/.ssh/目录中产生id_rsa和id_rsa.pub文件
ssh-keygen -m PEM -t rsa -b 4096 # 回车之后,一路回车就可以生成了
最后需要将私钥添加到jenkins全局凭据中。
- 使用管理员账号登陆jenkins web页面,进入
管理Jenkins->凭据->系统->全局凭据->添加凭据
进入添加凭据表单页面后,如图所示进行选择
点击最后的Add之后,将id_rsa文件中的内容贴到红框中,然后点击确定
添加jenkins节点
进入 管理Jenkins -> 节点管理 -> 新建节点 输入节点名称,选择固定节点,点击确定。
填写以下表单:
-
远程工作目录
构建任务的执行目录,即,发布公共模块其中一个步骤需要从gitlab上获取代码,那么代码就在这个目录中。
-
标签
由于添加的这个节点是一个专门用来执行发布任务的,所以需要填写
标签,在创建流水线任务的时候要指定这个标签。 -
用法
不希望jenkins中其他的构建任务使用该节点,则选择
只允许运行绑定到这台机器的Job -
启动方式
通过SSH登陆到代理服务器执行任务,选择
Launch agents via SSH需要注意的是,要安装插件 SSH Build Agents plugin才会有该选项
-
主机
节点服务器的IP地址,可以登陆到宿主机执行命令查询
docker inspect [节点容器Id]
-
执行之后在控制台输出的结果的最后有一个 IPAddress 的属性后面对应的就是该容器的IP地址,复制填入表单。
-
Credentials(凭据)
选择上一步中添加的凭据
-
Host Key Verification Strategy
选择
Non verifying Verification Strategy
点击确定后,Jenkins会自动根据表单中的配置去连接节点(代理)服务器,成功后会在左下角出现一个新的任务执行节点(代理)服务器。
创建流水线任务
- 使用管理员账号登陆Jenkins,创建任务
- 输入任务名称,选择流水线,点击确定
- 编辑任务属性 -
构建触发器
勾选 Build when a change is pushed to GitLab. Gitlab webhook URL http://xxxxxxxxxx, 复制后面的URL,这个URL将会配置到gitlab仓库的Webhooks中。
- 编辑任务属性 -
流水线
流水线脚本
pipeline {
agent {
label '代理节点标签' // 将该任务与前面新建的节点标签绑定,意味着本任务只会在该节点上运行
}
stages {
stage('Get Tag') {
steps {
script {
println env.gitlabSourceRepoHttpUrl // 打印环境变量
println env.gitlabAfter // 打印环境变量
println env.gitlabTargetBranch // 当前触发任务中包含的标签,其值为 refs/tags/[tag]
dirs = env.gitlabTargetBranch.split('/') // 将字符串分割,得到数组
tag = dirs[dirs.length - 1] // 取数组最后的一个元素,即为tag号
println 'tag is ' + tag
// 执行shell,拼接字符串脚本, clone当前最新的标签的代码
sh 'git clone [代码仓库的ssh访问地址] -b ' + tag + ' ./' + env.gitlabAfter
// shell脚本,执行npm install 和 发布命令
sh 'cd ./' + env.gitlabAfter + ' && npm install && npm run publish:lib'
}
}
}
}
}
值得一提的是,打印一下包含了当前构建任务信息的环境变量,你总能从打印结果中获得一些有用的东西,上方脚本中的变量就是从打印结果中拿到的
pipeline {
stages {
stage('env variable') {
sh 'printenv' // 打印所有的环境变量
}
}
}
gitlab
配置Webhooks
- 登陆可以访问仓库的账号,进入
仓库首页->Settings->Integrations, 填写表单
-
URL
该处填写,Jenkins流水线任务的访问
URL -
Trigger
Tag push events, 只有在打标签后才会触发Webhook, 将构建请求发送到Jenkins
这一步可能会出现404、403、401的错误
[403的解决办法] www.cnblogs.com/kaerxifa/p/…
到此,仓库创建tag触发webhooks通知jenkins触发构建任务,整个流程就串联起来了。