一个 Webhook 搞定自动部署

起因

git push origin main,然后 SSH 到服务器,git pull,重启服务。一天两次还行,一天十次就开始怀疑人生了。

问题很明确:代码推上去之后,部署能不能自己跑?

能。一个 webhook 就够了。

最小方案

整条链路只有三个角色:Git仓库(发信号)、webhook 服务(收信号)、部署脚本(干活)。

不需要 Jenkins,不需要 GitLab Runner,甚至不需要任何 CI 平台。一台服务器,一个轻量进程,搞定。

这里用 adnanh/webhook,一个 Go 写的小工具,单二进制文件,配置是 JSON。

配置 webhook服务

hook 定义文件 hooks.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[
{
"id": "deploy",
"execute-command": "/opt/scripts/deploy.sh",
"command-working-directory": "/opt/app",
"pass-arguments-to-command": [
{
"source": "payload",
"name": "ref"
}
],
"trigger-rule": {
"and": [
{
"match": {
"type": "value",
"value": "refs/heads/main",
"parameter": {
"source": "payload",
"name": "ref"
}
}
},
{
"match": {
"type": "value",
"value": "[YOUR_SECRET]",
"parameter": {
"source": "header",
"name": "X-Hub-Signature-256"
}
}
}
]
}
}
]

两个关键点:只响应 main 分支的推送;通过 secret 验签,防止随便谁都能触发。

启动服务:

1
webhook -hooks hooks.json -port 9000 -verbose

然后在 Git 仓库的 webhook 设置里填上 http://[YOUR_SERVER]:9000/hooks/deploy,payload 选 JSON,填好 secret。

部署脚本

deploy.sh 没什么花活:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash
set -euo pipefail

REPO_DIR="/opt/app"
LOG="/var/log/deploy.log"

echo "$(date '+%Y-%m-%d %H:%M:%S') Deploy started" >> "$LOG"

cd "$REPO_DIR"
git fetch origin main
git reset --hard origin/main

# 依赖安装、构建、重启,按项目实际情况改
npm ci --production >> "$LOG" 2>&1
pm2 restart app >> "$LOG" 2>&1

echo "$(date '+%Y-%m-%d %H:%M:%S') Deploy finished" >> "$LOG"

set -euo pipefail 是底线,任何一步出错直接停掉,别让半成品跑起来。

git reset --hard 而不是 git pull,是因为服务器上不应该有本地改动。如果有,那是另一个问题。

几个容易踩的坑

webhook 进程的运行用户得有仓库目录的读写权限,也得有重启服务的权限。建议单独建一个用户,用 sudoers 精确授权,别图省事用 root 跑。

日志一定要写。部署失败的时候,没日志等于瞎猜。

还有一个不太明显的问题:并发。如果短时间内连续推了好几次,多个部署脚本会同时跑。简单的解法是加个 flock 文件锁:

1
2
exec 200>/tmp/deploy.lock
flock -n 200 || { echo "Deploy already running, skip"; exit 0; }

拿不到锁就跳过,反正下一次推送还会触发。

然后呢

这套东西跑起来之后,自然会想要更多:部署失败发通知、自动回滚、跑完测试再部署。到了那个阶段,可能就该认真考虑一个真正的 CI/CD 平台了。

下一步值得想的问题:部署失败了,怎么自动回滚到上一个可用版本?


一个 Webhook 搞定自动部署
https://ghost.kasumi.live/2026/02/26/一个 Webhook 搞定自动部署/
作者
Amadeus
发布于
2026年2月26日
许可协议