使用github action自动部署,别光dev,也ops一下
dev&ops
作为一个程序员,我们的工作本质上可以拆解为两个动作:Develop(开发软件) 和 Operation(操作,部署,维护,把开发的东西用起来)。
在 Dev 时,我们追求工程化,设计模式、可读性、最佳实践。在 Ops 时,我们却成了懒狗。代码一丢,nohup 一挂,能跑就行。
既然我们总是以工程师的角色在dev,那ops也理应工程
无论是自动部署还是容器,在配置上都挺让人感到繁琐的,但其实这也是我们应该做的,把运维工作描述出来并且规范化,这也是开发的一部分
从最典中典的流程开始:代码推送到 GitHub → 自动测试构建 → 服务器同步代码 → 自动重启 Node 服务。
写一个github action
文档: https://docs.github.com/zh/actions
action实际上是一个yaml配置文件,位于你的项目/.github/workflows/[名称].yml
虽然可能有种脚本的感觉,但他不是脚本
下面是一个基础的action
name: 名称
on: [push] #在推送时触发,支持多种条件
jobs:
build: #build是job id,这里可以自定义
runs-on: ubuntu-latest #跑在最新的ubuntu中
steps:
- name: Trigger webhook # 步骤们
可以看出来,github会给我们提供一个虚拟环境,然后开始我们的步骤
很显然,最重要的就是steps
steps能干什么?
1.run – 执行shell命令
你可以随心所欲的在github给你的环境中做任何事,甚至临时开一个mc服务器
- name: 单行
run: npm install
- name: 检查环境
run: |
node -v
npm -v
ls -la
df -h # 查看磁盘空间
tip : | vs > (小知识)
虽然不常用,但 YAML 还有一个 > 符号:
> (Folded):折叠换行。它会把多行文本变成一个很长的单行字符串(中间用空格隔开)。
| (Literal):保留换行。你写几行,执行时就是几行。
2. 调用”积木“ (uses)
它是别人封装好的功能,你直接拿来用。
你可以在这里找你需要的操作: https://github.com/marketplace?type=actions
有
- 官方积木:如设置环境 (
setup-node)、上传产物 (upload-artifact)。 - 社区积木:如发送钉钉消息、部署到阿里云、扫描代码漏洞。
- name: 压缩图片
uses: calibreapp/image-actions@main # 直接引用别人的插件
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
3. 逻辑与条件控制 (if)
这是体现“工程化严谨性”的地方。你可以让某个步骤只在特定条件下运行。
- 场景:只有测试通过了才执行部署,或者只有在
main分支才发送生产环境通知。
- name: 告警通知
if: failure() # 只有前面的步骤失败时,才执行这个步骤
run: curl -X POST https://your-webhook-url -d '{"msg": "构建挂了!"}'
4. 变量管理与数据传递 (env & outputs)
- name: 获取当前版本号
id: get_version
run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: 使用上一步的版本号
run: echo "当前版本是 ${{ steps.get_version.outputs.VERSION }}"
ID 与输出:给 Step 起个 ID,它的结果就能被引用。
最常用的用法就是把一些敏感数据,比如token放在secrets中肯定比写在yaml中要好
这里区分一下 Repository secrets 和 Environment secrets
| 特性 | Repository Secrets (仓库级) | Environment Secrets (环境级) |
| 作用范围 | 整个仓库。只要是这个仓库的 Action 都能用。 | 特定环境。只有声明了使用该环境的任务(Job)才能用。 |

编译并部署到服务器
服务器同步代码有两种实现方式,一是在action打包并且传送到服务器,一个是在服务器中git pull后自行处理

一般来说应该这么写,在action中实现打包与部署
不过我要在宝塔中使用,编译后发送到服务器,速度较慢,也会有一些权限问题,所以只使用了webhook功能,并使用shell脚本实现剩下的流程

webhook功能可在应用市场中安装插件

我的项目是node项目,添加项目时选择pm2项目,可以通过命令行管理项目


# 实现一个webhook机器人的发消息函数
send_to_feishu() {
local text_content=$1
local json_data="{\"msg_type\":\"text\",\"content\":{\"text\":\"$text_content\"}}"
curl -s -X POST -H "Content-Type: application/json" -d "$json_data" "你的_WEBHOOK_URL" > /dev/null
}
logger(){ # 输出的同时可以发消息到飞书
if [ $# -gt 0 ]; then
send_to_feishu "$1"
echo "$1"
else
while IFS= read -r line; do
send_to_feishu "$line"
echo "$line"
done
fi
}
set -eo pipefail # 遇到错误便停止
logger "--- 任务开始: $(date) ---"
TARGET_DIR="项目路径"
REPO_URL="git地址"
# 进入目录
cd "$TARGET_DIR" || { logger "错误: 无法进入目录 $TARGET_DIR"; exit 1; }
# 经典信任文件夹
export HOME=/root # 保存设置,webhook是以root身份执行的
git config --global --add safe.directory "$TARGET_DIR" 2>&1 | logger
if [ -d ".git" ]; then
logger "Git仓库已存在,执行更新..."
git clean -fd 2>&1 | logger
git reset --hard HEAD 2>&1 | logger
# 强制拉取,防止分支名不一致(有些是 main,有些是 master)
git pull origin $(git branch --show-current) 2>&1 | logger
else
logger "Git仓库不存在,执行克隆..."
# 如果目录非空,git clone . 会报错,这里先确保清理
git clone "$REPO_URL" . 2>&1 | logger
fi
logger "最新的提交:"
git log -1 --pretty=format:"%h - %an, %ar : %s" | logger
logger "\n--- 开始构建 (npm) ---"
cd mailSilver
npm i
npm run build
logger "构建完成"
pm2 reload mailSilver
logger "重启完成"
评论