【Node】如何用 Webhook 实现 CI/CD

290 阅读3分钟

CI 持续集成: 代码提交后自动构建和测试 CD 持续部署: 测试通过后自动部署到目标环境

关于 CI/CD 有多种方式,比如

  • 基于工具的 CI/CD
    • Jenkis
    • GitLab CI/CD
    • Github Actions
    • CircleCI
    • Travis CI
  • 容器化 CI/CD
    • 使用 Docker 实现 CI/CD, 使用 Dokcerfile 定义构建环境
    • 在 CI/CD 构建容器镜像并推送到镜像仓库(Dokcer Hub、 AWS ECR)
    • 通过 Kunbernetes 或者其他容器编排工具实现自动化部署
  • 无服务器(Serverless) CI/CD
  • 蓝绿部署与金丝雀
  • 使用 webhook

WebHook

Webhook 是一种基于 HTTP 的通信机制,通常被用作一种事件驱动的集成方式。它在 CI/CD 中也扮演重要角色,尤其是在自动化流程的触发环节。简单来说,Webhook 是“反向 API”,它允许一个系统在特定事件发生时主动向另一个系统发送实时通知,而不是让后者不断轮询检查状态

Webhook 的工作原理

  1. 事件触发:当某个系统发生特定事件(例如代码提交、构建完成)时,会生成一个事件。
  2. HTTP 请求:该系统通过 HTTP POST 请求将事件数据(通常是 JSON 格式)发送到一个预先配置的 URL(即 Webhook 的目标地址)。
  3. 接收与处理:目标系统接收到请求后,根据数据执行相应操作,比如触发构建、部署或发送通知。

在 CI/CD 中的应用

Webhook 常用于连接代码仓库与 CI/CD 工具,典型场景包括:

  • 代码提交触发构建:例如,GitHub 或 GitLab 在代码推送(Push)或合并请求(Pull Request)发生时,通过 Webhook 通知 Jenkins 或 GitLab CI,开始构建和测试。

  • 状态反馈:CI/CD 工具完成任务后,可以通过 Webhook 将结果(成功/失败)发送给其他系统,比如通知 Slack 或更新代码仓库的状态。

  • 外部服务集成:比如部署完成后,通过 Webhook 通知监控系统或日志系统。

我的实战当中没有利用 jenkis, 因为我这是个小型项目。如果是复杂的场景,可以配置 Webhook 到 Jenkins,然后在 Jenkins 定义完整的流水线

WebHook + 自定义脚本

1、 在【宝塔 Linux】安装 Webhook

image.png

添加 hook ,输入CI/CD的脚本(拉取代码、build、start)

#!/bin/bash

# 定义变量
REPO_PATH="xx"
FRONTEND_PATH="xx"
REPO_URL="your github url"

# 日志文件
LOG_FILE="/var/log/deploy.log"
echo "$(date) - 开始部署" >> $LOG_FILE
echo "当前用户: $(whoami)" >> $LOG_FILE
echo "PATH: $PATH" >> $LOG_FILE

# 确认 pnpm 可用性
echo "测试 pnpm 版本..." >> $LOG_FILE
/www/server/nodejs/v23.7.0/bin/pnpm -v >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
    echo "错误: 无法运行 pnpm" >> $LOG_FILE
    exit 1
fi

# 检查仓库目录是否存在
echo "检查仓库目录..." >> $LOG_FILE
if [ ! -d "$REPO_PATH" ]; then
    echo "仓库目录 $REPO_PATH 不存在,执行 git clone..." >> $LOG_FILE
    mkdir -p $REPO_PATH
    cd $REPO_PATH
    git clone $REPO_URL . >> $LOG_FILE 2>&1
    if [ $? -ne 0 ]; then
        echo "错误: git clone 失败" >> $LOG_FILE
        exit 1
    fi
else
    # 切换到仓库目录
    cd $REPO_PATH
    # 确保是 Git 仓库
    if [ ! -d ".git" ]; then
        echo "目录 $REPO_PATH 不是 Git 仓库,执行 git init 并关联远程仓库..." >> $LOG_FILE
        git init >> $LOG_FILE 2>&1
        git remote add origin $REPO_URL >> $LOG_FILE 2>&1
    fi
    # 拉取最新代码
    echo "拉取最新代码..." >> $LOG_FILE
    git fetch origin >> $LOG_FILE 2>&1
    git reset --hard origin/main >> $LOG_FILE 2>&1
    if [ $? -ne 0 ]; then
        echo "错误: git pull 失败" >> $LOG_FILE
        exit 1
    fi
fi

# 检查前端目录是否存在
echo "检查前端目录..." >> $LOG_FILE
if [ ! -d "$FRONTEND_PATH" ]; then
    echo "错误: 前端目录 $FRONTEND_PATH 不存在" >> $LOG_FILE
    exit 1
fi

# 切换到前端目录
cd $FRONTEND_PATH

# 安装前端依赖
echo "运行 pnpm install (前端)..." >> $LOG_FILE
/www/server/nodejs/v23.7.0/bin/pnpm install >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
    echo "错误: 前端 pnpm install 失败" >> $LOG_FILE
    exit 1
fi

# 构建前端
echo "运行 pnpm run build (前端)..." >> $LOG_FILE
/www/server/nodejs/v23.7.0/bin/pnpm run build >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
    echo "错误: 前端 pnpm run build 失败" >> $LOG_FILE
    exit 1
fi
chown -R www:www $FRONTEND_PATH
echo "前端构建完成" >> $LOG_FILE

# 启动前端服务
echo "启动前端服务 .." >> $LOG_FILE
# 检查前端进程是否存在
if /www/server/nodejs/v23.7.0/bin/pm2 list | grep -q "nanlan-blog-client"; then
    echo "删除现有 nanlan-blog-client 进程..." >> $LOG_FILE
    /www/server/nodejs/v23.7.0/bin/pm2 delete nanlan-blog-client >> $LOG_FILE 2>&1
    if [ $? -ne 0 ]; then
        echo "错误: 删除 nanlan-blog-client 进程失败" >> $LOG_FILE
        exit 1
    fi
else
    echo "nanlan-blog-client 进程不存在,跳过删除..." >> $LOG_FILE
fi
/www/server/nodejs/v23.7.0/bin/pm2 start pnpm --name nanlan-blog-client -- start  >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
    echo "错误: 前端 pnpm start 失败" >> $LOG_FILE
    exit 1
fi
echo "前端服务启动完成" >> $LOG_FILE

2、 设置 Webhook 触发器

上述步骤完成之后,会有 web hook url

image.png

将这个 url 拷贝,到 github 去设置 Webhook

image.png

设置 payload url、 trigger event、content type

image.png

3、 测试

只要往 github push 代码,就能自动触发 CI/CD 流程