Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ec3e256a8c | |||
| 3547f49bd9 | |||
| ee6ab77f4d | |||
| ce3f0af82d | |||
| 638fc054b1 | |||
| 897bce11db | |||
| 1466cb01d2 | |||
| f6c75dcb86 | |||
| 187de82eaf | |||
| d372541925 | |||
| ef9b79bc83 | |||
| aee35353a3 | |||
| fcb2492118 | |||
| cab2ba868f | |||
| dab9e2e45a | |||
| 54ce485f41 | |||
| e36f94add3 | |||
| ca9cac21f1 | |||
| 662e5e67ea | |||
| f403c47052 | |||
| ac36837add | |||
| fe9d31146b | |||
| 01c55f5630 | |||
| b21ef2f6ec | |||
| a44fc4860e | |||
| ff2759cf0f | |||
| d746d04503 | |||
| 2a90b4d9ec | |||
| 9094bcbab0 | |||
| 29abd746da | |||
| 556bfd2919 | |||
| e3ef289b53 | |||
| 46588bd98c | |||
| 05f625dd0b | |||
| 3790fb813f | |||
| a55a59bff4 | |||
| d2a46ff6b9 | |||
| a4c4ca6666 |
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- pre
|
- test
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
DEPLOY_ENV="prod"
|
DEPLOY_ENV="prod"
|
||||||
NEXT_ENV_FILE=".env.production"
|
NEXT_ENV_FILE=".env.production"
|
||||||
;;
|
;;
|
||||||
pre)
|
test)
|
||||||
DEPLOY_ENV="test"
|
DEPLOY_ENV="test"
|
||||||
NEXT_ENV_FILE=".env.local"
|
NEXT_ENV_FILE=".env.local"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ copy_env_by_branch() {
|
|||||||
START_PORT=9185
|
START_PORT=9185
|
||||||
echo "=== env: copied .env.production (main → prod) ===" >> "$LOG_FILE"
|
echo "=== env: copied .env.production (main → prod) ===" >> "$LOG_FILE"
|
||||||
;;
|
;;
|
||||||
pre)
|
test)
|
||||||
cp -f env-example/.env.local.example .env.local
|
cp -f env-example/.env.local.example .env.local
|
||||||
ENV_FILE=".env.local"
|
ENV_FILE=".env.local"
|
||||||
DEPLOY_ENV="test"
|
DEPLOY_ENV="test"
|
||||||
START_PORT=9135
|
START_PORT=9135
|
||||||
echo "=== env: copied .env.local (pre branch → test runtime) ===" >> "$LOG_FILE"
|
echo "=== env: copied .env.local (test → test) ===" >> "$LOG_FILE"
|
||||||
;;
|
;;
|
||||||
dev)
|
dev)
|
||||||
cp -f env-example/.env.development.example .env.local
|
cp -f env-example/.env.development.example .env.local
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
| 环境 | Git remote | 推送分支 | 宿主机端口 | 容器端口 | 部署脚本 |
|
| 环境 | Git remote | 推送分支 | 宿主机端口 | 容器端口 | 部署脚本 |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 预发环境 | `test` | `pre` | `9135` | `3000` | `scripts/deploy/deploy_web_test.sh` |
|
| 测试环境 | `test` | `test` | `9135` | `3000` | `scripts/deploy/deploy_web_test.sh` |
|
||||||
| 生产环境 | `production` | `main` | `9185` | `3000` | `scripts/deploy/deploy_web.sh` |
|
| 生产环境 | `production` | `main` | `9185` | `3000` | `scripts/deploy/deploy_web.sh` |
|
||||||
|
|
||||||
当前 remote 配置示例:
|
当前 remote 配置示例:
|
||||||
@@ -26,15 +26,15 @@ production root@43.106.13.130:/root/cozsweet-repos/main
|
|||||||
|
|
||||||
## 本地发布流程
|
## 本地发布流程
|
||||||
|
|
||||||
旧预发环境发布流程(脚本迁移前):
|
旧测试环境发布流程(脚本迁移前):
|
||||||
|
|
||||||
1. 进入 pre worktree:`cozsweet-frontend-nextjs.worktrees/cozsweet-nextjs-pre`
|
1. 进入 test worktree:`cozsweet-frontend-nextjs.worktrees/cozsweet-nextjs-test`
|
||||||
2. 确认当前分支。
|
2. 确认当前分支。
|
||||||
3. 执行 `git rebase dev`,把 `dev` 的最新代码变基到 `pre` 分支。
|
3. 执行 `git rebase dev`,把 `dev` 的最新代码变基到 `test` 分支。
|
||||||
4. 复制测试环境图标到 `public/`。
|
4. 复制测试环境图标到 `public/`。
|
||||||
5. 复制 `env-example/.env.local.example` 到 `.env.local`。
|
5. 复制 `env-example/.env.local.example` 到 `.env.local`。
|
||||||
6. 执行旧版 `scripts/deploy/deploy_web_test.sh`。
|
6. 执行旧版 `scripts/deploy/deploy_web_test.sh`。
|
||||||
7. 旧版 `deploy_web_test.sh` 推送 `test` remote 的 `pre` 分支。
|
7. 旧版 `deploy_web_test.sh` 推送 `test` remote 的 `test` 分支。
|
||||||
8. 推送成功后尝试清除 Cloudflare CDN 缓存。
|
8. 推送成功后尝试清除 Cloudflare CDN 缓存。
|
||||||
|
|
||||||
旧生产环境发布流程(脚本迁移前):
|
旧生产环境发布流程(脚本迁移前):
|
||||||
@@ -71,7 +71,7 @@ production root@43.106.13.130:/root/cozsweet-repos/main
|
|||||||
| 服务端分支 | 环境变量复制 | 宿主机端口 | 容器名 | 镜像标签 |
|
| 服务端分支 | 环境变量复制 | 宿主机端口 | 容器名 | 镜像标签 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| `main` | `env-example/.env.production.example` → `.env.production` | `9185` | `cozsweet-web-prod` | `cozsweet-web:prod-<commit>` |
|
| `main` | `env-example/.env.production.example` → `.env.production` | `9185` | `cozsweet-web-prod` | `cozsweet-web:prod-<commit>` |
|
||||||
| `pre` | `env-example/.env.local.example` → `.env.local` | `9135` | `cozsweet-web-test` | `cozsweet-web:test-<commit>` |
|
| `test` | `env-example/.env.local.example` → `.env.local` | `9135` | `cozsweet-web-test` | `cozsweet-web:test-<commit>` |
|
||||||
| `dev` | `env-example/.env.development.example` → `.env.local` | `9135` | `cozsweet-web-dev` | `cozsweet-web:dev-<commit>` |
|
| `dev` | `env-example/.env.development.example` → `.env.local` | `9135` | `cozsweet-web-dev` | `cozsweet-web:dev-<commit>` |
|
||||||
| 其他分支 | 使用默认 `.env.local` | `9135` | `cozsweet-web-<branch>` | `cozsweet-web:<branch>-<commit>` |
|
| 其他分支 | 使用默认 `.env.local` | `9135` | `cozsweet-web-<branch>` | `cozsweet-web:<branch>-<commit>` |
|
||||||
|
|
||||||
@@ -264,12 +264,12 @@ ABORTED ... (docker compose up failed)
|
|||||||
|
|
||||||
1. `scripts/deploy/*` 只负责推送代码,不负责本地构建和本地启动。
|
1. `scripts/deploy/*` 只负责推送代码,不负责本地构建和本地启动。
|
||||||
2. 自动构建和自动重启只发生在服务器端 `post-receive` hook。
|
2. 自动构建和自动重启只发生在服务器端 `post-receive` hook。
|
||||||
3. `main` 分支对应生产环境,`pre` 分支对应预发环境。
|
3. `main` 分支对应生产环境,`test` 分支对应测试环境。
|
||||||
4. 生产推送当前使用 `git push --force production main`。
|
4. 生产推送当前使用 `git push --force production main`。
|
||||||
5. 构建失败时不会重启容器,旧容器继续运行。
|
5. 构建失败时不会重启容器,旧容器继续运行。
|
||||||
6. 服务启动由 Docker Compose 管理,不再使用 `nohup pnpm run start`。
|
6. 服务启动由 Docker Compose 管理,不再使用 `nohup pnpm run start`。
|
||||||
7. 服务器需要安装 Docker,并支持 `docker compose` 或旧版 `docker-compose` 命令。
|
7. 服务器需要安装 Docker,并支持 `docker compose` 或旧版 `docker-compose` 命令。
|
||||||
8. 预发环境和生产环境都通过同一套 `post-receive` 容器化流程部署,差异仅由分支、环境变量文件和端口决定。
|
8. 测试环境和生产环境都通过同一套 `post-receive` 容器化流程部署,差异仅由分支、环境变量文件和端口决定。
|
||||||
|
|
||||||
## 后续优化建议
|
## 后续优化建议
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
|
|
||||||
| Workflow | 触发时机 | 职责 |
|
| Workflow | 触发时机 | 职责 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `.gitea/workflows/ci.yml` | `dev`、`main`、`pre` push / PR | 安装依赖、执行完整质量检查、Python 后端 OpenAPI 差异检查、移动端 smoke,并校验 bundle 预算 |
|
| `.gitea/workflows/ci.yml` | `dev`、`main`、`test` push / PR | 安装依赖、执行完整质量检查、Python 后端 OpenAPI 差异检查、移动端 smoke,并校验 bundle 预算 |
|
||||||
| `.gitea/workflows/docker-image.yml` | `main`、`pre` push / 手动触发 | 构建 Docker 镜像、推送到镜像仓库,并通过 SSH 部署 |
|
| `.gitea/workflows/docker-image.yml` | `main`、`test` push / 手动触发 | 构建 Docker 镜像、推送到镜像仓库,并通过 SSH 部署 |
|
||||||
|
|
||||||
这样可以避免所有开发分支都发布镜像,并确保生产镜像通过发布门禁。
|
这样可以避免所有开发分支都发布镜像,并确保生产镜像通过发布门禁。
|
||||||
|
|
||||||
`main` 分支发布前会执行 Docker workflow 内的完整质量和 bundle 门禁。`pre`
|
`main` 分支发布前会执行 Docker workflow 内的完整质量和 bundle 门禁。`test`
|
||||||
分支用于快速部署预发环境,会跳过完整质量检查,但仍必须通过 bundle 预算;独立的
|
分支为快速部署测试环境,会跳过完整质量检查,但仍必须通过 bundle 预算;独立的
|
||||||
`ci.yml` 会同时执行完整检查并提供测试结果。
|
`ci.yml` 会同时执行完整检查并提供测试结果。
|
||||||
|
|
||||||
## 必需 Secrets
|
## 必需 Secrets
|
||||||
@@ -39,7 +39,7 @@ Next.js 的 `NEXT_PUBLIC_*` 会在构建期固化到产物中,因此测试环
|
|||||||
|
|
||||||
## 镜像 Tag 规则
|
## 镜像 Tag 规则
|
||||||
|
|
||||||
`pre` 分支发布时继续使用现有 `test-*` 运行镜像标签:
|
`test` 分支发布:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
REGISTRY_IMAGE:test-<short_sha>
|
REGISTRY_IMAGE:test-<short_sha>
|
||||||
@@ -81,7 +81,7 @@ volumes:
|
|||||||
|
|
||||||
## 验证方式
|
## 验证方式
|
||||||
|
|
||||||
推送到 `pre` 分支后,检查 Actions 日志中是否出现:
|
推送到 `test` 分支后,检查 Actions 日志中是否出现:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Build Docker image
|
Build Docker image
|
||||||
@@ -124,4 +124,4 @@ gitea.banlv-ai.com/admin/cozsweet-web:prod-<short_sha>
|
|||||||
- `prod-*` 精确 tag 只保留最近 3 个,`prod-latest` 不计入也不删除。
|
- `prod-*` 精确 tag 只保留最近 3 个,`prod-latest` 不计入也不删除。
|
||||||
- 当前刚推送的 `IMAGE_VERSION_TAG` 永远不会被删除。
|
- 当前刚推送的 `IMAGE_VERSION_TAG` 永远不会被删除。
|
||||||
|
|
||||||
SSH 部署成功后,服务器本机只保留当前环境正在运行的一个精确版本镜像;预发环境清理旧 `test-*`,生产环境清理旧 `prod-*`。
|
SSH 部署成功后,服务器本机只保留当前环境正在运行的一个精确版本镜像;测试环境清理旧 `test-*`,生产环境清理旧 `prod-*`。
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
当前推荐部署链路:
|
当前推荐部署链路:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
push pre/main
|
push test/main
|
||||||
→ Gitea Actions 构建并推送 Docker 镜像
|
→ Gitea Actions 构建并推送 Docker 镜像
|
||||||
→ Actions 通过 SSH 登录目标服务器
|
→ Actions 通过 SSH 登录目标服务器
|
||||||
→ 目标服务器 docker pull 指定镜像 tag
|
→ 目标服务器 docker pull 指定镜像 tag
|
||||||
@@ -16,7 +16,7 @@ push pre/main
|
|||||||
|
|
||||||
| 分支 | 环境 | 镜像 tag | 宿主机端口 | 默认服务器目录 | 容器名 |
|
| 分支 | 环境 | 镜像 tag | 宿主机端口 | 默认服务器目录 | 容器名 |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| `pre` | 预发环境 | `test-<short_sha>` | `9135` | `/opt/cozsweet-web-test` | `cozsweet-web-test` |
|
| `test` | 测试环境 | `test-<short_sha>` | `9135` | `/opt/cozsweet-web-test` | `cozsweet-web-test` |
|
||||||
| `main` | 生产环境 | `prod-<short_sha>` | `9185` | `/opt/cozsweet-web-prod` | `cozsweet-web-prod` |
|
| `main` | 生产环境 | `prod-<short_sha>` | `9185` | `/opt/cozsweet-web-prod` | `cozsweet-web-prod` |
|
||||||
|
|
||||||
## Gitea Secrets
|
## Gitea Secrets
|
||||||
@@ -75,14 +75,14 @@ prod-<short_sha> 最近 3 个
|
|||||||
|
|
||||||
`test-latest` / `prod-latest` 不计入保留数量,也不会主动删除。
|
`test-latest` / `prod-latest` 不计入保留数量,也不会主动删除。
|
||||||
|
|
||||||
部署脚本会在 `docker compose up` 成功后清理服务器本机旧镜像,只保留当前环境正在运行的一个精确版本镜像:预发环境保留当前 `test-<short_sha>`,生产环境保留当前 `prod-<short_sha>`。
|
部署脚本会在 `docker compose up` 成功后清理服务器本机旧镜像,只保留当前环境正在运行的一个精确版本镜像:测试环境保留当前 `test-<short_sha>`,生产环境保留当前 `prod-<short_sha>`。
|
||||||
|
|
||||||
## 本地发布入口
|
## 本地发布入口
|
||||||
|
|
||||||
本地发布脚本现在只负责推送 Gitea 分支,触发 Actions:
|
本地发布脚本现在只负责推送 Gitea 分支,触发 Actions:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 预发环境
|
# 测试环境
|
||||||
./scripts/release/pre_release_web.sh
|
./scripts/release/pre_release_web.sh
|
||||||
|
|
||||||
# 生产环境
|
# 生产环境
|
||||||
@@ -92,16 +92,16 @@ prod-<short_sha> 最近 3 个
|
|||||||
也可以直接推送:
|
也可以直接推送:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git push gitea pre
|
git push gitea test
|
||||||
git push --force gitea main
|
git push --force gitea main
|
||||||
```
|
```
|
||||||
|
|
||||||
## 验证
|
## 验证
|
||||||
|
|
||||||
预发环境:
|
测试环境:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh <user>@<pre-host>
|
ssh <user>@<test-host>
|
||||||
cd /opt/cozsweet-web-test
|
cd /opt/cozsweet-web-test
|
||||||
docker compose ps
|
docker compose ps
|
||||||
curl -I http://127.0.0.1:9135/
|
curl -I http://127.0.0.1:9135/
|
||||||
|
|||||||
+2
-2
@@ -27,8 +27,8 @@ pnpm exec playwright install chromium
|
|||||||
For local development on macOS, `pnpm test:e2e:chrome` can reuse the installed Google Chrome.
|
For local development on macOS, `pnpm test:e2e:chrome` can reuse the installed Google Chrome.
|
||||||
|
|
||||||
`pnpm test:e2e:mobile-smoke` runs the critical authentication, logout, token
|
`pnpm test:e2e:mobile-smoke` runs the critical authentication, logout, token
|
||||||
refresh and paid-image unlock paths with the Pixel 7 profile. CI 在所有 pull
|
refresh and paid-image unlock paths with the Pixel 7 profile. CI runs this tier
|
||||||
request 以及 `dev` / `pre` / `main` push 时运行这一层测试。
|
on every pull request and `dev` / `test` / `main` push.
|
||||||
|
|
||||||
## Environment overrides
|
## Environment overrides
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# 推送指定分支到指定远端。
|
# 推送指定分支到指定远端。
|
||||||
# 当前发布由 Gitea Actions 构建镜像并通过 SSH 部署;本脚本只负责触发分支 push。
|
# 当前发布由 Gitea Actions 构建镜像并通过 SSH 部署;本脚本只负责触发分支 push。
|
||||||
# 调用方:deploy_web.sh(production)→ push_to_remote "gitea" "main"
|
# 调用方:deploy_web.sh(production)→ push_to_remote "gitea" "main"
|
||||||
# deploy_web_test.sh(pre)→ push_to_remote "gitea" "pre"
|
# deploy_web_test.sh(test)→ push_to_remote "gitea" "test"
|
||||||
push_to_remote() {
|
push_to_remote() {
|
||||||
local remote="$1"
|
local remote="$1"
|
||||||
local branch="$2"
|
local branch="$2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# 预发环境 Web 部署脚本(Next.js + Gitea Actions SSH 部署模型)
|
# 测试环境 Web 部署脚本(Next.js + Gitea Actions SSH 部署模型)
|
||||||
# 原始 Dart: scripts/deploy/deploy_web_test.sh
|
# 原始 Dart: scripts/deploy/deploy_web_test.sh
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ source "$SCRIPT_DIR/_deploy_lib.sh"
|
|||||||
|
|
||||||
# 主函数
|
# 主函数
|
||||||
main() {
|
main() {
|
||||||
push_to_remote "gitea" "pre"
|
push_to_remote "gitea" "test"
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ unset_git_hook_env() {
|
|||||||
|
|
||||||
unset_git_hook_env
|
unset_git_hook_env
|
||||||
|
|
||||||
# pre 分支 worktree 路径
|
# Test 分支 worktree 路径
|
||||||
WORKTREE_PATH="/Users/chase/Documents/frontend/cozsweet-frontend-nextjs.worktrees/cozsweet-nextjs-pre"
|
WORKTREE_PATH="/Users/chase/Documents/frontend/cozsweet-frontend-nextjs.worktrees/cozsweet-nextjs-test"
|
||||||
echo "=== 进入 pre 分支 worktree ==="
|
echo "=== 进入 test 分支 worktree ==="
|
||||||
cd "$WORKTREE_PATH" || { echo "错误: 无法进入 $WORKTREE_PATH"; exit 1; }
|
cd "$WORKTREE_PATH" || { echo "错误: 无法进入 $WORKTREE_PATH"; exit 1; }
|
||||||
|
|
||||||
echo "=== 检查当前分支 ==="
|
echo "=== 检查当前分支 ==="
|
||||||
@@ -22,17 +22,17 @@ git branch --show-current
|
|||||||
echo "=== 变基到 dev 分支 ==="
|
echo "=== 变基到 dev 分支 ==="
|
||||||
git rebase dev
|
git rebase dev
|
||||||
|
|
||||||
# 复制预发环境图标(运行资源目录仍为 icons/test)
|
# 复制测试环境图标(source: $WORKTREE_PATH/icons/test → dest: $WORKTREE_PATH/public/)
|
||||||
echo "=== 复制预发环境图标(icons/test → public/) ==="
|
echo "=== 复制测试环境图标(icons/test → public/) ==="
|
||||||
cp -f "$WORKTREE_PATH/icons/test/favicon.ico" "$WORKTREE_PATH/public/favicon.ico"
|
cp -f "$WORKTREE_PATH/icons/test/favicon.ico" "$WORKTREE_PATH/public/favicon.ico"
|
||||||
cp -f "$WORKTREE_PATH/icons/test/icons/Icon-192.png" "$WORKTREE_PATH/public/images/icons/Icon-192.png"
|
cp -f "$WORKTREE_PATH/icons/test/icons/Icon-192.png" "$WORKTREE_PATH/public/images/icons/Icon-192.png"
|
||||||
cp -f "$WORKTREE_PATH/icons/test/icons/Icon-512.png" "$WORKTREE_PATH/public/images/icons/Icon-512.png"
|
cp -f "$WORKTREE_PATH/icons/test/icons/Icon-512.png" "$WORKTREE_PATH/public/images/icons/Icon-512.png"
|
||||||
|
|
||||||
# 准备预发环境变量(运行配置仍使用 .env.local)
|
# 准备测试环境变量($WORKTREE_PATH/env-example/.env.local.example → $WORKTREE_PATH/.env.local)
|
||||||
echo "=== 准备预发环境变量(env-example/.env.local.example → .env.local) ==="
|
echo "=== 准备测试环境变量(env-example/.env.local.example → .env.local) ==="
|
||||||
cp -f "$WORKTREE_PATH/env-example/.env.local.example" "$WORKTREE_PATH/.env.local"
|
cp -f "$WORKTREE_PATH/env-example/.env.local.example" "$WORKTREE_PATH/.env.local"
|
||||||
|
|
||||||
echo "=== 执行构建部署脚本(预发环境)==="
|
echo "=== 执行构建部署脚本(测试环境)==="
|
||||||
./scripts/deploy/deploy_web_test.sh
|
./scripts/deploy/deploy_web_test.sh
|
||||||
|
|
||||||
echo "=== 预发布完成 ==="
|
echo "=== 预发布完成 ==="
|
||||||
|
|||||||
Reference in New Issue
Block a user