1041 字
5 分钟

如何使用github进行自动化不停机CI/CD

2026-01-28
20260128
加载中...

前言#

最近在跟同学一起做一个产品,我们也没有什么钱,在做产品部署的时候想着能用免费的就用免费的了,于是就使用 github 完成了自动化 CI/CD 的蓝绿部署

思路#

蓝绿部署本质上就是两份文件,一份是新版本另一份是老版本,在切换版本时候不停机不影响另一份。而 github 又有 actions 可以免费做 CI/CD 的操作,那我们就可以通过 github 的 actions 来操作我们服务器了。

步骤#

github actions 脚本#

  1. 在 github 仓库跟根目录下准备 .github/workflows/test-deploy.yaml,其中test-deploy可以替换成你的部署的文件名,但是结尾必须是.yaml

  2. 我的 yaml 文件如下

name: 部署测试环境
on:
push:
branches:
- develop # 或者是你想触发自动构建的分支
- feat/**
# 可以写也可以不写path模块,它的意思是当修改的代码命中下列规则时才会执行脚本
paths:
- "apps/server/**"
- "apps/web/**"
- ".github/workflows/test-delopy.yaml"
# paths-ignore:
# - 'apps/mini-program/**'
# 公共的env 参考https://github.com/easingthemes/ssh-deploy下的tips
env:
# 本地.ssh文件下的私钥id_rsa,存在secrets的PRIVATE_KEY中
SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_PRIVATE_KEY_TEST }}
# 服务器域名/IP
REMOTE_HOST: ${{ secrets.SERVER_HOST_TEST }}
# 服务器端口
REMOTE_PORT: ${{ secrets.SERVER_PORT_TEST }}
# 服务器默认用户名为root
REMOTE_USER: ${{ secrets.SERVER_USER_TEST }}
jobs:
test-deploy-server:
runs-on: ubuntu-latest
steps:
- name: 检测仓库
uses: actions/checkout@v3
- name: 部署到服务器
uses: appleboy/ssh-action@master
with:
host: ${{ env.REMOTE_HOST }}
port: ${{ env.REMOTE_PORT }}
username: ${{ env.REMOTE_USER }}
key: ${{ env.SSH_PRIVATE_KEY }}
script: |
set -e # 任何命令失败立即退出
cd /home/apps/sports
./deploy-server.sh

上述的 yaml 文件表示当我的分支名命中develop或者是以feat开头时,并且我推送的代码的更改命中了 path 中声明的文件就会执行该 action,path 模块可以不写,不写的话表示只要命中了分支名就会执行该 action env 模块表示引用了 secret 中的变量到 env 中,方便后续再 steps 中使用,方便统一管理。我的 env 模块引用了四个变量,分别是服务器的ssh连接密钥服务器地址服务器ssh端口服务器用户名,其中服务器指的是你的代码要部署的服务器。

下面的 jobs 模块声明了一个部署任务:test-deploy-server,该部署任务主要工作是使用了appleboy/ssh-action@master带服务器上执行 shell 脚本,我们上述声明的环境变量就是在此处使用的。比较重要的是部署到服务器步骤中的script中的内容,它表示:到服务器的 /home/apps/sports目录下执行deploy-server.sh脚本。

deploy-server.sh 脚本#

Terminal window
set -e # 任何命令失败立即退出
# 加载了nvm的命令
source /root/.nvm/nvm.sh
# nvm使用了node24
nvm use 24
# 安装了pnpm
npm i -g pnpm
# 也可以设置执行当前脚本时的环境变量例如NODE_ENV
export NODE_ENV=production
# 目录定义
BLUE_DIR=/home/apps/sports/blue
GREEN_DIR=/home/apps/sports/green
CURRENT_SYMLINK=/home/apps/sports/current
# 自动创建目录(首次部署时不存在)
mkdir -p $BLUE_DIR
mkdir -p $GREEN_DIR
# 判断当前指向如果当前指向蓝则将当前指向为绿
if [ "$(readlink -f $CURRENT_SYMLINK)" == "$BLUE_DIR" ]; then
NEW_DIR=$GREEN_DIR
else
NEW_DIR=$BLUE_DIR
fi
echo "Deploying to $NEW_DIR ..."
# 清空新目录并拉取代码
rm -rf $NEW_DIR
mkdir -p $NEW_DIR
# 克隆当前的develop分支代码到新的文件夹中,当然也可以判断一下如果是首次就克隆后续可以直接pull
git clone -b develop git@github.com:zhaoyuqiqi/xxxx.git $NEW_DIR
cd $NEW_DIR
git checkout develop
# 安装依赖 & 构建
pnpm install
pnpm run build:server
# 数据库迁移
pnpm run migrate:server
# 更新 symlink
ln -sfn $NEW_DIR $CURRENT_SYMLINK
# PM2 reload(cluster 模式保证零停机)
cd /home/apps
# 通过机子上的PM2重新启动新项目
pm2 reload pm2.config.js --only sports
echo "Deployment completed successfully."

通过上述的步骤即可自动化部署一个零停机的 nodejs 应用,当然部署其他的也是类似的步骤,主要是通过了ln -sfn 地址A /home/apps/sports/current,将/home/apps/sports/current指向了地址 A,这个操作是瞬时的,并且在 pm2 的部署脚本中,部署的代码地址也是指向了/home/apps/sports/current所以可以做到切换当前目录后,直接重启 pm2 部署脚本即可。

如何使用github进行自动化不停机CI/CD
https://www.zhaoyuqi.top/posts/20260128/
作者
爱哭的赵一一
发布于
2026-01-28
许可协议
CC BY-NC-SA 4.0