Merge pull request 'ci: 部署工作流改为本地 runner 直跑版(免 SSH/Secrets)' (#65) from ci/local-runner-deploy into main
This commit is contained in:
@@ -1,90 +1,83 @@
|
||||
# PM2 手动部署工作流
|
||||
# 手动触发 → 构建 → rsync → 安装依赖 → 数据库迁移 → PM2 重载
|
||||
# PM2 本地 runner 手动部署工作流
|
||||
# 手动触发 → 服务器本地 git pull → 构建 → 依赖安装 → 数据库迁移 → PM2 重载
|
||||
#
|
||||
# 适用场景:Gitea runner 与生产服务器同机(本机直跑,不需要 SSH/Secrets)。
|
||||
#
|
||||
# 前置准备:
|
||||
# 1. 服务器 MySQL 已在运行
|
||||
# 2. 服务器已安装 PM2: npm i -g pm2
|
||||
# 3. Gitea 仓库 Settings → Secrets 配置:
|
||||
# - SSH_PRIVATE_KEY : 部署用 SSH 私钥
|
||||
# - SSH_HOST : 服务器地址
|
||||
# - SSH_USER : SSH 用户名
|
||||
# - SSH_PORT : SSH 端口(默认 22,可选)
|
||||
# - REMOTE_DIR : 服务器项目目录,如 /opt/gongxue
|
||||
# 1. Gitea Actions 已开启,且已注册 self-hosted runner(runs-on 标签与下面一致)
|
||||
# 2. 服务器已 clone 仓库到部署目录(默认 /opt/gongxue,可用仓库 Variable REMOTE_DIR 覆盖)
|
||||
# 3. 服务器已安装 Node 22 + PM2(npm i -g pm2),MySQL 已运行
|
||||
# 4. runner 运行账户对部署目录有写权限、可执行 npm/pm2
|
||||
#
|
||||
# 关于 .env:不需要配置在 Gitea 界面。.env 只放在服务器部署目录下,
|
||||
# git pull 不会覆盖它,PM2/Nest 启动时直接读取服务器上的 .env。
|
||||
#
|
||||
# 关于“在 docker 里构建/迁移”:
|
||||
# - 如果 runner 以“宿主机进程”方式运行(推荐,最省事):本 workflow 的
|
||||
# npm ci / build / migration 直接在宿主机执行,pm2 直接操作宿主 pm2。
|
||||
# - 如果 runner 跑在 docker 容器里:需要把部署目录挂载进容器
|
||||
# (如 -v /opt/gongxue:/opt/gongxue),构建/迁移在容器内完成;
|
||||
# PM2 重载则必须打到宿主机(挂载 docker.sock 后 docker exec 到宿主,
|
||||
# 或在宿主机单独跑 pm2 服务端)——容器里的 pm2 管理不了宿主进程。
|
||||
|
||||
name: PM2 部署
|
||||
name: PM2 本地部署
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
seed_roles:
|
||||
description: '强制播种 RBAC 权限码(首次部署或新增权限码时勾选,跑完会自动去掉)'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: deploy
|
||||
group: deploy-local
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: self-hosted # 改为你注册 runner 时使用的 label(如 ubuntu-latest)
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 安装 Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
- name: 拉取最新代码
|
||||
run: |
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
git fetch origin
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
- name: 安装依赖 & 构建
|
||||
run: |
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
npm ci
|
||||
npm run build -w @gongxue/server
|
||||
npm run build -w @gongxue/admin
|
||||
|
||||
- name: 配置 SSH
|
||||
- name: 执行数据库迁移
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
# 单引号 EOF 防止 key 中的 $ / 反引号被 shell 插值(YAML 会剥掉缩进,bash 实际收到列首 EOF)
|
||||
cat > ~/.ssh/deploy_key <<'EOF'
|
||||
${{ secrets.SSH_PRIVATE_KEY }}
|
||||
EOF
|
||||
chmod 600 ~/.ssh/deploy_key
|
||||
cat >> ~/.ssh/config <<'EOF'
|
||||
Host deploy-server
|
||||
HostName ${{ secrets.SSH_HOST }}
|
||||
User ${{ secrets.SSH_USER }}
|
||||
Port ${{ secrets.SSH_PORT || '22' }}
|
||||
IdentityFile ~/.ssh/deploy_key
|
||||
StrictHostKeyChecking accept-new
|
||||
EOF
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
npm run migration:run -w @gongxue/server
|
||||
|
||||
- name: 同步代码到服务器
|
||||
- name: PM2 重载
|
||||
run: |
|
||||
rsync -avz --delete \
|
||||
--exclude='node_modules' \
|
||||
--exclude='.git' \
|
||||
--exclude='*.db' \
|
||||
--exclude='.DS_Store' \
|
||||
--exclude='logs/' \
|
||||
--exclude='.turbo/' \
|
||||
--exclude='.claude/' \
|
||||
--exclude='.codegraph/' \
|
||||
--exclude='.env*' \
|
||||
--exclude='data.sql' \
|
||||
--exclude='uploads/' \
|
||||
./ deploy-server:${{ secrets.REMOTE_DIR }}/
|
||||
|
||||
- name: 安装依赖 → 迁移 → PM2 重载
|
||||
run: |
|
||||
ssh deploy-server "
|
||||
set -e
|
||||
cd ${{ secrets.REMOTE_DIR }}
|
||||
mkdir -p logs
|
||||
echo '安装依赖...'
|
||||
# 注意:migration:run 依赖 ts-node/tsconfig-paths(devDependencies),不能 --omit=dev
|
||||
npm ci
|
||||
echo '执行数据库迁移...'
|
||||
npm run migration:run -w @gongxue/server
|
||||
echo 'PM2 重载...'
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
if [ "${{ github.event.inputs.seed_roles }}" = "true" ]; then
|
||||
echo '>>> 强制播种 RBAC 权限码(本次进程带 SEED_ROLES=true)'
|
||||
SEED_ROLES=true pm2 startOrReload ecosystem.config.cjs --only gongxue-backend --update-env
|
||||
pm2 restart gongxue-backend --update-env # 去掉 SEED_ROLES 正常重启
|
||||
else
|
||||
pm2 startOrReload ecosystem.config.cjs --update-env
|
||||
pm2 save
|
||||
echo '=== PM2 状态 ==='
|
||||
pm2 status
|
||||
"
|
||||
fi
|
||||
pm2 save
|
||||
pm2 status
|
||||
|
||||
- name: 健康检查
|
||||
run: |
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
sleep 3
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/api/dashboard/stats || true)"
|
||||
echo "后端 HTTP 状态: ${code}(401=正常,接口需登录)"
|
||||
if [ "${code}" != "401" ] && [ "${code}" != "200" ]; then
|
||||
echo "健康检查失败:后端未按预期响应" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user