Files
sub2api/CLAUDE.md
liuxiongfeng 9375f1809c docs: 部署步骤增加前置检查和验证环节
- 各步骤增加检查点说明,确保每步执行成功后再继续
- 步骤 0 强调推送成功确认和未提交改动检查
- 步骤 1 增加版本号验证
- 步骤 2 增加常见构建问题排查(buildx 版本、磁盘空间)
- 步骤 4 增加生产服务器代码同步步骤
- 新增「构建服务器首次初始化」章节
2026-02-11 00:34:48 +08:00

25 KiB
Raw Blame History

Sub2API 开发说明

版本管理策略

版本号规则

我们在官方版本号后面添加自己的小版本号:

  • 官方版本:v0.1.68
  • 我们的版本:v0.1.68.1v0.1.68.2(递增)

分支策略

分支 说明
main 我们的主分支,包含所有定制功能
release/custom-X.Y.Z 基于官方 vX.Y.Z 的发布分支
upstream/main 上游官方仓库

发布流程(基于新官方版本)

当官方发布新版本(如 v0.1.69)时:

1. 同步上游并创建发布分支

# 获取上游最新代码
git fetch upstream --tags

# 基于官方标签创建新的发布分支
git checkout v0.1.69 -b release/custom-0.1.69

# 合并我们的 main 分支(包含所有定制功能)
git merge main --no-edit

# 解决可能的冲突后继续

2. 更新版本号并打标签

# 更新版本号文件
echo "0.1.69.1" > backend/cmd/server/VERSION
git add backend/cmd/server/VERSION
git commit -m "chore: bump version to 0.1.69.1"

# 打上我们自己的标签
git tag v0.1.69.1

# 推送分支和标签
git push origin release/custom-0.1.69
git push origin v0.1.69.1

3. 更新 main 分支

# 将发布分支合并回 main保持 main 包含最新定制功能
git checkout main
git merge release/custom-0.1.69
git push origin main

热修复发布(在现有版本上修复)

当需要在当前版本上发布修复时:

# 在当前发布分支上修复
git checkout release/custom-0.1.68
# ... 进行修复 ...
git commit -m "fix: 修复描述"

# 递增小版本号
echo "0.1.68.2" > backend/cmd/server/VERSION
git add backend/cmd/server/VERSION
git commit -m "chore: bump version to 0.1.68.2"

# 打标签并推送
git tag v0.1.68.2
git push origin release/custom-0.1.68
git push origin v0.1.68.2

# 同步修复到 main
git checkout main
git cherry-pick <fix-commit-hash>
git push origin main

服务器部署流程

前置条件

  • 本地已配置 SSH 别名 clicodeplus 连接到生产服务器(运行服务)
  • 本地已配置 SSH 别名 us-asaki-root 连接到构建服务器(拉取代码、构建镜像)
  • 生产服务器部署目录:/root/sub2api(正式)、/root/sub2api-beta(测试)
  • 生产服务器使用 Docker Compose 部署
  • 镜像统一在构建服务器上构建,避免生产服务器因编译占用 CPU/内存影响线上服务

服务器角色说明

服务器 SSH 别名 职责
构建服务器 us-asaki-root 拉取代码、docker build 构建镜像
生产服务器 clicodeplus 加载镜像、运行服务、部署验证

部署环境说明

环境 目录(生产服务器) 端口 数据库 容器名
正式 /root/sub2api 8080 sub2api sub2api
Beta /root/sub2api-beta 8084 beta sub2api-beta

外部数据库

