# Gitea Actions SSH 部署流程

当前推荐部署链路：

```text
push test/main
→ Gitea Actions 构建并推送 Docker 镜像
→ Actions 通过 SSH 登录目标服务器
→ 目标服务器 docker pull 指定镜像 tag
→ docker compose up -d --no-build
```

服务器不再依赖 Git remote 的 `post-receive` hook 拉取或构建镜像。

## 分支与环境

| 分支 | 环境 | 镜像 tag | 宿主机端口 | 默认服务器目录 | 容器名 |
| --- | --- | --- | --- | --- | --- |
| `test` | 测试环境 | `test-<short_sha>` | `9135` | `/opt/cozsweet-web-test` | `cozsweet-web-test` |
| `main` | 生产环境 | `prod-<short_sha>` | `9185` | `/opt/cozsweet-web-prod` | `cozsweet-web-prod` |

## Gitea Secrets

已有镜像构建 Secrets：

| Secret | 说明 |
| --- | --- |
| `REGISTRY_HOST` | Docker registry host，例如 `gitea.banlv-ai.com` |
| `REGISTRY_IMAGE` | 镜像仓库，例如 `gitea.banlv-ai.com/admin/cozsweet-web` |
| `REGISTRY_USERNAME` | registry 用户名 |
| `REGISTRY_PASSWORD` | registry 密码或 token |
| `REGISTRY_API_BASE_URL` | Gitea API 地址，例如 `https://gitea.banlv-ai.com/api/v1` |
| `REGISTRY_PACKAGE_TOKEN` | 具备 package 删除权限的 Gitea token，用于清理旧镜像 tag |
| `REGISTRY_PACKAGE_OWNER` / `REGISTRY_PACKAGE_NAME` | 可选；当 `REGISTRY_IMAGE` 不包含 owner/package 两段路径时，显式指定 Gitea package owner 和 name |
| `TEST_ENV_FILE` | 测试环境 `.env.local` 内容 |
| `PRODUCTION_ENV_FILE` | 生产环境 `.env.production` 内容 |

SSH 部署 Secrets：

| Secret | 说明 |
| --- | --- |
| `SSH_HOST` | 部署服务器地址，测试 / 生产共用 |
| `SSH_USER` | SSH 用户，例如 `root` |
| `SSH_PRIVATE_KEY` | 私钥内容 |
| `SSH_PORT` | 可选，默认 `22` |
| `SSH_KNOWN_HOSTS` | 可选，推荐配置 `ssh-keyscan` 输出 |
| `TEST_DEPLOY_DIR` / `PROD_DEPLOY_DIR` | 可选，覆盖默认服务器目录 |
| `CF_ZONE_ID` / `CF_API_TOKEN` | 可选，部署成功后清理 Cloudflare 缓存 |

## 服务器要求

目标服务器需要：

1. 安装 Docker，并支持 `docker compose` 或 `docker-compose`。
2. SSH 用户可执行 Docker 命令。
3. 能访问 Gitea registry。
4. 部署目录允许 SSH 用户写入。

workflow 会自动同步以下文件到服务器部署目录：

```text
docker-compose.yml
deploy-docker-image.sh
.env.local 或 .env.production
```

## 镜像保留策略

Actions 推送镜像后会清理 Gitea Container Registry，同一环境只保留最近 3 个精确版本 tag：

```text
test-<short_sha> 最近 3 个
prod-<short_sha> 最近 3 个
```

`test-latest` / `prod-latest` 不计入保留数量，也不会主动删除。

部署脚本会在 `docker compose up` 成功后清理服务器本机旧镜像，只保留当前环境正在运行的一个精确版本镜像：测试环境保留当前 `test-<short_sha>`，生产环境保留当前 `prod-<short_sha>`。

## 本地发布入口

本地发布脚本现在只负责推送 Gitea 分支，触发 Actions：

```bash
# 测试环境
./scripts/release/pre_release_web.sh

# 生产环境
./scripts/release/release_web.sh
```

也可以直接推送：

```bash
git push gitea test
git push --force gitea main
```

## 验证

测试环境：

```bash
ssh <user>@<test-host>
cd /opt/cozsweet-web-test
docker compose ps
curl -I http://127.0.0.1:9135/
```

生产环境：

```bash
ssh <user>@<prod-host>
cd /opt/cozsweet-web-prod
docker compose ps
curl -I http://127.0.0.1:9185/
```

## 旧 hook 处理

服务器上的 Git remote `post-receive` hook 属于旧部署链路。迁移完成并验证 Actions SSH 部署成功后，可以在服务器上禁用旧 hook，避免误触发：

```bash
mv /root/cozsweet-repos/test/.git/hooks/post-receive /root/cozsweet-repos/test/.git/hooks/post-receive.disabled
mv /root/cozsweet-repos/main/.git/hooks/post-receive /root/cozsweet-repos/main/.git/hooks/post-receive.disabled
```
