# Copyboard Release

> CopyBoard App Store 发版流程：查询并明确反馈商店在售版本与在途版本（审核中/待提交/被拒等）、 经用户二次确认后再 bump 版本号、生成简洁更新日志、上传 metadata、构建并上传二进制。 Use when the user asks to release, ship, publish, bump version, upload to App Store, TestFlight production, or 发版/上架/版本发布.

- Skill: `fanthus/copyboard-release` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add fanthus/copyboard-release`
- Raw SKILL.md: https://api.skillmd.com/api/skills/fanthus/copyboard-release/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: fanthus (https://skillmd.com/u/fanthus)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/fanthus/copyboard-release

---


# CopyBoard 发版

端到端把 CopyBoard 发到 App Store。**任何版本号变更与上传前，必须先向用户汇报完整商店版本状态并获二次确认。**

## 硬性规则（必须遵守）

1. **必须先查询并明确告知**以下商店状态（缺一不可）：
   - **正在销售（Ready for Sale / live）** 的版本号
   - **所有在途版本**（非历史归档）：`WAITING_FOR_REVIEW`、`IN_REVIEW`、`PREPARE_FOR_SUBMISSION`、`PENDING_*`、`REJECTED` 等（见下方状态表）
2. **禁止自动 bump 版本号**；是否 bump、目标版本号是多少，**必须等用户二次确认后再执行**
3. 在用户确认前，**不得**运行 `bump_project_version.sh`、不得改 `MARKETING_VERSION` / `Deliverfile`、不得创建 ASC 版本、不得上传二进制
4. 向用户反馈时使用固定模板（见下方「版本状态反馈模板」），数字与状态必须来自脚本输出，禁止臆测
5. 若存在在途版本，**必须**在模板中单独列出，并提醒：不可与在途版本号冲突；建议目标默认避开在途号（脚本已按 `max(在售,在途).patch+1` 计算）

## 前置检查

执行前逐项确认，任一失败则停止并告知用户：

- [ ] 当前工作目录为 CopyBoard 仓库根（含 `CopyBoard.xcodeproj`），或已设置 `COPYBOARD_ROOT`
- [ ] `cers/AuthKey_XLHKRZLVU8.p8` 存在（gitignore，本机需自备）
- [ ] 仓库根目录执行 `bundle install` 已成功（使用根目录 `Gemfile`）
- [ ] 当前分支适合发版（通常 `develop` 或 `main`），功能已合并
- [ ] 用户明确要 **发版**（会可能改版本号、写 release notes、上传商店）

## 工作流

```text
发版进度：
- [ ] 1. 查询版本状态（在售 + 在途），向用户反馈并等待二次确认
- [ ] 2. 收集自上一 tag 以来的提交
- [ ] 3. 生成并写入各语言 release_notes
- [ ] 4. （仅用户确认后）同步工程版本号
- [ ] 5. （仅用户确认后）创建 ASC 版本并上传 metadata
- [ ] 6. （仅用户确认后）构建并上传二进制
- [ ] 7. 汇总结果给用户
```

### Step 1 — 查询版本状态 + 二次确认（门禁）

运行：

```bash
~/.agent/skills/copyboard-release/scripts/show_version_status.sh
```

输出 JSON 示例：

```json
{
  "store_live_version": "1.3.4",
  "store_live_build": "250",
  "store_live_source": "app_store_connect",
  "store_in_flight_versions": [
    {
      "version": "1.3.5",
      "state": "WAITING_FOR_REVIEW",
      "release_type": "AFTER_APPROVAL",
      "created": "2026-07-02T09:22:39-07:00"
    }
  ],
  "has_in_flight_version": "yes",
  "project_marketing_version": "1.3.5",
  "project_build_number": "31",
  "latest_git_tag": "1.3.5",
  "suggested_bump_version": "1.3.6",
  "will_bump_if_use_suggestion": "yes",
  "store_query_error": null
}
```

字段说明：

| 字段 | 含义 |
|---|---|
| `store_live_version` | **商店正在销售的版本号**（必须告知用户） |
| `store_live_build` | 商店在售 build 号（若有） |
| `store_live_source` | `app_store_connect` / `git_tag_fallback` / `unavailable` |
| `store_in_flight_versions` | **所有在途版本**数组：`version` / `state` / `release_type` / `created` |
| `has_in_flight_version` | 是否存在在途版本（`yes`/`no`） |
| `project_marketing_version` | 工程当前 `MARKETING_VERSION` |
| `project_build_number` | 工程当前 build 号 |
| `suggested_bump_version` | 建议发版目标 = `max(在售, 所有在途).patch + 1` |
| `will_bump_if_use_suggestion` | 若采用建议版本，工程是否需要 bump（`yes`/`no`） |

#### 在途状态（必须上报）

| ASC `state` | 中文说明 |
|---|---|
| `PREPARE_FOR_SUBMISSION` | 准备提交 |
| `WAITING_FOR_REVIEW` | 等待审核 |
| `IN_REVIEW` | 审核中 |
| `PENDING_APPLE_RELEASE` | 等待 Apple 发布 |
| `PENDING_DEVELOPER_RELEASE` | 等待开发者发布 |
| `PROCESSING_FOR_APP_STORE` | 正在处理上架 |
| `DEVELOPER_REJECTED` | 开发者已撤回 |
| `REJECTED` | 审核被拒 |
| `METADATA_REJECTED` | 元数据被拒 |
| `INVALID_BINARY` | 二进制无效 |

**不必逐条罗列**的历史状态：`READY_FOR_SALE`（只报当前在售一条）、`REPLACED_WITH_NEW_VERSION`。

**必须用以下模板回复用户，然后停止等待确认：**

```markdown
## 发版版本状态

