- ci.yml 增加 deploy job:verify 全绿后 rsync 到 /opt/kanban/dist 并做线上自检 - runner 与站点同机(host 模式),部署直接写本地目录,不依赖 SSH 密钥与 Secrets - 站点目录是容器 bind mount,必须原地同步;manual deploy.sh 同步改为 rsync 语义 - 新增 deploy/:容器版 nginx 配置、runner 配置与 systemd 单元、服务器初始化脚本 - README 更新实际部署架构(1Panel + Nginx Proxy Manager 反代)与 runner 说明
72 lines
2.3 KiB
Bash
72 lines
2.3 KiB
Bash
#!/usr/bin/env bash
|
|
# 一键发布到云服务器:本地构建 → 上传 → 原地同步
|
|
#
|
|
# 用法:
|
|
# SERVER=root@132.232.203.88 ./deploy/deploy.sh
|
|
# SERVER=root@1.2.3.4 WEB_ROOT=/var/www/kanban SSH_PORT=2222 ./deploy/deploy.sh
|
|
#
|
|
# 环境变量:
|
|
# SERVER 远端 SSH 目标(必填),如 root@1.2.3.4
|
|
# WEB_ROOT 远端站点目录,默认 /opt/kanban/dist(容器挂载的就是这里)
|
|
# SSH_PORT SSH 端口,默认 22
|
|
# SKIP_BUILD 设为 1 时跳过本地构建,直接发布现有 dist/
|
|
#
|
|
# 注意:站点目录是容器的 bind mount,必须「原地同步」。
|
|
# 整目录 mv 之后容器仍指向旧 inode,看不到新文件 —— 所以这里只用 rsync / tar 解包原地覆盖。
|
|
|
|
set -euo pipefail
|
|
|
|
# 无论从哪里调用,都切到仓库根目录
|
|
cd "$(dirname "$0")/.."
|
|
|
|
SERVER="${SERVER:-}"
|
|
WEB_ROOT="${WEB_ROOT:-/opt/kanban/dist}"
|
|
SSH_PORT="${SSH_PORT:-22}"
|
|
SKIP_BUILD="${SKIP_BUILD:-0}"
|
|
|
|
if [ -z "$SERVER" ]; then
|
|
echo "缺少 SERVER。示例:SERVER=root@1.2.3.4 $0" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$SKIP_BUILD" != "1" ]; then
|
|
echo "==> 本地构建"
|
|
npm run build
|
|
fi
|
|
|
|
if [ ! -f dist/index.html ]; then
|
|
echo "dist/index.html 不存在,构建可能失败了" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> 远端准备目录 $WEB_ROOT"
|
|
ssh -p "$SSH_PORT" "$SERVER" "mkdir -p '$WEB_ROOT'"
|
|
|
|
if command -v rsync >/dev/null 2>&1; then
|
|
echo "==> rsync 原地增量同步"
|
|
rsync -az --delete -e "ssh -p $SSH_PORT" dist/ "$SERVER:$WEB_ROOT/"
|
|
else
|
|
# Windows / Git Bash 一般没有 rsync:上传到远端临时目录,再在远端原地同步
|
|
echo "==> tar 上传后远端原地同步(本地未检测到 rsync)"
|
|
STAMP=$(date +%Y%m%d%H%M%S)
|
|
STAGE="/tmp/kanban-release-$STAMP"
|
|
|
|
ssh -p "$SSH_PORT" "$SERVER" "rm -rf '$STAGE' && mkdir -p '$STAGE'"
|
|
tar -czf - -C dist . | ssh -p "$SSH_PORT" "$SERVER" "tar -xzf - -C '$STAGE'"
|
|
|
|
ssh -p "$SSH_PORT" "$SERVER" "
|
|
set -e
|
|
if command -v rsync >/dev/null 2>&1; then
|
|
rsync -a --delete '$STAGE/' '$WEB_ROOT/'
|
|
else
|
|
# 没有 rsync 时退化为「清空 + 解包」,会有毫秒级空窗
|
|
find '$WEB_ROOT' -mindepth 1 -delete
|
|
cp -a '$STAGE/.' '$WEB_ROOT/'
|
|
fi
|
|
rm -rf '$STAGE'
|
|
"
|
|
fi
|
|
|
|
echo "==> 发布完成:$SERVER:$WEB_ROOT"
|
|
echo " 验证:curl -I http://<域名或 IP>/today # 期望 200,而不是 404"
|