正式和 Beta 环境共用外部 PostgreSQL 数据库(非容器内数据库),配置在 .env 文件中:

  • DATABASE_HOST:外部数据库地址
  • DATABASE_SSLMODESSL 模式(通常为 require
  • POSTGRES_USER / POSTGRES_DB:用户名和数据库名

数据库操作命令

通过 SSH 在服务器上执行数据库操作:

# 正式环境 - 查询迁移记录
ssh clicodeplus "source /root/sub2api/deploy/.env && PGPASSWORD=\"\$POSTGRES_PASSWORD\" psql -h \$DATABASE_HOST -U \$POSTGRES_USER -d \$POSTGRES_DB -c 'SELECT * FROM schema_migrations ORDER BY applied_at DESC LIMIT 5;'"

# Beta 环境 - 查询迁移记录
ssh clicodeplus "source /root/sub2api-beta/deploy/.env && PGPASSWORD=\"\$POSTGRES_PASSWORD\" psql -h \$DATABASE_HOST -U \$POSTGRES_USER -d \$POSTGRES_DB -c 'SELECT * FROM schema_migrations ORDER BY applied_at DESC LIMIT 5;'"

# Beta 环境 - 清除指定迁移记录(重新执行迁移)
ssh clicodeplus "source /root/sub2api-beta/deploy/.env && PGPASSWORD=\"\$POSTGRES_PASSWORD\" psql -h \$DATABASE_HOST -U \$POSTGRES_USER -d \$POSTGRES_DB -c \"DELETE FROM schema_migrations WHERE filename LIKE '%049%';\""

# Beta 环境 - 更新账号数据
ssh clicodeplus "source /root/sub2api-beta/deploy/.env && PGPASSWORD=\"\$POSTGRES_PASSWORD\" psql -h \$DATABASE_HOST -U \$POSTGRES_USER -d \$POSTGRES_DB -c \"UPDATE accounts SET credentials = credentials - 'model_mapping' WHERE platform = 'antigravity';\""

注意:使用 source .env 加载环境变量,避免在命令行中暴露密码。

部署步骤

重要:每次部署都必须递增版本号!

0. 递增版本号并推送(本地操作)

每次部署前,先在本地递增小版本号并确保推送成功:

# 查看当前版本号
cat backend/cmd/server/VERSION
# 假设当前是 0.1.69.1

# 递增版本号
echo "0.1.69.2" > backend/cmd/server/VERSION
git add backend/cmd/server/VERSION
git commit -m "chore: bump version to 0.1.69.2"
git push origin release/custom-0.1.69

# ⚠️ 确认推送成功(必须看到分支更新输出,不能有 rejected 错误)

检查点:如果有其他未提交的改动,应先 commit 并 push确保 release 分支上的所有代码都已推送到远程。

1. 构建服务器拉取代码

# 拉取最新代码并切换分支
ssh us-asaki-root "cd /root/sub2api && git fetch origin && git checkout -B release/custom-0.1.69 origin/release/custom-0.1.69"

# ⚠️ 验证版本号与步骤 0 一致
ssh us-asaki-root "cat /root/sub2api/backend/cmd/server/VERSION"

首次使用构建服务器? 需要先初始化仓库,参见下方「构建服务器首次初始化」章节。

2. 构建服务器构建镜像

ssh us-asaki-root "cd /root/sub2api && docker build --no-cache -t sub2api:latest -f Dockerfile ."

# ⚠️ 必须看到构建成功输出,如果失败需要先排查问题

常见构建问题

  • buildx 版本过旧导致 API 版本不兼容 → 更新 buildxcurl -fsSL "https://github.com/docker/buildx/releases/latest/download/buildx-$(curl -fsSL https://api.github.com/repos/docker/buildx/releases/latest | grep tag_name | cut -d'"' -f4).linux-amd64" -o ~/.docker/cli-plugins/docker-buildx && chmod +x ~/.docker/cli-plugins/docker-buildx
  • 磁盘空间不足 → docker system prune -f 清理无用镜像

3. 传输镜像到生产服务器并加载

# 导出镜像 → 通过管道传输 → 生产服务器加载
ssh us-asaki-root "docker save sub2api:latest" | ssh clicodeplus "docker load"

# ⚠️ 必须看到 "Loaded image: sub2api:latest" 输出

4. 生产服务器同步代码、更新标签并重启

# 同步代码(用于版本号确认和 deploy 配置)
ssh clicodeplus "cd /root/sub2api && git fetch fork && git checkout -B release/custom-0.1.69 fork/release/custom-0.1.69"

# 更新镜像标签并重启
ssh clicodeplus "docker tag sub2api:latest weishaw/sub2api:latest"
ssh clicodeplus "cd /root/sub2api/deploy && docker compose up -d --force-recreate sub2api"

5. 验证部署

# 查看启动日志
ssh clicodeplus "docker logs sub2api --tail 20"

# 确认版本号(必须与步骤 0 中设置的版本号一致)
ssh clicodeplus "cat /root/sub2api/backend/cmd/server/VERSION"

# 检查容器状态(必须显示 healthy
ssh clicodeplus "docker ps | grep sub2api"

构建服务器首次初始化

首次使用 us-asaki-root 作为构建服务器时,需要执行以下一次性操作:

ssh us-asaki-root

# 1) 克隆仓库
cd /root
git clone https://github.com/touwaeriol/sub2api.git sub2api
cd sub2api

# 2) 验证 Docker 和 buildx 版本
docker version
docker buildx version
# 如果 buildx 版本过旧(< v0.14),执行更新:
# LATEST=$(curl -fsSL https://api.github.com/repos/docker/buildx/releases/latest | grep tag_name | cut -d'"' -f4)
# curl -fsSL "https://github.com/docker/buildx/releases/download/${LATEST}/buildx-${LATEST}.linux-amd64" -o ~/.docker/cli-plugins/docker-buildx
# chmod +x ~/.docker/cli-plugins/docker-buildx

# 3) 验证构建能力
docker build --no-cache -t sub2api:test -f Dockerfile .
docker rmi sub2api:test

Beta 并行部署(不影响现网)

目标:在同一台服务器上并行启动一个 beta 实例(例如端口 8084严禁改动/重启现网实例(默认目录 /root/sub2api)。

设计原则

  • 新目录beta 使用独立目录,例如 /root/sub2api-beta
  • 敏感信息只放 .envbeta 的数据库密码、JWT_SECRET 等只写入 /root/sub2api-beta/deploy/.env,不要提交到 git。
  • 独立 Compose Project:通过 docker compose -p sub2api-beta ... 启动,确保 network/volume 隔离。
  • 独立端口:通过 .envSERVER_PORT 映射宿主机端口(例如 8084:8080)。

前置检查

# 1) 确保 8084 未被占用
ssh clicodeplus "ss -ltnp | grep :8084 || echo '8084 is free'"

# 2) 确认现网容器还在(只读检查)
ssh clicodeplus "docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}' | sed -n '1,200p'"

首次部署步骤

# 0) 进入构建服务器
ssh us-asaki-root

# 1) 克隆代码到新目录(示例使用你的 fork
cd /root
git clone https://github.com/touwaeriol/sub2api.git sub2api-beta
cd /root/sub2api-beta
git checkout release/custom-0.1.71

# 2) 构建 beta 镜像
docker build -t sub2api:beta -f Dockerfile .
exit

# 3) 传输镜像到生产服务器
ssh us-asaki-root "docker save sub2api:beta" | ssh clicodeplus "docker load"

# 4) 在生产服务器上准备 beta 环境
ssh clicodeplus

# 克隆代码(仅用于 deploy 配置和版本号确认,不在此构建)
cd /root
git clone https://github.com/touwaeriol/sub2api.git sub2api-beta
cd /root/sub2api-beta
git checkout release/custom-0.1.71

# 5) 准备 beta 的 .env敏感信息只写这里
cd /root/sub2api-beta/deploy

# 推荐:从现网 .env 复制,保证除 DB 名/用户/端口外完全一致
cp -f /root/sub2api/deploy/.env ./.env

# 仅修改以下三项(其他保持不变)
perl -pi -e 's/^SERVER_PORT=.*/SERVER_PORT=8084/' ./.env
perl -pi -e 's/^POSTGRES_USER=.*/POSTGRES_USER=beta/' ./.env
perl -pi -e 's/^POSTGRES_DB=.*/POSTGRES_DB=beta/' ./.env

# 6) 写 compose override避免与现网容器名冲突镜像使用构建服务器传输的 sub2api:beta
cat > docker-compose.override.yml <<'YAML'
services:
  sub2api:
    image: sub2api:beta
    container_name: sub2api-beta
  redis:
    container_name: sub2api-beta-redis
YAML

# 7) 启动 beta独立 project确保不影响现网
cd /root/sub2api-beta/deploy
docker compose -p sub2api-beta --env-file .env -f docker-compose.yml -f docker-compose.override.yml up -d

# 8) 验证 beta
curl -fsS http://127.0.0.1:8084/health
docker logs sub2api-beta --tail 50

数据库配置约定beta

  • 数据库地址/SSL/密码:与现网一致(从现网 .env 复制即可)。
  • 仅修改:
    • POSTGRES_USER=beta
    • POSTGRES_DB=beta

注意:需要数据库侧已存在 beta 用户与 beta 数据库,并授予权限;否则容器会启动失败并不断重启。

更新 beta构建服务器构建 + 传输 + 仅重启 beta 容器)

# 1) 构建服务器拉取代码并构建镜像
ssh us-asaki-root "set -e; cd /root/sub2api-beta && git fetch --all --tags && git checkout -f release/custom-0.1.71 && git reset --hard origin/release/custom-0.1.71"
ssh us-asaki-root "cd /root/sub2api-beta && docker build -t sub2api:beta -f Dockerfile ."

# 2) 传输镜像到生产服务器
ssh us-asaki-root "docker save sub2api:beta" | ssh clicodeplus "docker load"

# 3) 生产服务器同步代码(用于版本号确认和 deploy 配置)
ssh clicodeplus "set -e; cd /root/sub2api-beta && git fetch --all --tags && git checkout -f release/custom-0.1.71 && git reset --hard origin/release/custom-0.1.71"

# 4) 重启 beta 容器
ssh clicodeplus "cd /root/sub2api-beta/deploy && docker compose -p sub2api-beta --env-file .env -f docker-compose.yml -f docker-compose.override.yml up -d --no-deps --force-recreate sub2api"
ssh clicodeplus "curl -fsS http://127.0.0.1:8084/health"

停止/回滚 beta只影响 beta

ssh clicodeplus "cd /root/sub2api-beta/deploy && docker compose -p sub2api-beta -f docker-compose.yml -f docker-compose.override.yml down"

服务器首次部署

1. 构建服务器:克隆代码并配置远程仓库

ssh us-asaki-root
cd /root
git clone https://github.com/Wei-Shaw/sub2api.git
cd sub2api

# 添加 fork 仓库
git remote add fork https://github.com/touwaeriol/sub2api.git

2. 构建服务器:切换到定制分支并构建镜像

git fetch fork
git checkout -B release/custom-0.1.69 fork/release/custom-0.1.69

cd /root/sub2api
docker build -t sub2api:latest -f Dockerfile .
exit

3. 传输镜像到生产服务器

ssh us-asaki-root "docker save sub2api:latest" | ssh clicodeplus "docker load"

4. 生产服务器:克隆代码并配置环境

ssh clicodeplus
cd /root
git clone https://github.com/Wei-Shaw/sub2api.git
cd sub2api

# 添加 fork 仓库
git remote add fork https://github.com/touwaeriol/sub2api.git
git fetch fork
git checkout -B release/custom-0.1.69 fork/release/custom-0.1.69

# 配置环境变量
cd deploy
cp .env.example .env
vim .env  # 配置 DATABASE_URL, REDIS_URL, JWT_SECRET 等

5. 生产服务器:更新镜像标签并启动服务

docker tag sub2api:latest weishaw/sub2api:latest
cd /root/sub2api/deploy && docker compose up -d

6. 验证部署

# 查看应用日志
docker logs sub2api --tail 50

# 检查健康状态
curl http://localhost:8080/health

# 确认版本号
cat /root/sub2api/backend/cmd/server/VERSION

7. 常用运维命令

# 查看实时日志
docker logs -f sub2api

# 重启服务
docker compose restart sub2api

# 停止所有服务
docker compose down

# 停止并删除数据卷(慎用!会删除数据库数据)
docker compose down -v

# 查看资源使用情况
docker stats sub2api

定制功能说明

当前定制分支包含以下功能(相对于官方版本):

UI/UX 定制

功能 说明
首页优化 面向用户的价值主张设计
移除 GitHub 链接 用户菜单中不显示 GitHub 导航
微信客服按钮 首页悬浮微信客服入口
限流时间精确显示 账号限流时间显示精确到秒

Antigravity 平台增强

功能 说明
Scope 级别限流 按配额域claude/gemini_text/gemini_image独立限流避免整个账号被锁定
模型级别限流 按具体模型(如 claude-opus-4-5独立限流更精细的限流控制
限流预检查 调度时预检查账号/模型限流状态,避免选中已限流账号
秒级冷却时间 支持 429 响应的秒级精确冷却时间
身份注入优化 模型身份信息注入 + 静默边界防止身份泄露
thoughtSignature 修复 Gemini 3 函数调用 400 错误修复
max_tokens 自动修正 自动修正 max_tokens <= budget_tokens 导致的 400 错误

调度算法优化

功能 说明
分层过滤选择 调度算法从全排序改为分层过滤,提升性能
LRU 随机选择 相同 LRU 时间时随机选择,避免账号集中
限流等待阈值配置化 可配置的限流等待阈值

运维增强

功能 说明
Scope 限流统计 运维界面展示 Antigravity 账号 scope 级别限流统计
账号限流状态显示 账号列表显示 scope 和模型级别限流状态
清除限流按钮增强 有 scope/模型限流时也显示清除限流按钮

其他修复

功能 说明
.gitattributes 确保迁移文件使用 LF 换行符(解决 Windows 下 SQL 摘要不一致)
部署配置优化 DATABASE_HOST 和 DATABASE_SSLMODE 可通过 .env 配置

注意事项

  1. 前端必须打包进镜像:使用 docker build 在构建服务器(us-asaki-root上构建Dockerfile 会自动编译前端并 embed 到后端二进制中,构建完成后通过 docker save | docker load 传输到生产服务器(clicodeplus

  2. 镜像标签docker-compose.yml 使用 weishaw/sub2api:latest,本地构建后需要 docker tag 覆盖

  3. Windows 换行符问题:已通过 .gitattributes 解决,确保 *.sql 文件始终使用 LF

  4. 版本号管理:每次发布必须更新 backend/cmd/server/VERSION 并打标签

  5. 合并冲突:合并上游新版本时,重点关注以下文件可能的冲突:

    • backend/internal/service/antigravity_gateway_service.go
    • backend/internal/service/gateway_service.go
    • backend/internal/pkg/antigravity/request_transformer.go

Go 代码规范

1. 函数设计

单一职责原则

  • 函数行数:单个函数常规不应超过 30 行,超过时应拆分为子函数。若某段逻辑确实不可拆分(如复杂的状态机、协议解析等),可以例外,但需添加注释说明原因
  • 嵌套层级:避免超过 3 层嵌套,使用 early return 减少嵌套
// ❌ 不推荐:深层嵌套
func process(data []Item) {
    for _, item := range data {
        if item.Valid {
            if item.Type == "A" {
                if item.Status == "active" {
                    // 业务逻辑...
                }
            }
        }
    }
}

// ✅ 推荐early return
func process(data []Item) {
    for _, item := range data {
        if !item.Valid {
            continue
        }
        if item.Type != "A" {
            continue
        }
        if item.Status != "active" {
            continue
        }
        // 业务逻辑...
    }
}

复杂逻辑提取

将复杂的条件判断或处理逻辑提取为独立函数:

// ❌ 不推荐:内联复杂逻辑
if resp.StatusCode == 429 || resp.StatusCode == 503 {
    // 80+ 行处理逻辑...
}

// ✅ 推荐:提取为独立函数
result := handleRateLimitResponse(resp, params)
switch result.action {
case actionRetry:
    continue
case actionBreak:
    return result.resp, nil
}

2. 重复代码消除

配置获取模式

将重复的配置获取逻辑提取为方法:

// ❌ 不推荐:重复代码
logBody := s.settingService != nil && s.settingService.cfg != nil && s.settingService.cfg.Gateway.LogUpstreamErrorBody
maxBytes := 2048
if s.settingService != nil && s.settingService.cfg != nil && s.settingService.cfg.Gateway.LogUpstreamErrorBodyMaxBytes > 0 {
    maxBytes = s.settingService.cfg.Gateway.LogUpstreamErrorBodyMaxBytes
}

// ✅ 推荐:提取为方法
func (s *Service) getLogConfig() (logBody bool, maxBytes int) {
    maxBytes = 2048
    if s.settingService == nil || s.settingService.cfg == nil {
        return false, maxBytes
    }
    cfg := s.settingService.cfg.Gateway
    if cfg.LogUpstreamErrorBodyMaxBytes > 0 {
        maxBytes = cfg.LogUpstreamErrorBodyMaxBytes
    }
    return cfg.LogUpstreamErrorBody, maxBytes
}

3. 常量管理

避免魔法数字

所有硬编码的数值都应定义为常量:

// ❌ 不推荐
if retryDelay >= 10*time.Second {
    resetAt := time.Now().Add(30 * time.Second)
}

// ✅ 推荐
const (
    rateLimitThreshold       = 10 * time.Second
    defaultRateLimitDuration = 30 * time.Second
)

if retryDelay >= rateLimitThreshold {
    resetAt := time.Now().Add(defaultRateLimitDuration)
}

注释引用常量名

在注释中引用常量名而非硬编码值:

// ❌ 不推荐
// < 10s: 等待后重试

// ✅ 推荐
// < rateLimitThreshold: 等待后重试

4. 错误处理

使用结构化日志

优先使用 slog 进行结构化日志记录:

// ❌ 不推荐
log.Printf("%s status=%d model_rate_limit_failed model=%s error=%v", prefix, statusCode, modelName, err)

// ✅ 推荐
slog.Error("failed to set model rate limit",
    "prefix", prefix,
    "status_code", statusCode,
    "model", modelName,
    "error", err,
)

5. 测试规范

Mock 函数签名同步

修改函数签名时,必须同步更新所有测试中的 mock 函数:

// 如果修改了 handleError 签名
handleError func(..., groupID int64, sessionHash string) *Result

// 必须同步更新测试中的 mock
handleError: func(..., groupID int64, sessionHash string) *Result {
    return nil
},

测试构建标签

统一使用测试构建标签:

//go:build unit

package service

6. 时间格式解析

使用标准库

优先使用 time.ParseDuration,支持所有 Go duration 格式:

// ❌ 不推荐:手动限制格式
if !strings.HasSuffix(delay, "s") || strings.Contains(delay, "m") {
    continue
}

// ✅ 推荐:使用标准库
dur, err := time.ParseDuration(delay) // 支持 "0.5s", "4m50s", "1h30m" 等

7. 接口设计

接口隔离原则

定义最小化接口,只包含必需的方法:

// ❌ 不推荐:使用过于宽泛的接口
type AccountRepository interface {
    // 20+ 个方法...
}

// ✅ 推荐:定义最小化接口
type ModelRateLimiter interface {
    SetModelRateLimit(ctx context.Context, id int64, modelKey string, resetAt time.Time) error
}

8. 并发安全

共享数据保护

访问可能被并发修改的数据时,确保线程安全:

// 如果 Account.Extra 可能被并发修改
// 需要使用互斥锁或原子操作保护读取
func (a *Account) GetRateLimitRemainingTime(model string) time.Duration {
    a.mu.RLock()
    defer a.mu.RUnlock()
    // 读取 Extra 字段...
}

9. 命名规范

一致的命名风格

  • 常量使用 camelCaserateLimitThreshold
  • 类型使用 PascalCaseAntigravityQuotaScope
  • 同一概念使用统一命名:ThresholdLimit,不要混用
// ❌ 不推荐:命名不一致
antigravitySmartRetryMinWait    // 使用 Min
antigravityRateLimitThreshold   // 使用 Threshold

// ✅ 推荐:统一风格
antigravityMinRetryWait
antigravityRateLimitThreshold

10. 代码审查清单

在提交代码前,检查以下项目:

  • 函数是否超过 30 行?(不可拆分的逻辑除外,需注释说明)
  • 嵌套是否超过 3 层?
  • 是否有重复代码可以提取?
  • 是否使用了魔法数字?
  • Mock 函数签名是否与实际函数一致?
  • 测试是否覆盖了新增逻辑?
  • 日志是否包含足够的上下文信息?
  • 是否考虑了并发安全?

CI 检查与发布门禁

GitHub Actions 检查项

本项目有 4 个 CI 任务,任何代码推送或发布前都必须全部通过

Workflow Job 说明 本地验证命令
CI test 单元测试 + 集成测试 cd backend && make test-unit && make test-integration
CI golangci-lint Go 代码静态检查golangci-lint v2.7 cd backend && golangci-lint run --timeout=5m
Security Scan backend-security govulncheck + gosec 安全扫描 cd backend && govulncheck ./... && gosec -severity high -confidence high ./...
Security Scan frontend-security pnpm audit 前端依赖安全检查 cd frontend && pnpm audit --prod --audit-level=high

向上游提交 PR

PR 目标是上游官方仓库,只包含通用功能改动bug fix、新功能、性能优化等

以下文件禁止出现在 PR 中(属于我们 fork 的定制化内容):

  • CLAUDE.mdAGENTS.md — 我们的开发文档
  • backend/cmd/server/VERSION — 我们的版本号文件
  • UI 定制改动GitHub 链接移除、微信客服按钮、首页定制等)
  • 部署配置(deploy/ 目录下的定制修改)

PR 流程

  1. develop 创建功能分支,只包含要提交给上游的改动
  2. 推送分支后,等待 4 个 CI job 全部通过
  3. 确认通过后再创建 PR
  4. 使用 gh run list --repo touwaeriol/sub2api --branch <branch> 检查状态

自有分支推送develop / main

推送到我们自己的 developmain 分支时,包含所有改动(定制化 + 通用功能)。

推送流程

  1. 本地运行 cd backend && make test-unit 确保单元测试通过
  2. 本地运行 cd backend && gofmt -l ./... 确保格式正确
  3. 推送后确认 CI 和 Security Scan 两个 workflow 的 4 个 job 全部绿色
  4. 任何 job 失败必须立即修复,禁止在 CI 未通过的状态下继续后续操作

发布版本

  1. 确保 main 分支最新提交的 4 个 CI job 全部通过
  2. 递增 backend/cmd/server/VERSION,提交并推送
  3. 打 tag 推送后,确认 tag 触发的 3 个 workflowCI、Security Scan、Release全部通过
  4. Release workflow 失败时禁止部署 — 必须先修复问题,删除旧 tag重新打 tag
  5. 使用 gh run list --repo touwaeriol/sub2api --limit 10 确认状态

常见 CI 失败原因及修复

  • gofmtstruct 字段对齐不一致 → 运行 gofmt -w <file> 修复
  • golangci-lint:未使用的变量/导入 → 删除或使用 _ 忽略
  • test 失败mock 函数签名不一致 → 同步更新 mock
  • gosec:安全漏洞 → 根据提示修复或添加例外