| 项目 | 版本 |
|---|---|
| **App Store 正在销售版本** | **{store_live_version 或「查询失败」}**（build {store_live_build 或 -}） |
| **商店在途版本** | {若 has_in_flight_version=no：无}{若有：逐条列出 **版本号 — state（中文说明）**，可附 release_type} |
| 工程当前版本 | {project_marketing_version}（build {project_build_number}） |
| 最新 git tag | {latest_git_tag 或 -} |
| 建议发版目标 | {suggested_bump_version 或待你指定} |
| 是否需 bump 工程版本 | {will_bump_if_use_suggestion} |

数据来源：{store_live_source}
{若 store_query_error 非空，附简短错误说明}
{若存在在途版本，追加一句：存在在途版本时不要复用其版本号；建议目标已避开在途号。可选路径：等审核结束 / 撤审后重传同号 / 发建议的新版本号。}

请确认发版目标版本号：
- A) 使用建议版本 {suggested_bump_version}（{will_bump 说明}）
- B) 使用工程当前版本 {project_marketing_version}（不 bump）
- C) 指定其他版本（请给出 x.y.z）
```

优先使用 **AskQuestion** 工具收集用户选择；若不可用，在对话中等待用户明确回复 **A / B / C** 或具体版本号。

**确认前禁止进入 Step 2 及之后任何会改版本或上传的步骤。**

特殊情况：

- `store_live_source` = `unavailable`：说明 ASC 查询失败原因（常见：协议未签），可用 git tag 作参考，但**目标版本仍须用户确认**
- 存在在途版本且工程版本与在途版本相同：在选项 B 旁注明「与在途版本冲突，通常应选 A 或撤审后再发」
- 用户说「发当前版本」：仍须先展示在售 + 在途，再确认是否用工程版本 `{project_marketing_version}` 发版
- 用户指定 minor/major：记录目标版本，确认后再 bump

### Step 2 — 收集提交

```bash
~/.agent/skills/copyboard-release/scripts/list_release_commits.sh
```

自最近 semver tag 到 `HEAD`，排除 `release:`、`chore: bump` 等 housekeeping 提交。

### Step 3 — 生成版本更新日志

**风格：简洁、面向用户、2–5 条**；每条以 `- ` 开头。

1. 先写 **zh-Hans**，再翻译到其余 8 个 metadata 语言
2. 合并同类 commit；忽略纯 chore/docs/CI（除非用户可见）

写入 9 个 `fastlane/metadata/*/release_notes.txt`（见 [reference.md](reference.md)）。

### Step 4 — 同步工程版本号（仅用户确认后）

仅当 Step 1 确认的目标版本 **≠** 当前 `project_marketing_version` 时执行：

```bash
~/.agent/skills/copyboard-release/scripts/bump_project_version.sh <CONFIRMED_VERSION>
```

若用户选择 **不 bump**（工程版本已是目标版本），**跳过本步**。

### Step 5 — 创建商店版本并上传 metadata（仅用户确认后）

```bash
bundle exec fastlane ios create_app_store_version
```

### Step 6 — 构建并上传二进制（仅用户确认后）

```bash
RELEASE_CONFIRM=1 scripts/release_appstore.sh
```

或 `bundle exec fastlane ios release`。

### Step 7 — 汇总

向用户报告：

- **商店在售版本** → **本次发版版本**（并再次确认在途是否已变化）
- 是否执行了 bump
- Build 号、release notes 要点、上传结果
- 后续：ASC 提交审核等

## 常见问题

| 情况 | 处理 |
|---|---|
| ASC 协议未签署 | 告知用户签署 Paid Apps 等协议；**仍需先反馈版本状态，等确认后再重试** |
| 商店查询失败 | 展示工程版本 + git tag 参考；目标版本必须用户确认 |
| 工程版本高于商店 | 在 Step 1 模板中明确对比，让用户选建议 bump 或工程当前版本 |
| 已有等待审核 / 审核中版本 | **必须上报**；建议发更高版本号，或等过审 / 撤审后再动该版本 |
| 仅更新文案 | 仍走 Step 1 确认；只跑 `bundle exec fastlane ios metadata` |

## 不要做的事

- **不要**跳过 Step 1 二次确认
- **不要**只报在售版本而漏报在途版本（审核中、待提交、被拒等）
- **不要**未经确认 bump 版本或上传
- **不要**臆测商店在售 / 在途版本号
- **不要**在已有同号在途版本时默认建议复用该号
- 不要未经用户要求 commit / push
- 不要只更新部分语言的 release notes

## 参考

- 文件清单与 lane 说明：[reference.md](reference.md)
- 项目发版约定：`AGENTS.md` → CopyBoard 项目上下文 / fastlane 章节

