ci: 部署到腾讯云服务器并启用 Gitea Actions 自动发布
CI / verify (push) Canceled after 1m37s
CI / 部署到服务器 (push) Skipped

- 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 说明
This commit is contained in:
chenshoulin
2026-10-19 20:59:38 +08:00
parent 777815704d
commit f9bf1b3eb3
8 changed files with 446 additions and 18 deletions
+84 -13
View File
@@ -169,19 +169,61 @@ npm run build
# 将 dist/ 上传或指向静态服务器
```
Nginx 示例:
### 部署到云服务器(当前实际架构)
服务器由 1Panel 管理,80/443 已被 **Nginx Proxy Manager** 占用,所以站点不装宿主机 Nginx,
而是跑一个 `nginx:alpine` 容器,由 NPM 反代:
```nginx
server {
listen 80;
root /var/www/kanban/dist;
index index.html;
location / {
# 必须配置:/today 是真实路径,刷新时文件不存在,需要回落到 index.html
try_files $uri $uri/ /index.html;
}
}
```
浏览器 → NPM(80/443, 证书) → kanban 容器(:80) → /opt/kanban/dist
↑
CI runner 构建后 rsync 到这里(原地同步)
```
| 文件 | 用途 |
| -------------------------------------- | ---------------------------------------------------------------- |
| `deploy/nginx.docker.conf` | 容器内站点配置:SPA 回落、`sw.js` 不缓存、`/assets` 长缓存、gzip |
| `deploy/gitea-runner.config.yaml` | runner 配置:host 模式、`ubuntu-latest` 标签 |
| `deploy/gitea-runner.service` | runner 的 systemd 单元 |
| `deploy/deploy.sh` | 不走 CI 时的手动发布脚本 |
| `deploy/nginx.conf` + `server-init.sh` | 备选路径:80 端口空闲、直接用宿主机 Nginx 的机器 |
**容器启动命令**(已在服务器上运行,重建时照抄):
```bash
docker run -d --name kanban --restart unless-stopped \
--network 1panel-network \
-p 127.0.0.1:8081:80 \
-v /opt/kanban/dist:/usr/share/nginx/html:ro \
-v /opt/kanban/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
nginx:alpine
```
**反向代理**:NPM 后台 → Hosts → Proxy Hosts → Add
| 字段 | 值 |
| ---------------- | -------------------- |
| Domain Names | `kanban.shoulin.net` |
| Scheme | `http` |
| Forward Hostname | `172.17.0.1` |
| Forward Port | `8081` |
其余站点都走 `172.17.0.1:端口`,这里保持一致(用容器名 `kanban:80` 实测也可通,但容器重建后 IP 可能变)。
SSL 页签挂证书并开启 Force SSL,域名解析到服务器 IP 即可。
**手动发布**(CI 不可用时):
```bash
SERVER=root@132.232.203.88 WEB_ROOT=/opt/kanban/dist ./deploy/deploy.sh
```
> 注意:`/opt/kanban/dist` 是容器挂载目录,**不能整目录 `mv`**——bind mount 跟的是 inode,
> 换目录后容器仍指向旧内容。`deploy.sh` 与 CI 都用 rsync 原地同步,就是为了避开这个坑。
> **HTTPS 不是可选项**:Service Worker 只在 HTTPS 或 localhost 下注册成功。用 IP 走 HTTP 访问时,
> 应用能打开,但「安装到桌面 / 离线可用 / 版本更新提示」全部失效。证书在 NPM 里配置。
### 其它静态托管
Netlify / Vercel 等平台,在 `dist/` 同级放一个 `_redirects` 或配置即可:
@@ -223,9 +265,38 @@ scripts/ # 图标生成等辅助脚本
.gitea/workflows/ # CI(lint / typecheck / test / build)
```
## 持续集成
## 持续集成与自动部署
仓库内置 `.gitea/workflows/ci.yml`:推送与合并请求会依次执行 `npm run lint`、`npm run typecheck`、`npm run test`、`npm run build`。
仓库内置 `.gitea/workflows/ci.yml`,分两个 job:
| Job | 触发条件 | 做什么 |
| -------- | ------------------------------------------ | --------------------------------------------------- |
| `verify` | push 与合并请求 | `npm ci` → `lint` → `typecheck` → `test` → `build` |
| `deploy` | push 到 `master` / `main` 且 `verify` 通过 | 重新构建 → `rsync` 到 `/opt/kanban/dist` → 线上自检 |
合并请求只跑校验、不部署。部署用 `rsync -a --delete` 原地同步,失败时旧文件仍在,不会把站点弄空;
同步完会自检根路径、`/today` 回落与 `sw.js`,任一异常就让 job 变红。
### Runner(自托管,已部署)
服务器 `132.232.203.88` 上的 `tencent-sh-1`,host 模式,systemd 常驻:
```bash
systemctl status gitea-runner
journalctl -u gitea-runner -n 50 --no-pager
```
配置见 `deploy/gitea-runner.config.yaml` 与 `deploy/gitea-runner.service`,几个要点:
- 标签 `ubuntu-latest:host`,任务直接在宿主机执行,不再套一层容器
- `DEFAULT_ACTIONS_URL=https://gitea.com` —— 这台机器访问 github.com 不通,action 必须换源
- 宿主机 Node 22 在 `/opt/node22`,软链到 `/usr/local/bin`;npm 源指向 `registry.npmmirror.com`
- runner 与站点同机,部署直接写本地目录,**不需要配置任何 Secrets**
### 为什么不用 SSH 部署
runner 与站点同一台机器,绕一圈 SSH 只是多一个故障点、多一份私钥要管。
真要跨机部署,用 `deploy/deploy.sh` 的 `SERVER=... WEB_ROOT=...` 形式即可。
E2E 需要真实浏览器,默认不放进 CI(要求 runner 预装 Chrome);请在本地或用带浏览器的 runner 执行 `npm run test:e2e`。