# Gitee push自动触发Jenkins测试
可以实现每次提交代码(git pull, Pull Request)后自动构建、测试(需要仓库管理者配置Gitee Webhook)。
## 1 配置方法
简单来说:
1. 为一台服务器配置HTTP公网地址,实现内网穿透(如用花生壳做网页映射)
2. 在目标服务器上,安装并配置Jenkins,并配置对应的Gitee以及Generic Webhook Trigger插件。
3. 创建对应的Jenkins Item, 写自动化shell脚本。
4. 在Gitee为目标仓库配置Webhook,指向目标服务器的Jenkins。
5. 每次执行`git push`命令,就会触发Jenkins自动构建&测试,生成日志。也可手动或定时触发。
### 1.1 配置公网地址
通过FRP等方式实现。
Dashboard - Manage Jenkins - System - Jenkins Location,将Jenkins URL改为公网地址。
### 1.2 配置Jenkins
**安装插件** :Dashboard - Manage Jenkins - System Configuration - Plugins - Available plugins,搜索Gitee和Generic Webhook Trigger并安装。
**在Gitee中创建新令牌:** Dashboard - Manage Jenkins - Credentials,添加Gitee APIV5 私人令牌。
**创建Jenkins Item:**
- General
- Gitee 链接 : Gitee
- 源码管理 : Git
- Repository URL : `https://gitee.com/<仓库地址>.git`
- 构建触发器
- 选中Gitee webhook 触发构建
- Gitee WebHook 密码 : 点“生成”按钮生成一串密码
- 选中Generic Webhook Trigger
- Token: 输入token
- Build Steps: 编写测试脚本,见下一节。
### 1.3 编写测试脚本
> 注:笔者要运行2个进程(./server和./client),其中./server需要持续运行直到./client运行结束,但实测由于未知原因,server启动后立即退出,创建的server进程号无法追踪到。下面的脚本使用了supervisor(事先已在机器上配置,见1.4节),保证server启动后持续运行。脚本示例:
```sh
#!/bin/bash
# Show current time, user & path
whoami
pwd
# Checkout and update repository
git checkout master
git pull
git submodule update --init
# Clean and build
make clean
make
# Set log file path
rm -f *.log
now=$(date +"%Y-%m-%d-%H:%M:%S")
echo $now
LOG_FILE="$now.log"
# Define client exec path
CLIENT_EXEC="./voter_client"
# 1. Run server
echo "Starting server..." | tee -a $LOG_FILE
sudo supervisorctl start como_fscp_voter
sleep 1
# 2. Run client
echo "Starting client..." | tee -a $LOG_FILE
$CLIENT_EXEC -t 127.0.0.1 7711 -d
sleep 1
# 3. Terminate server
echo "Terminating server..." | tee -a $LOG_FILE
sudo supervisorctl stop como_fscp_voter
# Read & print logs
echo "--------------------------------"
echo "$LOG_FILE content:"
cat "$LOG_FILE"
# Read & print syslog (if necessary)
# echo "Syslog content:"
# cat /var/log/syslog
```
### 1.4 supervisor配置
参考链接:[Ubuntu 安装和使用 Supervisor(进程管理)](https://www.cnblogs.com/xishuai/p/ubuntu-install-supervisor.html)
```sh
# 安装supervisor
sudo apt install supervisor
# 创建待运行应用的配置文件
sudo vim /etc/supervisor/conf.d/como_fscp_voter.conf
```
以笔者需构建的项目como-fscp-voter为例,写入下列配置,注意自定义directory, command(需为绝对路径)和stdout_logfile(该文件必须事先存在):
```sh
[program:voter]
directory=//var/lib/jenkins/workspace/gitee_task
command=/var/lib/jenkins/workspace/gitee_task/como_fscp_voter
autostart=true
autorestart=true
startretries=10
redirect_stderr=true
stdout_logfile=/var/lib/jenkins/workspace/gitee_task/voter.log
environment=ASPNETCORE_ENVIRONMENT="Development"
```
解释:当按照1.3节创建Jenkins任务(gitee_task)后,该路径(`/var/lib/jenkins/workspace/gitee_task/`)即所填Gitee仓库(como-fscp-voter)的根目录。
手动测试时,需要先创建.log文件:
```sh
sudo touch /var/lib/jenkins/workspace/gitee_task/voter.log
```
自动执行时,1.3节脚本(`LOG_FILE="voter.log"`)已经在每次运行前保证了log文件存在。
运行supervisor,并可运行supervisorctl进行控制:
```sh
sudo supervisord
sudo supervisorctl # 进入supervisorctl环境
reread # 重新加载配置
update # 更新配置
start all # 开始所有配置
status # 查看状态
# 成功运行:
como_fscp_voter RUNNING pid 2126469, uptime 0:01:04
```
在shell中可直接执行`sudo supervisorctl start como_fscp_voter`启动(而无需进入supervisorctl环境)。
### 1.5 在Gitee为目标仓库配置Webhook
打开Gitee目标仓库页面 - 管理 - (下滑找到)Webhooks - 添加WebHook:
URL: `https://<公网IP[:端口]>/generic-webhook-trigger/invoke?token=<Generic Webhook trigger生成的token>>`
Webbook密码:`在Jenkins创建任务时生成的Webhook密码`
选择事件:`Push(默认)`, `Pull Request(可选)`
按更新按钮,若请求历史一栏显示Response值为200,说明配置成功。
## 2 测试
### 2.1 测试方法
正确配置后,可通过如下方式触发构建:
1. Gitee触发。如git push(最常用)或Pull Request;
2. Jenkins手动或定时触发。
Gitee有测试Webhook是否配置成功的模块,向Jenkins所在服务器发送HTTP请求,但据传有bug([参考链接](https://blog.csdn.net/weixin_58887621/article/details/135242286))。我们可以编写一个发送HTTP请求的Python程序,按照链接改正Headers,以模拟Gitee的git push或Pull Request事件。示例如下:
```python
import requests
# 定义URL
url = 'https://<Jenkins服务器的公网IP>/gitee-project/gitee_task'
# 设置headers
headers = {
'X-Gitee-Token': '<Your Token>',
'X-Gitee-Event': 'Push Hook',
'User-Agent': 'git-oschina-hook',
'X-Gitee-Timestamp': 'time',
'X-Gitee-Ping': 'true',
'Content-Type': 'application/json',
'X-Git-Oschina-Event': 'Push Hook'
}
# 设置payload (具体在Gitee Webhook上查看)
payload = {...}
# 发送POST请求
response = requests.post(url, headers=headers, json=payload)
# 打印响应内容
print(f"Status Code: {response.status_code}")
print(f"Response Content: {response.text}")
```
若返回状态码200,表示配置成功:
```sh
Status Code: 200
Response Content: push_hooks ref = refs/heads/test_version commit sha = ad2f7b...f242a8 has been accepted.
```
### 2.2 输出示例
运行1.3节所述脚本,即可正常运行,某次测试的Jenkins控制台输出如下:
```sh
Started by user admin
Running as SYSTEM
Building in workspace /var/lib/jenkins/workspace/gitee_task
The recommended git tool is: NONE
No credentials specified
> git rev-parse --resolve-git-dir /var/lib/jenkins/workspace/gitee_task/.git # timeout=10
Fetching changes from the remote Git repository
> git config remote.origin.url https://gitee.com/tjopenlab/como-fscp-voter.git # timeout=10
Fetching upstream changes from https://gitee.com/tjopenlab/como-fscp-voter.git
> git --version # timeout=10
> git --version # 'git version 2.34.1'
> git fetch --tags --force --progress -- https://gitee.com/tjopenlab/como-fscp-voter.git +refs/heads/*:refs/remotes/origin/* # timeout=10
> git rev-parse refs/remotes/origin/master^{commit} # timeout=10
Checking out Revision f352e32...a11038e1a0b3d00 (refs/remotes/origin/master)
> git config core.sparsecheckout # timeout=10
> git checkout -f f352e32...a11038e1a0b3d00 # timeout=10
Commit message: "Add debugging options"
> git rev-list --no-walk f352e32...a11038e1a0b3d00 # timeout=10
[gitee_task] $ /bin/bash /tmp/jenkins5491866742155348232.sh
jenkins
/var/lib/jenkins/workspace/gitee_task
切换到分支 'master'
您的分支与上游分支 'origin/master' 一致。
已经是最新的。
rm -f como_fscp_voter
rm -f voter_client
rm -f voter_client_tcp_1
gcc -I./libzmtp/include -I./libcrc -I./inih -I./src -I./rudp src/como_fscp_voter.c src/config.c src/voter_server.c src/voterlib.c src/math_utils.c src/proc_utils.c src/voter_message.c libcrc/crc32.c inih/ini.c src/ZMQ_Switcher.c src/voter_logger.c rudp/rudp.c ./libzmtp/src/MemPool.c ./libzmtp/src/zmtp_channel.c ./libzmtp/src/zmtp_dealer.c ./libzmtp/src/zmtp_endpoint.c ./libzmtp/src/zmtp_ipc_endpoint.c ./libzmtp/src/zmtp_msg.c ./libzmtp/src/zmtp_tcp_endpoint.c -o como_fscp_voter -O0 -Wall -W -lpthread -g
gcc -I./libzmtp/include -I./libcrc -I./inih -I./src -I./rudp libcrc/crc32.c src/voter_message.c src/ZMQ_Switcher.c src/voterlib.c src/voter_logger.c clients/voter_client.c rudp/rudp.c ./libzmtp/src/MemPool.c ./libzmtp/src/zmtp_channel.c ./libzmtp/src/zmtp_dealer.c ./libzmtp/src/zmtp_endpoint.c ./libzmtp/src/zmtp_ipc_endpoint.c ./libzmtp/src/zmtp_msg.c ./libzmtp/src/zmtp_tcp_endpoint.c -o voter_client -O0 -Wall -W -lpthread -g
gcc -I./libzmtp/include -I./libcrc -I./inih -I./src -I./rudp libcrc/crc32.c src/voter_message.c src/ZMQ_Switcher.c src/voterlib.c src/voter_logger.c clients/voter_client_tcp_1.c rudp/rudp.c ./libzmtp/src/MemPool.c ./libzmtp/src/zmtp_channel.c ./libzmtp/src/zmtp_dealer.c ./libzmtp/src/zmtp_endpoint.c ./libzmtp/src/zmtp_ipc_endpoint.c ./libzmtp/src/zmtp_msg.c ./libzmtp/src/zmtp_tcp_endpoint.c -o voter_client_tcp_1 -O0 -Wall -W -lpthread -g
2024-11-15-09:17:55
Starting server...
como_fscp_voter: started
Starting client...
Terminating server...
como_fscp_voter: stopped
--------------------------------
2024-11-15-09:17:55.log content:
Starting server...
Starting client...
Terminating server...
Finished: SUCCESS
```
### 参考链接
[Jenkins + Gitee 实现代码自动化构建 - 腾讯云](https://cloud.tencent.com/developer/article/2024230)
[Jenkins - 一篇就能上手 Gitee代码自动化构建 - 阿里云](https://developer.aliyun.com/article/947111)
[Generic Webhook Trigger - Jenkins.io](https://plugins.jenkins.io/generic-webhook-trigger/)
Gitee Webhook存在404问题,使用Generic Webhook([jenkins使用gitee插件自动部署webhook404问题记录 - CSDN](https://blog.csdn.net/qq_44980517/article/details/134060461))