ly-workflow-codex 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,388 @@
1
+ ---
2
+ name: lyx-publish
3
+ description: 'npm 包发布:bmc 私域 Nexus / GitHub Packages / npmjs + GitHub Release / CI 自动发布 四场景'
4
+ argument-hint: '<场景描述>'
5
+ ---
6
+
7
+ # Publish - npm 包发布
8
+
9
+ > 调用方式:`@lyx-publish` mention 后跟随的自然语言即参数(如 `@lyx-publish` 带需求描述/选项);无参数时直接 `@lyx-publish`。
10
+
11
+ 覆盖四个发布场景:bmc 私域 Nexus、GitHub Packages、公开 npmjs.org + GitHub Release、CI 自动发布(tag push 触发)。发布前走前置检查 → 版本号自动推导 → 构建 → 发布 → 验证完整流程。
12
+
13
+ ## 使用方法
14
+
15
+ ```bash
16
+ @lyx-publish <场景描述>
17
+ ```
18
+
19
+ **🔴 CHECKPOINT:先确认发布目标,问用户,别猜。**
20
+
21
+ - **bmc 私域**:发到公司 Nexus 私有 registry(scope 通常是 `@bmc`)
22
+ - **GitHub**:三种情况之一,需要用户明确
23
+ - A. GitHub Packages npm registry(`npm.pkg.github.com`,需要 GitHub 账号/组织权限)
24
+ - B. 公开发到 npmjs.org,再在 GitHub 建 Release/Tag(开源包常见做法)
25
+ - C. **CI 自动发布**:本地只 push commit/tag,实际 `npm publish` 由 GitHub Actions workflow 执行(团队协作/避免本地手动发布出错的常见做法)
26
+
27
+ 确认后按对应场景执行。
28
+
29
+ ---
30
+
31
+ ## 前置检查(所有场景通用)
32
+
33
+ ```bash
34
+ # Node/pnpm 版本
35
+ node -v
36
+ pnpm -v 2>/dev/null || npm -v
37
+
38
+ # Git 工作目录是否干净
39
+ git status --porcelain
40
+ # 有未提交改动先询问用户是否继续,别自动 commit
41
+
42
+ # 当前分支
43
+ git branch --show-current
44
+ # 建议从 master/main 发布,非主分支要提醒用户
45
+ ```
46
+
47
+ 检查 `package.json` 必备字段:
48
+
49
+ ```bash
50
+ cat package.json | grep -E '"name"|"version"|"files"|"main"|"exports"|"publishConfig"'
51
+ ```
52
+
53
+ - `files` 字段要包含实际产物目录(如 `dist`),漏了会导致发布出去的包缺文件
54
+ - 有 `prepublishOnly` / `build` 脚本的,发布前必须先跑一遍构建
55
+
56
+ **🔴 检测项目是否已有自定义发布脚本:**
57
+
58
+ ```bash
59
+ cat package.json | grep -iE '"(publish|release)[a-z:-]*"\s*:'
60
+ ls scripts/*publish* scripts/*release* 2>/dev/null
61
+ ```
62
+
63
+ - **有** → 先读脚本内容确认它做了什么(是否已封装 registry 检查/构建/版本 bump/tag)。**🔴 CHECKPOINT:优先问用户是否直接用现有脚本**,不要绕过去重新走下面的通用流程——现有脚本往往已经绑定了正确的 registry 地址和内部约定,重新手搓一遍容易和它冲突或重复发布
64
+ - **没有** → 按下面场景的通用步骤走
65
+
66
+ ---
67
+
68
+ ## 版本号确定规则(SemVer + Conventional Commits 自动推导)
69
+
70
+ **不要直接问用户「patch 还是 minor」,先分析 commit 历史给出建议,再让用户确认/覆盖。**(与 `@lyx-release` 共享同一套规则)
71
+
72
+ ### 自动分析步骤
73
+
74
+ ```bash
75
+ # 1. 确定上一次 bump 的边界(优先 tag → package.json 历史 commit)
76
+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "")
77
+ PREV_BUMP=$(git log -2 -p --format=%H -- package.json | grep -B5 '"version"' | grep '^[0-9a-f]\{40\}$' | tail -1)
78
+ BASE_REF=${PREV_TAG:-${PREV_BUMP:-}}
79
+
80
+ # 2. 收集本次发版的 commit(排除 bump version 本身)
81
+ if [ -n "$BASE_REF" ]; then
82
+ COMMITS=$(git log ${BASE_REF}..HEAD --oneline --no-merges -- | grep -v "bump version")
83
+ else
84
+ COMMITS=$(git log HEAD --oneline --no-merges -- | grep -v "bump version")
85
+ fi
86
+
87
+ # 3. 按 Conventional Commits 分类统计
88
+ echo "$COMMITS" | grep -c "^[a-f0-9]* feat" || true # 新功能数量
89
+ echo "$COMMITS" | grep -c "^[a-f0-9]* fix" || true # 修复数量
90
+ echo "$COMMITS" | grep -i "BREAKING CHANGE" || true # 破坏性变更
91
+ ```
92
+
93
+ ### 推导规则
94
+
95
+ | 条件 | 建议档位 | 示例 |
96
+ |------|---------|------|
97
+ | 含 `BREAKING CHANGE` 或 `feat!:` | **major** | 1.6.1 → 2.0.0 |
98
+ | 无 BREAKING CHANGE,有 `feat:` | **minor** | 1.6.1 → 1.7.0 |
99
+ | 仅 `fix:` / `docs:` / `chore:` | **patch** | 1.6.1 → 1.6.2 |
100
+ | 首次发版 / 无历史 | 问用户 | — |
101
+
102
+ ### 询问模板
103
+
104
+ ```
105
+ 分析发现本次改动:
106
+ - 新增功能 X 个,修复 Y 个,无破坏性变更
107
+ → 建议 bump minor:1.6.1 → 1.7.0
108
+
109
+ 是否使用此建议?可以改为 patch(1.6.1 → 1.6.2)或 major(1.6.1 → 2.0.0)
110
+ ```
111
+
112
+ - **同意建议**:直接按建议执行 `npm version <patch|minor|major>`
113
+ - **覆盖**:按用户输入的档位执行
114
+ - **不存在以往的 commit**:回退到直接询问版本号
115
+
116
+ 若已装 `@lyx-changelog`,version bump 后触发它更新 CHANGELOG,再补一次 commit;没装则询问用户要不要更新日志。
117
+
118
+ ---
119
+
120
+ ## 场景一:发布到 bmc 私域 Nexus
121
+
122
+ **触发词:** "发私域"、"发到bmc"、"内网发布"、"发到nexus"
123
+
124
+ ### 1. 确认 `.npmrc` scope 配置
125
+
126
+ ```bash
127
+ cat .npmrc 2>/dev/null | grep registry
128
+ ```
129
+
130
+ 应包含(scope 按实际包名调整,如 `@bmc`):
131
+
132
+ ```
133
+ @bmc:registry=https://nexus-office.domob-inc.cn/repository/bfm_npm_hosted/
134
+ ```
135
+
136
+ 没有就先创建 `.npmrc`(询问用户具体 Nexus 地址,不要瞎填)。
137
+
138
+ ### 2. 登录检查
139
+
140
+ ```bash
141
+ REGISTRY_URL=$(grep "@bmc:registry" .npmrc | cut -d'=' -f2 | tr -d ' ')
142
+ npm whoami --registry="$REGISTRY_URL"
143
+ ```
144
+
145
+ 未登录:
146
+
147
+ ```bash
148
+ npm login --registry="$REGISTRY_URL"
149
+ ```
150
+
151
+ ### 3. 构建与检查
152
+
153
+ ```bash
154
+ pnpm build # 或对应包的 build 脚本
155
+ pnpm type-check # 有则跑
156
+ pnpm lint # 有则跑,失败先询问是否继续
157
+ ```
158
+
159
+ ### 4. 版本号(🔴 SemVer 自动推导 + 用户确认,非直接问 patch/minor/major)
160
+
161
+ 按上方「版本号确定规则」执行:
162
+ - 分析上次 bump 以来的 commit 列表
163
+ - 按 feat/fix/BREAKING 推导建议档位
164
+ - 将建议展示给用户确认/覆盖
165
+ - 确认后执行 `npm version <patch|minor|major>`(会自动更新 package.json + 打 git tag + commit)
166
+
167
+ 若项目已装 `@lyx-changelog`,version bump 后触发它更新 CHANGELOG,再补一次 commit;没装则询问用户要不要更新日志。
168
+
169
+ ### 5. 发布
170
+
171
+ ```bash
172
+ # 注意 scope 私有包默认 restricted,要标注 access
173
+ npm publish --registry="$REGISTRY_URL" --access restricted
174
+ ```
175
+
176
+ ### 6. 推送 tag 并验证
177
+
178
+ ```bash
179
+ git push --follow-tags
180
+
181
+ # 验证:发布后确认新版本已出现在目标 registry
182
+ npm view <包名>@<新版本号> --registry="$REGISTRY_URL"
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 场景二:发布到 GitHub Packages(`npm.pkg.github.com`)
188
+
189
+ **触发词:** "发到github packages"、"github registry"
190
+
191
+ ### 1. `.npmrc` 配置
192
+
193
+ scope 必须对应 GitHub 用户名/组织(大小写敏感):
194
+
195
+ ```
196
+ @<github用户名或组织>:registry=https://npm.pkg.github.com
197
+ ```
198
+
199
+ ### 2. 认证
200
+
201
+ 需要一个具备 `write:packages`(发布)+ `read:packages` 权限的 GitHub Personal Access Token:
202
+
203
+ ```bash
204
+ # 方式一:npm login 交互式
205
+ npm login --scope=@<github用户名或组织> --registry=https://npm.pkg.github.com
206
+
207
+ # 方式二:环境变量 + .npmrc 直接写 token(本地测试可用,别提交含 token 的 .npmrc)
208
+ echo "//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}" >> ~/.npmrc
209
+ ```
210
+
211
+ **注意:** 千万别把带 token 的 `.npmrc` commit 进仓库——检查 `.gitignore` 是否已排除本地 `.npmrc`(若项目里 `.npmrc` 本身要提交作为团队共享配置,token 必须走环境变量而非硬编码)。
212
+
213
+ ### 3. package.json 需要 `publishConfig` 指向该 registry
214
+
215
+ ```json
216
+ {
217
+ "publishConfig": {
218
+ "registry": "https://npm.pkg.github.com"
219
+ }
220
+ }
221
+ ```
222
+
223
+ ### 4. 构建、版本号步骤同场景一(版本号按上方「版本号确定规则」自动推导 + 确认),发布命令:
224
+
225
+ ```bash
226
+ npm publish
227
+ ```
228
+
229
+ ---
230
+
231
+ ## 场景三:公开发到 npmjs.org + GitHub Release(开源包常见流程)
232
+
233
+ **触发词:** "发到npm官方"、"发public包"、"发github release"、"开源发布"
234
+
235
+ ### 1. 确认无 scope registry 覆盖
236
+
237
+ ```bash
238
+ cat .npmrc 2>/dev/null
239
+ # 若有 registry 指向私有源,临时用 --registry 覆盖,别改动 .npmrc 影响其他包
240
+ ```
241
+
242
+ ### 2. 登录 npmjs.org
243
+
244
+ ```bash
245
+ npm whoami
246
+ # 未登录:
247
+ npm login
248
+ ```
249
+
250
+ ### 3. 构建、版本号步骤同场景一(版本号按上方「版本号确定规则」自动推导 + 确认)
251
+
252
+ ### 4. 发布
253
+
254
+ ```bash
255
+ npm publish --access public # 首次发布 scoped 公共包必须加 --access public
256
+ ```
257
+
258
+ ### 5. GitHub Release
259
+
260
+ ```bash
261
+ # 确认 tag 已推送(npm version 已打好 tag)
262
+ git push --follow-tags
263
+
264
+ # 用 gh cli 建 release,标题/说明取自 CHANGELOG 对应版本段落
265
+ gh release create v<新版本号> --title "v<新版本号>" --notes-file <(sed -n '/## \[<新版本号>\]/,/## \[/p' CHANGELOG.md | sed '$d')
266
+ ```
267
+
268
+ 没装 `gh` 的话提示用户去 GitHub 网页手动创建 Release,附上对应 CHANGELOG 片段。
269
+
270
+ ---
271
+
272
+ ## 场景四:推送 GitHub 触发 CI 自动发布(GitHub Actions)
273
+
274
+ **触发词:** "用CI发布"、"github actions发包"、"推tag自动发布"、"CI自动发npm"
275
+
276
+ 本地不跑 `npm publish`,只负责构建前的版本号/tag 准备,真正的发布动作在 CI 里跑。
277
+
278
+ ### 1. 确认触发方式(🔴 CHECKPOINT:问用户,别猜)
279
+
280
+ - **打 tag 触发**(最常见):workflow 监听 `push: tags: ['v*']`
281
+ - **push 到 release 分支触发**:workflow 监听 `push: branches: [main/master]`
282
+ - **手动触发**:workflow 监听 `workflow_dispatch`
283
+
284
+ ```bash
285
+ cat .github/workflows/*.yml 2>/dev/null | grep -A3 "^on:"
286
+ ```
287
+
288
+ 没有 workflow 文件就先帮用户写一个(`.github/workflows@lyx-publish.yml`),核心结构:
289
+
290
+ ```yaml
291
+ name: Publish
292
+ on:
293
+ push:
294
+ tags: ['v*']
295
+ jobs:
296
+ publish:
297
+ runs-on: ubuntu-latest
298
+ steps:
299
+ - uses: actions/checkout@v4
300
+ - uses: actions/setup-node@v4
301
+ with:
302
+ node-version: 20
303
+ registry-url: 'https://registry.npmjs.org' # 私域改成 Nexus 地址;@scope 需在 .npmrc 里配好
304
+ - run: npm ci
305
+ - run: npm run build
306
+ - run: npm publish --access public # 私有包用 --access restricted
307
+ env:
308
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
309
+ ```
310
+
311
+ ### 2. 配置发布用的 Secret(GitHub 仓库设置里做,本地只提醒)
312
+
313
+ - npmjs.org / GitHub Packages:在仓库 `Settings → Secrets and variables → Actions` 添加 `NPM_TOKEN`(npm 官网生成的 Automation Token,或 GitHub PAT)
314
+ - bmc 私域 Nexus:CI runner 需能访问内网 Nexus 地址——若 GitHub Actions 是公网 runner,先确认 Nexus 是否对公网开放/走 self-hosted runner,不确定就提醒用户先确认网络可达性,别假设能连上
315
+ - **注意:** Token 只存在 Secrets 里,绝不写进 workflow 文件或 commit
316
+
317
+ ### 3. 本地准备工作(触发 CI 前要做的)
318
+
319
+ ```bash
320
+ # 构建、类型检查照场景一跑一遍(确保能过,CI 里挂了排查更麻烦)
321
+ pnpm build
322
+ pnpm type-check
323
+
324
+ # 版本号 bump(按上方「版本号确定规则」自动推导 + 确认)
325
+ npm version <patch|minor|major>
326
+
327
+ # 若装了 @lyx-changelog,此时更新 CHANGELOG 并补 commit;没装则询问用户
328
+ ```
329
+
330
+ ### 4. 推送触发
331
+
332
+ ```bash
333
+ git push --follow-tags
334
+ # 或按 workflow 触发条件,push 到对应分支
335
+ ```
336
+
337
+ ### 5. 验证
338
+
339
+ ```bash
340
+ # 查看 workflow 运行状态
341
+ gh run list --limit 5
342
+ gh run watch # 实时看当前发布 workflow 的日志
343
+
344
+ # CI 跑完后确认包已上线
345
+ npm view <包名> versions --registry=<对应registry>
346
+ ```
347
+
348
+ 没装 `gh` 就提示用户去仓库 Actions 页面看运行结果。
349
+
350
+ **🔴 CHECKPOINT:** 本地绝不要在 CI 已接管发布的项目里再手动跑一遍 `npm publish`——会导致版本号冲突或重复发布。先确认这次是走 CI 还是走本地手动,别两条路一起跑。
351
+
352
+ ---
353
+
354
+ ## 发布前自检清单(任何场景都建议过一遍)
355
+
356
+ ```bash
357
+ # 预览实际会打进包里的文件,检查是否缺文件/夹带不该发的文件
358
+ npm pack --dry-run
359
+ ```
360
+
361
+ - `dist`/构建产物是否已生成且是最新的(避免发的是旧代码)
362
+ - `README.md`、`LICENSE` 是否存在且会被 `files` 字段包含
363
+ - `version` 是否已经存在于目标 registry(避免 409 冲突,`npm view <包名>@<版本号>` 可查)
364
+ - 私有包 `access` 是否为 `restricted`,公开包是否为 `public`
365
+
366
+ ## `npm publish` 常见报错处理
367
+
368
+ | 报错 | 触发条件 | 处理 |
369
+ |---|---|---|
370
+ | `403 Forbidden` / `You must be logged in` | 未登录或 token 过期 | 重新 `npm login --registry=<对应地址>`;GitHub Packages/CI 场景检查 token 权限是否含 `write:packages` 或 Secret 是否过期 |
371
+ | `409 Conflict` / `You cannot publish over the previously published version` | 版本号已存在 | 先 `npm view <包名>@<版本号> --registry=<对应地址>` 确认;确实冲突则重新 `npm version patch/minor/major` 打一个新版本号,不要改已发布版本 |
372
+ | `402 Payment Required` / 需要 `--access public` | 首次发布 scoped 公共包没加 `--access public` | 补上 `--access public` 重试;私有包保持 `--access restricted` 别改 |
373
+ | 构建脚本报错 / `prepublishOnly` 失败 | 代码本身有问题,或依赖没装齐 | 别绕过直接强发(`npm publish` 会先跑 `prepublishOnly`,失败会自动中止,不用手动加 `--ignore-scripts` 硬闯);先定位报错原因修好代码再重试 |
374
+ | CI 里 `npm publish` 卡住或失败但本地能发 | CI runner 网络不通私域 Nexus,或 Secret 没配对 | 检查该 workflow 是否为 self-hosted runner、Secret 名字是否与 workflow 里 `secrets.XXX` 一致;不确定就让用户去 Actions 页面看具体报错,不要瞎猜重试 |
375
+
376
+ ---
377
+
378
+ ## 发布后验证
379
+
380
+ ```bash
381
+ npm view <包名> versions --registry=<对应registry> # 确认新版本已出现
382
+ ```
383
+
384
+ 新开一个临时目录 `npm install`/`pnpm add` 装一下,跑通基本 import,确认没有漏文件。
385
+
386
+ ---
387
+
388
+ **注意:** 版本号 bump(`npm version`)、tag、push 若项目已装 `@lyx-release` 和 `@lyx-changelog`,优先复用那两个命令的规则,避免重复定义流程;本命令专注 registry 认证配置 + `npm publish` 本身这一环。不引入 changesets。
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: lyx-release
3
+ description: 'GitFlow 发版流程:feature/release/hotfix/dev-offline 四场景,SemVer 自动推导版本号'
4
+ argument-hint: '<场景描述>'
5
+ ---
6
+
7
+ # Release - GitFlow 发版
8
+
9
+ > 调用方式:`@lyx-release` mention 后跟随的自然语言即参数(如 `@lyx-release` 带需求描述/选项);无参数时直接 `@lyx-release`。
10
+
11
+ 按场景执行 GitFlow 分支操作,版本号按 SemVer + Conventional Commits 自动推导建议,用户确认后执行。
12
+
13
+ ## 使用方法
14
+
15
+ ```bash
16
+ @lyx-release <场景描述>
17
+ ```
18
+
19
+ 直接告诉 Codex 要做什么,例如:"开始新功能"、"准备发版"、"线上有 bug 要 hotfix"、"发到线下"。
20
+
21
+ ## 重要规则
22
+
23
+ > **任何合并到 master 的改动都必须更新 `version.sh` 中的版本号,否则 CI/CD 部署会失败。**
24
+ >
25
+ > - release 流程:在 release 分支上更新版本号
26
+ > - hotfix 流程:**也必须**在 hotfix 分支上更新版本号,不能跳过
27
+ >
28
+ > **分支基准规则:`master` 是唯一的分支 base**——feature、release、hotfix 分支**一律从 master 拉出**;`develop` 是主开发分支,只接收合并(所有开发成果汇入 develop),**任何时候不作为创建分支的 base**。
29
+ >
30
+ > **线上合并后必须三分支同步:** 任何改动合并到 master(含 feature 方式 C 直上线、release/hotfix 的 PR merge 或本地直接合并)后,都要把 `master`、`develop`、`dev-offline` 三个分支同步一遍,**以远端 `origin/master` 为基准**——同步前先 `git fetch origin master` 保证 `origin/master` 是线上最新状态,再 `git merge origin/master`,确保本地三个分支与线上保持一致。
31
+ >
32
+ > **主分支名检测规则:主分支可能是 `master` 也可能是 `main`。** 在执行任何场景前,先检测远端主分支名:
33
+ >
34
+ > ```bash
35
+ > git remote show origin | grep 'HEAD branch' # 输出形如:HEAD branch: master
36
+ > # 远端不可用或未设置 HEAD 时的兜底:
37
+ > git branch -r | grep -E 'origin/(master|main)$'
38
+ > ```
39
+ >
40
+ > 下方所有命令示例中的 `master` 一律替换为实际检测到的主分支名(如 `main`),流程逻辑不变。
41
+
42
+ ---
43
+
44
+ ## 版本号确定规则(SemVer + Conventional Commits 自动推导)
45
+
46
+ **不要直接问用户「patch 还是 minor」,先分析 commit 历史给出建议,再让用户确认/覆盖。**
47
+
48
+ ### 自动分析步骤
49
+
50
+ ```bash
51
+ # 1. 确定上一次 bump 的边界(优先 tag → version.sh 历史 commit)
52
+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "")
53
+ PREV_BUMP=$(git log --format=%H -- version.sh | head -2 | tail -1)
54
+ BASE_REF=${PREV_TAG:-${PREV_BUMP:-}}
55
+
56
+ # 2. 收集本次发版的 commit(排除 bump version 本身)
57
+ if [ -n "$BASE_REF" ]; then
58
+ COMMITS=$(git log ${BASE_REF}..HEAD --oneline --no-merges -- | grep -v "bump version")
59
+ else
60
+ COMMITS=$(git log HEAD --oneline --no-merges -- | grep -v "bump version")
61
+ fi
62
+
63
+ # 3. 按 Conventional Commits 分类统计
64
+ echo "$COMMITS" | grep -c "^[a-f0-9]* feat" || true # 新功能数量
65
+ echo "$COMMITS" | grep -c "^[a-f0-9]* fix" || true # 修复数量
66
+ echo "$COMMITS" | grep -i "BREAKING CHANGE" || true # 破坏性变更
67
+ ```
68
+
69
+ ### 推导规则
70
+
71
+ | 条件 | 建议档位 | 示例 |
72
+ |------|---------|------|
73
+ | 含 `BREAKING CHANGE` 或 `feat!:` | **major** | 1.6.1 → 2.0.0 |
74
+ | 无 BREAKING CHANGE,有 `feat:` | **minor** | 1.6.1 → 1.7.0 |
75
+ | 仅 `fix:` / `docs:` / `chore:` | **patch** | 1.6.1 → 1.6.2 |
76
+ | 首次发版 / 无历史 | 问用户 | — |
77
+
78
+ ### 询问模板
79
+
80
+ ```
81
+ 分析发现本次改动:
82
+ - 新增功能 X 个,修复 Y 个,无破坏性变更
83
+ → 建议 bump minor:1.6.1 → 1.7.0
84
+
85
+ 是否使用此建议?可以改为 patch(1.6.1 → 1.6.2)或 major(1.6.1 → 2.0.0)
86
+ ```
87
+
88
+ - **同意建议**:直接按建议执行
89
+ - **覆盖**:按用户输入的档位执行,不改建议逻辑(记录偏好不持久化)
90
+ - **不存在以往的 commit**:回退到直接询问版本号
91
+
92
+ ---
93
+
94
+ ## 场景一:开始新功能(feature)
95
+
96
+ **触发词:** "开始新功能"、"新feature"、"feature分支"
97
+
98
+ ```bash
99
+ # 1. 确保 master 是最新的
100
+ git checkout master
101
+ git pull origin master
102
+
103
+ # 2. 创建 feature 分支(功能名用英文小写+连字符,如 user-login)
104
+ git checkout -b feature/<功能名>
105
+
106
+ # 3. 开发完成后,确认本次功能发到哪个环境,选择对应合并方式:
107
+ #
108
+ # 方式 A:合入主开发分支 develop(常规集成,后续统一走发版流程)
109
+ git checkout develop
110
+ git pull origin develop # 再次拉取;feature 基于 master 拉出,merge 前确认 develop 上没有冲突
111
+ git merge --no-ff feature/<功能名>
112
+ git push origin develop
113
+ #
114
+ # 方式 B:直接发线下测试环境 dev-offline
115
+ git checkout dev-offline
116
+ git pull origin dev-offline
117
+ git merge --no-ff feature/<功能名>
118
+ git push origin dev-offline
119
+ #
120
+ # 方式 C:直接上线 master
121
+ git checkout master
122
+ git pull origin master
123
+ git merge --no-ff feature/<功能名>
124
+
125
+ # 合并后必须先更新版本号(凡合入 master 都必须 bump,否则 CI/CD 部署失败)
126
+ # 读取当前版本:grep -oP 'VERSION=\K[^ ]+' version.sh
127
+ # 按上方「版本号确定规则」分析 commit 历史,给出建议档位,询问用户确认
128
+ # 编辑 version.sh 将 VERSION=x.x.x 改为确认的版本号,再执行:
129
+ git add version.sh
130
+ git commit -m "chore: bump version to <确认的版本号>"
131
+ git push origin master
132
+
133
+ # 方式 C 上线合并完成后,三分支同步(以远端 origin/master 为基准):
134
+ git fetch origin master # 关键:先把 origin/master 引用刷新到线上最新
135
+ git checkout master
136
+ git merge --ff-only origin/master
137
+ git push origin master
138
+ git checkout develop
139
+ git pull origin develop
140
+ git merge origin/master
141
+ git push origin develop
142
+ git checkout dev-offline
143
+ git pull origin dev-offline
144
+ git merge origin/master
145
+ git push origin dev-offline
146
+
147
+ # 4. 删除 feature 分支
148
+ git branch -d feature/<功能名>
149
+ git push origin --delete feature/<功能名>
150
+ ```
151
+
152
+ **注意:** `--no-ff` 会产生一个合并提交,保留分支历史,便于后续追溯。
153
+
154
+ ---
155
+
156
+ ## 场景二:发布版本(release)
157
+
158
+ **触发词:** "发版"、"release"、"准备上线"
159
+
160
+ > **发版范围(单功能带发模式):** release 从 master 拉出,天然只包含已合入 master 的功能。
161
+ > 本次要发的功能需提前合入 master(feature 完成时走场景一「方式 C」直接上线,或先 merge feature 分支到 master);
162
+ > 若功能尚未合入 master,先按下方步骤 1 创建 release 分支后,再执行
163
+ > `git merge feature/<功能名>` 或 cherry-pick 对应 commit 带入本次发版。
164
+
165
+ ```bash
166
+ # 1. 从 master 创建 release 分支
167
+ git checkout master
168
+ git pull origin master
169
+ git checkout -b release/<版本号> # 例如 release/1.4.0
170
+
171
+ # 2. 确定版本号(SemVer 自动推导 + 用户确认)
172
+ # 读取当前版本:grep -oP 'VERSION=\K[^ ]+' version.sh
173
+ # 按上方「版本号确定规则」执行:
174
+ # a. 自动分析上次 bump 以来的 commit 列表
175
+ # b. 按 feat/fix/BREAKING 推导建议档位
176
+ # c. 将建议展示给用户:「建议 bump X → Y,是否确认?(可改为 Z)」
177
+ # d. 用户确认后,编辑 version.sh 将 VERSION=x.x.x 改为确认的版本号
178
+ git add version.sh
179
+ git commit -m "chore: bump version to <确认的版本号>"
180
+
181
+ # 3. 更新 CHANGELOG(如有)
182
+ # 若已安装 @lyx-changelog:直接触发它生成/更新 CHANGELOG.md 并提交
183
+ # 若未安装,按以下步骤手动执行:
184
+ #
185
+ # 检查项目根目录是否存在 CHANGELOG.md(或 CHANGELOG、CHANGELOG.txt):
186
+ # ls CHANGELOG* 2>/dev/null
187
+ #
188
+ # 【如果不存在 CHANGELOG】:询问用户是否需要创建,如果需要则按 Keep a Changelog 格式建立(见 @lyx-changelog)
189
+ # 【如果存在 CHANGELOG】:以本次 version.sh 的更新 commit 为节点,收集 commit 并按类型分组(Added/Fixed/Changed)写入
190
+ #
191
+ # 提交 CHANGELOG 变更:
192
+ git add CHANGELOG.md # 如果文件存在
193
+ git commit -m "docs: update CHANGELOG for v<确认的版本号>"
194
+
195
+ # 4. 上线合并到 master(二选一):
196
+ #
197
+ # 方式 A:远端 PR 合并(默认,可走 code review)
198
+ git push origin release/<版本号>
199
+ # 在 GitHub/GitLab 创建 PR:release/<版本号> → master
200
+ # 标题示例:Release v<版本号>
201
+ # 等待 code review 通过后 merge
202
+ #
203
+ # 方式 B:本地直接合并 master(跳过远端 PR,适合无需 review 的快速上线)
204
+ git push origin release/<版本号> # 先推送分支留档
205
+ git checkout master
206
+ git pull origin master
207
+ git merge --no-ff release/<版本号>
208
+ git push origin master
209
+
210
+ # 5. 上线合并完成后(无论方式 A 还是 B),以远端 origin/master 为基准同步 develop 和 dev-offline(带回版本号、CHANGELOG、修复)
211
+ git fetch origin master # 先把 origin/master 引用刷新到线上最新
212
+ git checkout master
213
+ git merge --ff-only origin/master
214
+ git push origin master
215
+ git checkout develop
216
+ git pull origin develop
217
+ git merge origin/master
218
+ git push origin develop
219
+ git checkout dev-offline
220
+ git pull origin dev-offline
221
+ git merge origin/master
222
+ git push origin dev-offline
223
+
224
+ # 6. 删除 release 分支
225
+ git branch -d release/<版本号>
226
+ git push origin --delete release/<版本号>
227
+ ```
228
+
229
+ **注意:** 版本号文件在根目录 `version.sh`,格式为 `export VERSION=x.x.x`,直接修改该行即可。
230
+
231
+ ---
232
+
233
+ ## 场景三:紧急修复(hotfix)
234
+
235
+ **触发词:** "hotfix"、"紧急修复"、"线上 bug"
236
+
237
+ ```bash
238
+ # 1. 从 master 创建 hotfix 分支
239
+ git checkout master
240
+ git pull origin master
241
+ git checkout -b hotfix/<问题描述> # 例如 hotfix/login-crash
242
+
243
+ # 2. 修复 bug,提交
244
+ git add .
245
+ git commit -m "fix: <问题描述>"
246
+
247
+ # 3. 确定版本号并 bump(必须!否则部署会失败)
248
+ # 读取当前版本:grep -oP 'VERSION=\K[^ ]+' version.sh
249
+ # hotfix 场景下通常只包含 fix: 类型 commit,自动推导结果为 patch(如 1.6.1 → 1.6.2)
250
+ # 按上方「版本号确定规则」展示推导结果给用户确认,确认后:
251
+ # 编辑 version.sh 将 VERSION=x.x.x 改为确认的版本号
252
+ git add version.sh
253
+ git commit -m "chore: bump version to <确认的版本号>"
254
+
255
+ # 4. 上线合并到 master(二选一):
256
+ #
257
+ # 方式 A:远端 PR 合并(默认,可走 code review)
258
+ git push origin hotfix/<问题描述>
259
+ # 在 GitHub/GitLab 创建 PR:hotfix/<问题描述> → master
260
+ # 标题示例:Hotfix: <问题描述>
261
+ # 等待 code review 通过后 merge
262
+ #
263
+ # 方式 B:本地直接合并 master(跳过远端 PR,适合紧急情况快速上线)
264
+ git push origin hotfix/<问题描述> # 先推送分支留档
265
+ git checkout master
266
+ git pull origin master
267
+ git merge --no-ff hotfix/<问题描述>
268
+ git push origin master
269
+
270
+ # 5. 上线合并完成后(无论方式 A 还是 B),以远端 origin/master 为基准同步 develop 和 dev-offline(三个分支对齐)
271
+ git fetch origin master # 先把 origin/master 引用刷新到线上最新
272
+ git checkout master
273
+ git merge --ff-only origin/master
274
+ git push origin master
275
+ git checkout develop
276
+ git pull origin develop
277
+ git merge origin/master
278
+ git push origin develop
279
+ git checkout dev-offline
280
+ git pull origin dev-offline
281
+ git merge origin/master
282
+ git push origin dev-offline
283
+
284
+ # 6. 删除 hotfix 分支
285
+ git branch -d hotfix/<问题描述>
286
+ git push origin --delete hotfix/<问题描述>
287
+ ```
288
+
289
+ **注意:** hotfix 上线合并后(无论 PR merge 还是本地直接合并)必须同步到 develop 和 dev-offline 两个分支,缺一不可。
290
+
291
+ ---
292
+
293
+ ## 场景四:同步到线下环境(dev-offline)
294
+
295
+ **触发词:** "同步线下"、"dev-offline"、"发到线下"
296
+
297
+ 先确认同步方式:
298
+
299
+ **方式 A:全量同步 develop 到 dev-offline**
300
+
301
+ ```bash
302
+ git checkout dev-offline
303
+ git pull origin dev-offline
304
+ git merge --no-ff develop
305
+ git push origin dev-offline
306
+ ```
307
+
308
+ **方式 B:仅同步指定 commit(cherry-pick)**
309
+
310
+ ```bash
311
+ git checkout dev-offline
312
+ git pull origin dev-offline
313
+ git cherry-pick <commit-hash> # 多个 commit 空格分隔,如:abc1234 def5678
314
+ git push origin dev-offline
315
+ ```
316
+
317
+ **注意:** dev-offline 是线下测试环境专用分支,merge 前确认不会覆盖该分支上的线下专属配置。如有冲突,以 dev-offline 上的配置为准。