Jenkins + Git自动化部署流程搭建姿势大全~纯干货开箱即用
目录
1、环境说明
2、安装Jenkins
2.1、方式一:war包手动安装
2.1.1、下载安装包
2.1.2、配置安装jdk
2.1.3、安装配置jenkins
2.1.4、调试jenkins
2.2、方式二:docker镜像安装
2.2.1、拉取镜像
2.2.2、创建挂载目录
2.2.3、启动镜像
3、配置Jenkins
4、配置项目
5、配置构建通知(可选)
1、环境说明
本文默认使用Centos7进行操作配置
2、安装Jenkins
2.1、方式一:war包手动安装
2.1.1、下载安装包
(1)根据需要下载对应版本的jenkins_war包 ,本文使用版本:2.479.2Jenkins提供的历史版本下载地址https://get.jenkins.io/war-stable/
(2)根据Jenkins java支持策略下载对应的JDK版本 (本文中使用的版本需要下载jdk17)
Java 支持策略 --- Java Support Policyhttps://www.jenkins.io/doc/book/platform-information/support-policy-java/#running-jenkins-system
2.1.2、配置安装jdk
# 将jdk包放到安装路径下。 默认路径:/usr/local
# 解压jdk-tar包 (注意替换解压的包名)
tar -zxvf jdk-17.0.8.tar
# 删除tar包 (注意替换删除的包名)
rm -rf jdk-17.0.8.tar
# 配置JAVA_HOME (配置环境变量)
vim /etc/profile
# 在打开的profile文件中插入 (注意替换jdk版本为自己的版本)
## Java
export JAVA_HOME=/usr/local/jdk-17.0.8
export PATH=$JAVA_HOME/bin:$PATH
# 保存profile文件后 刷新配置
source /etc/profile
2.1.3、安装配置jenkins
# 将下载的war包移动到安装目录下, 默认: /usr/local/jenkins/
# 配置systemctl unit服务 来管理 jenkins
# 创建jenkins.service配置文件
vim /usr/lib/systemd/system/jenkins.service
# 在打开的vim窗口中插入:
[Unit]
Description=jenkins
After=network.target
[Service]
User=root
Type=simple
Restart=always
SyslogIdentifier=jenkins
PrivateTmp=false
Environment="JENKINS_HOME=/data/jenkins"
# 启动命令 可根据需要修改端口 分配内存 指定日志路径等
ExecStart=/usr/local/jdk-17.0.8/bin/java -Xmx1024M -Xms256M -jar /usr/local/jenkins/jenkins.war --httpPort=8080
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
2.1.4、调试jenkins
(1)jenkins服务管理命令
# 启动jenkins服务
systemctl start jenkins
# 停止jenkins服务
systemctl stop jenkins
# 重启jenkins服务
systemctl restart jenkins
# 查看jenkins服务状态
systemctl status jenkins
# 查看jenkins配置文件
systemctl cat jenkins
(2)启动jenkins后输出如下内容则表示启动成功,在局域网环境下输入服务器IP:8080即可查看jenkins-webUI
(3)如报错未能启动,根据报错提示排查,一般错误如下:
- 检查服务器的 8080 端口是否被占用,在命令行输入 lsof -i:8080
- 检查 jdk 是否可以正常调用,在命令行输入 java --version
- 检查 jenkins.service 内容是否正确
2.2、方式二:docker镜像安装
2.2.1、拉取镜像
本文默认服务器已安装docker环境,若无docker环境,则需要先安装docker。
# 拉取中文jenkins镜像
docker pull jenkinszh/jenkins-zh
2.2.2、创建挂载目录
在服务器上创建一个jenkins工作目录, /data/jenkins,赋予读写权限,将jenkins容器目录挂载到此目录上。
#创建 jenkins 工作目录
mkdir -p /data/jenkins
# 赋予目录权限
chmod 777 /data/jenkins
2.2.3、启动镜像
# 启动容器
docker run -d -p 8080:8080 -p 443:443
-v /data/jenkins:/var/jenkins_home
-v /root/apache-maven-3.6.3:/usr/local/maven
-v /etc/localtime:/etc/localtime --name myjenkins jenkinszh/jenkins-zh
根据需求来增加启动参数,一般还需要挂载Node、Jdk, Git等,使用-v参数挂载即可。
参数详情 :
-d | 后台运行容器 |
-p | 映射 8080 与 443 端口到宿主机 |
-v | /data/jenkins:/var/jenkins_home 挂载jenkins工作目录到宿主机 |
-v | /root/apache-maven-3.6.3:/usr/local/maven 挂载本地maven,前面是服务器路径,后面是容器路径 |
-v | /etc/localtime:/etc/localtime --name MyJenkins 容器别名 |
3、配置Jenkins
在浏览器中输入 IP:8080 访问Jenkins-webUI
注意:浏览器显示的是jenkins_home 路径,在服务器上根据自己实际配置的路径找到密码输入即可。
本文中方式一与方式二路径均为:/data/jenkins
根据指示安装推荐的插件
安装插件
进入插件页面,安装需要的插件,安装完成后需要重启jenkins,在浏览器输入:IP:8080/reload
publish over ssh 使用ssh协议发送文件插件 (必须)
Maven Integration Maven编辑环境 (可选- java项目则必须)
GitLab Plugin 使用GitLab做代码仓库下载此插件 (可选)
Gitee 使用码云做代码仓库下载此插件 (可选)
Environment Injector Plugin 在构建过程中注入环境变量 (可选)
Post build task 在构建完成后执行脚本 (可选)
Role-based Authorization Strategy 超细致的权限控制插件 (可选)
配置全局工具
进入全局工具配置页面,配置相关的依赖工具如:JDK、Node、Maven、Git
配置系统内容
进入此页面,配置需要使用的服务器(如部署发布的服务器地址)
配置凭据
进入此页面配置凭据账号(如GitLab、Gitee使用的登陆账号)
4、配置项目
点击左侧的新建任务,选择新建自由风格项目
选择Git仓库地址
GitLab项目直接选择Git即可,Gitee项目选择Gitee(需要下载Gitee插件)
配置好仓库地址,选择登陆凭据,配置拉取的分支即可
配置webhook
按图勾选,复制webhook地址,后续配置需要填写此地址。
点击高级,点击Generate 生成密钥,复制密钥,后续配置需要填写此密钥。
构建步骤
这一步需要配置的内容根据项目来定,一般java项目需要配置maven编译环境,Node项目需要配置Node编译环境。
也可以在此步骤中加入环境变量,可以在后续的构建管道中使用,包括构建脚本。
执行shell脚本:若项目中有启动脚本,则可以在此步骤中执行。或用来执行项目编译的脚本也可以放在此步骤中。
目前我所有在构建的项目编译打包操作都是在这一步使用脚本来完成。你可以将通用的编译或打包流程编写为脚本,在此配置运行即可。附录一个我在使用的前端打包脚本,包含PC和uiapp项目。通过项目中配置环境变量来控制打包。
#!/bin/bash
workspace=${WORKSPACE} # jenkins工作目录
dist_name=${dist} # 指定的输出包名称
project=${project_type} # 项目类型 1=pc , 0=h5
is_vue_admin=${vue_admin} # 是否为 vue_admin 框架项目 1=true 0=flase
is_pnpm=${n_or_p} # 决定项目install 使用哪个管理器 1=pnpm 0=npm
# 异常处理
function ErrorExit {
echo "$1" 1>&2
exit 1
}
# vue项目 build操作
function BuildonVue {
cd ${workspace} || ErrorExit "${LINENO}: failed"
case ${is_vue_admin} in
1)
pnpm install
npm run build:prod
;;
0)
if [[ ${is_pnpm} -eq 1 ]]; then
pnpm install
else
source ~/.nvm/nvm.sh
nvm use v14.0.0
npm install
fi
npm run build
;;
esac
tar -zcf ${dist_name} ./dist
}
# uiapp build操作
function BuildonUiapp {
cd ${workspace} || ErrorExit "${LINENO}: failed"
pnpm install # 下载依赖
uapp sdk init # 初始化 uapp sdk
uapp config hbx.dir /usr/local/hbuilderx-linux # 配置 hbx.dir
uapp config node `which node` # 配置 node
uapp run build:h5 # build
tar -zcf ${dist_name} ./unpackage/dist/build/h5
}
case ${project} in
1)
BuildonVue
;;
0)
BuildonUiapp
;;
esac
发送打包后的文件
使用ssh插件发送打包后的文件到发布服务器
选择要发送的服务器ip,输入要发送的文件名(可以使用shell语法来匹配)
Source files:要发送的文件
Remote directory:发送到服务器上的目录
Exec command: 发送后需要执行的命令
到这一步项目配置就结束了,点击save保存。然后到GIT仓库配置webhook地址即可,以GitLib为例:输入上一步骤中复制的webhook地址和密钥,配置需要触发构建的分支保存即可,配置完成后可以点击测试。若配置无误则jenkins会触发构建。
5、配置构建通知(可选)
在配置好项目后,我们需要知道构建的结果来确定是否构建成功,Jenkins自带的邮件发送功能不太适合我们国内办公者,可以集成企业微信群聊机器人或者钉钉群聊机器人来作为推送结果的工具。
这里提供两种思路,第一种是直接去插件市场下载企业微信推送插件 Qy-Wechat Notification
然后填入企业微信群聊机器人webhook地址即可。
然后在项目中添加构建后操作步骤,选择企业微信通知,将企业微信群聊机器人的webhook地址填入,userID需要到企业微信管理后台查看,没有权限的同学可以用手机号来做提醒。
第二种方式是使用脚本发送web请求来推送通知,这样的好处是可以自由构建推送内容。缺点是需要自己维护企业微信的用户字典(目前还没想到更好的方式)
编写好脚本后,将脚本上传至服务器目录,并在项目中配置构建后使用脚本。运行该脚本即可。
我使用的是python脚本,所以需要在服务器上提前安装python环境,也可以直接使用shell或者其他脚本,只要安装好运行环境即可。
附录我自己项目中在使用的推送脚本,目前用户字典也维护在脚本内部,有兴趣的同学可以把字典分离出来,维护在数据库中或者单独文件中。
"""
用于jenkins构建完成后推送企业微信
"""
import os
import requests
from requests.auth import HTTPBasicAuth
from datetime import datetime
import git
import json
# 企业微信hook地址
webhooks = "填写你的企业微信hook地址"
# 获取服务器环境变量 通过jenkins管道注入的环境变量
JOB_NAME = os.environ.get('JOB_NAME') # 项目名称
JENKINS_URL = os.environ.get('JENKINS_URL') # jenkins地址
BUILD_NUMBER = os.environ.get('BUILD_NUMBER') # 构建编号
GIT_BRANCH = os.environ.get('GIT_BRANCH') # 远程分支名称
BUILD_URL = os.environ.get('BUILD_URL') # 构建控制台地址
branch_name = os.environ.get('branch_name') # jenkins分支名称
# 工作目录及时间配置
work_dir = "/usr/local/jenkins/workspace/" + JOB_NAME # 工作目录
TAG_DATE = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 当前时间
# jenkins相关配置
jenkins_user = "root"
api_token = "" # 在jenkins-WebUI 用户安全页可以获取api_token
class Contacts:
"""
Gitlab与企业微信通讯录对照字典
"""
contacts = {
"Administrator": "TaoShi",
}
def get_git_message():
"""
获取git信息
:return:
"""
repo = git.Repo(work_dir) # 打开目录下的git地址
last_commit = repo.head.commit # 获取最后一次commit信息
remote_url = repo.remotes.origin.url # 获取远程git仓库地址
# 获取commit信息
commit_dict = json.loads(repo.git.log(
'--pretty=format:{"commit":"%h", "date":"%cd", "summary":"%s"}',
max_count=1
)
)
job_url = f"{JENKINS_URL}job/{JOB_NAME}/{BUILD_NUMBER}/api/json"
response = requests.get(
job_url,
auth=HTTPBasicAuth(jenkins_user, api_token),
timeout=10
)
result = response.json().get('actions')[0].get("causes")[0].get("shortDescription")
committer_name = result.split("Started by GitLab push by ")[1].strip()
return {
"last_commit": last_commit,
"committer_name": committer_name,
"remote_url": remote_url,
"commit_dict": commit_dict
}
def get_job_result():
"""
获取jenkins job 工作结果
:return:
"""
job_url = f"{JENKINS_URL}job/{JOB_NAME}/{BUILD_NUMBER}/api/json"
response = requests.get(
job_url,
auth=HTTPBasicAuth(jenkins_user, api_token),
timeout=10
)
result = response.json().get('result', 'UNKNOWN')
if result == "SUCCESS":
result_str = "构建成功"
elif result == "FAILURE" or result == "UNSTABLE":
result_str = "构建失败"
else:
result_str = "获取结果失败-请查看控制台"
return result_str
def mentioned(username):
"""获取通知列表"""
mentioned_list = []
userid = Contacts().contacts.get(username, "")
mentioned_list.append(userid)
return mentioned_list
def push_bots():
"""
推送到企业微信机器人
:return:
"""
msg = get_git_message()
message = {
"markdown": {
"content":
f" **【{JOB_NAME}】** —— **{get_job_result()}**
"
f" > **jenkins分支名称:** {branch_name}
"
f" > **远程地址:** {msg['remote_url']}
"
f" > **构建分支:** {GIT_BRANCH}
"
f" > **commit:** {msg['commit_dict']['summary']}
"
f" > **提交者:** {msg['committer_name']}
"
f"
"
f" > [查看控制台]({BUILD_URL})
"
f"
"
f" > {TAG_DATE}
"
},
"msgtype": "markdown",
}
message1 = {
"msgtype": "text",
"text": {
"content": f"{JOB_NAME} 已构建完毕",
"mentioned_list": mentioned(msg.get('committer_name'))
}
}
requests.post(webhooks, headers={"Content-Type": "application/json"}, json=message)
# markdown 不支持提醒用户,所以分为两条消息
requests.post(webhooks, headers={"Content-Type": "application/json"}, json=message1)
if __name__ == '__main__':
push_bots()