@sppk/auto-git-flow 0.0.1

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.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # 🚀 Auto-Git-Flow (agf)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@sppk/auto-git-flow.svg)](https://www.npmjs.com/package/@sppk/auto-git-flow)
4
+ [![license](https://img.shields.io/badge/license-ISC-blue.svg)](./LICENSE)
5
+
6
+ **Auto-Git-Flow** 是一个专为团队协作设计的 Git 工作流自动化工具。它通过命令行交互(CLI)规范化分支命名,并自动处理繁琐的合并流程,防止人为错误,提升交付效率。
7
+
8
+ ---
9
+
10
+ ## ✨ 核心特性
11
+
12
+ - 🛠 **命名规范化**: 自动生成符合团队约定的 `feat/`, `DEV-`, `RELEASE-` 分支名称。
13
+ - 🔄 **合并自动化**: 一键同步基准分支、合并代码并推送到远程,减少手工误操作。
14
+ - 📋 **全景视图**: 快速查看当前项目的开发(Dev)与发布(Release)分支状态。
15
+ - 🛡 **安全检查**: 执行前自动检查工作区状态,确保代码提交安全。
16
+ - ⌨️ **交互式体验**: 基于 `@inquirer/prompts` 提供平滑的命令行交互。
17
+
18
+ ---
19
+
20
+ ## 📦 安装
21
+
22
+ ### 全局安装 (推荐)
23
+
24
+ ```bash
25
+ pnpm add -g @sppk/auto-git-flow
26
+ ```
27
+
28
+ ### 直接运行 (无需安装)
29
+
30
+ ```bash
31
+ pnpx agf --help
32
+ ```
33
+
34
+ ---
35
+
36
+ ## 🛠 常用命令
37
+
38
+ ### 1. 查看分支状态 `agf list`
39
+ 展示最近的开发分支与发布分支列表。
40
+ ```bash
41
+ agf list [count] # 默认查看最近 2 个
42
+ ```
43
+
44
+ ### 2. 创建新分支 `agf create`
45
+ 根据类型(Feature/Dev/Release)和需求号自动生成规范分支。
46
+ ```bash
47
+ agf create
48
+ ```
49
+
50
+ ### 3. 合并分支 `agf merge`
51
+ 将当前 Feature 分支自动同步基准代码并合并到指定的目标分支(Dev 或 Release)。
52
+ ```bash
53
+ agf merge [target] # target 为必填:dev 或 release。
54
+ ```
55
+
56
+ ## 📋 命名规范
57
+
58
+ 工具严格遵循以下命名约定:
59
+
60
+ - **Feature**: `feat/<username>-<date>-<reqNo>`
61
+ *示例: `feat/jack-20231024-QZ-8848`*
62
+ - **Dev**: `<project>-DEV-<date>`
63
+ *示例: `mall-DEV-20231024`*
64
+ - **Release**: `<project>-RELEASE-<date>`
65
+ *示例: `mall-RELEASE-20231024`*
66
+
67
+ ## 📐 工作流图解
68
+
69
+ ### 分支创建流程 (Create)
70
+ 如果是 `dev` 或 `release` 分支,会自动推送到远程并切回原分支;如果是 `feature` 分支,则留在新分支。
71
+
72
+ ```mermaid
73
+ graph TD
74
+ Start([开始创建]) --> CheckClean{检查工作区}
75
+ CheckClean -- 脏 --> Error([提示保存并退出])
76
+ CheckClean -- 干净 --> Fetch[获取远程更新]
77
+ Fetch --> Config[采集配置: 类型/日期/需求号]
78
+ Config --> Name[生成规范名称]
79
+ Name --> Checkout[从 Base 分支创建并切换]
80
+ Checkout --> TypeCheck{分支类型?}
81
+
82
+ TypeCheck -- Feature --> DoneFeature([切到新分支, 完成])
83
+ TypeCheck -- Dev/Release --> Push[推送到远程]
84
+ Push --> Back[切回原分支]
85
+ Back --> DoneOther([完成])
86
+ ```
87
+
88
+ ### 分支合并流程 (Merge)
89
+ 将当前特性分支合并到目标环境。会自动先同步 `Release` 与 `Dev`、`Main` 分支的代码,确保环境一致性。
90
+
91
+ ```mermaid
92
+ graph TD
93
+ Start([开始合并]) --> CheckClean{检查工作区}
94
+ CheckClean -- 脏 --> Error([提示保存并退出])
95
+ CheckClean -- 干净 --> CheckType{当前是 Feature?}
96
+
97
+ CheckType -- 否 --> ErrorType([只允许从 Feature 发起])
98
+ CheckType -- 是 --> FindTarget[定位目标分支]
99
+
100
+ FindTarget --> Exist{目标分支存在?}
101
+ Exist -- 否 --> CreateNew[引导创建并推送]
102
+ Exist -- 是 --> Sync[同步目标与基准分支]
103
+
104
+ CreateNew --> Sync
105
+ Sync --> Confirm{如果是 Release?}
106
+ Confirm -- 是 --> UserConfirm[二次人工确认]
107
+ Confirm -- 否 --> DoMerge
108
+
109
+ UserConfirm -- 取消 --> End([结束])
110
+ UserConfirm -- 确认 --> DoMerge[执行合并]
111
+
112
+ DoMerge --> MergeBase[基准 -> 目标]
113
+ MergeBase --> MergeFeat[Feature -> 目标]
114
+ MergeFeat --> Push[推送目标分支]
115
+ Push --> Back[切回 Feature 分支]
116
+ Back --> Done([合并完成])
117
+
118
+ classDef highlight fill:#f96,stroke:#333,stroke-width:2px
119
+ class MergeBase,UserConfirm highlight
120
+ ```
121
+
122
+
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{Command as H}from"commander";import{input as G,select as O}from"@inquirer/prompts";import{format as _}from"date-fns";import{simpleGit as Z}from"simple-git";import C from"chalk";var i=Z();async function T(){if(!(await i.status()).isClean())throw new Error("\u274C \u5DE5\u4F5C\u533A\u6709\u672A\u63D0\u4EA4\u7684\u4EE3\u7801\uFF0C\u8BF7\u5148 Commit \u6216 Stash\u3002")}async function U(){let e=await i.getConfig("user.name");if(!e.value)throw new Error("\u274C \u83B7\u53D6\u4E0D\u5230\u7528\u6237\u540D\uFF0C\u8BF7\u6267\u884C git config user.name \u914D\u7F6E\u3002");return e.value}async function u(){console.log(C.gray("\u6B63\u5728\u62C9\u53D6\u8FDC\u7A0B\u6700\u65B0\u5206\u652F\u5217\u8868...")),await i.fetch(["--prune"])}async function w(){return(await i.branch()).current}async function d(e,t=!1,a){t?a?await i.checkout(["-b",e,a]):await i.checkoutLocalBranch(e):await i.checkout(e)}async function v(e,t){try{await i.merge([t])}catch{throw new Error(`\u26A0\uFE0F \u53D1\u751F\u4EE3\u7801\u51B2\u7A81\uFF01\u4ECE ${t} \u5408\u5E76\u5230 ${e} \u5931\u8D25\u3002
3
+ \u8BF7\u624B\u52A8\u89E3\u51B3\u51B2\u7A81\u6587\u4EF6\u5E76\u63D0\u4EA4\uFF0C\u7136\u540E\u5207\u6362\u56DE\u539F\u5206\u652F\u3002`)}}async function x(e){await i.push(["-u","origin",e])}async function L(e){let t=await i.branch();if(t.all.includes(e))console.log(C.gray(`\u6B63\u5728\u66F4\u65B0\u672C\u5730\u5206\u652F ${e}...`)),await i.checkout(e),await i.pull("origin",e);else if(t.all.includes(`remotes/origin/${e}`))console.log(C.gray(`\u6B63\u5728\u4ECE\u8FDC\u7A0B\u62C9\u53D6\u5206\u652F ${e}...`)),await i.checkout(["-b",e,`origin/${e}`]);else throw new Error(`\u274C \u9519\u8BEF: \u8FDC\u7A0B\u4E0D\u5B58\u5728\u5206\u652F ${e}`)}async function h(){let e=await i.branch(["-a"]);return Array.from(new Set(e.all.map(t=>t.replace("remotes/origin/",""))))}import{compareDesc as M,compareAsc as N,parse as F}from"date-fns";var b=/^QZ-\d{4}$/;function $(e){let t=e.match(/^(.+)-RELEASE-(\d{8})$/);if(t)return{name:e,type:"RELEASE",project:t[1],date:F(t[2],"yyyyMMdd",new Date)};let a=e.match(/^(.+)-(?:DEV|dev)-(\d{8})$/);if(a)return{name:e,type:"DEV",project:a[1],date:F(a[2],"yyyyMMdd",new Date)};let n=e.match(/^feat\/(.+)-(\d{8})-(QZ-\d{4})$/);return n?{name:e,type:"FEATURE",date:F(n[2],"yyyyMMdd",new Date)}:null}function D(e){return e.map($).filter(a=>a?.type==="RELEASE").sort((a,n)=>M(a.date,n.date))[0]||null}function j(e){return e.map($).filter(a=>a?.type==="RELEASE").sort((a,n)=>M(a.date,n.date))[1]||null}function S(e,t){let a=new Date,n=new Date(a.getFullYear(),a.getMonth(),a.getDate());return e.map($).filter(s=>s?.type===t&&!!s.date).filter(s=>s.date>=n).sort((s,c)=>N(s.date,c.date))[0]||null}function k(e,t,a){return e.map($).filter(n=>n?.type===t).sort((n,o)=>M(n.date,o.date)).slice(0,a)}import l from"chalk";var m=l.gray("\u2502"),r={header:e=>{console.log(`
4
+ ${l.bgCyan.black.bold(" GIT-FLOW ")} ${l.cyan.bold(e)}`),console.log(m)},info:e=>console.log(`${m} ${l.blue("\u2139")} ${e}`),step:e=>{process.stdout.write(`${m} ${l.yellow("\u279C")} ${e}`)},success:e=>console.log(`${m} ${l.green("\u2714")} ${e}`),done:()=>{process.stdout.write(l.green(` [OK]
5
+ `))},warn:e=>console.log(`${m} ${l.yellow("\u26A0")} ${e}`),error:e=>console.error(`${m} ${l.red("\u2718")} ${e}`),errorRaw:e=>console.error(`${m} ${l.red(e)}`),dim:e=>console.log(`${m} ${l.gray(e)}`),dimRaw:e=>{process.stdout.write(`${m} ${l.gray(e)}`)},footer:()=>console.log(m+`
6
+ `)};async function q(e){let t=await w(),a=await h(),n=D(a),o=n?.name||t;r.info(`\u5F53\u524D\u5206\u652F: ${t}`),n?r.info(`\u57FA\u51C6\u5206\u652F: ${n.name}`):r.warn("\u672A\u627E\u5230 Release \u5206\u652F\uFF0C\u5C06\u4EE5\u5F53\u524D\u5206\u652F\u4E3A\u57FA\u51C6");let s=e||await O({message:"\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u7684\u5206\u652F\u7C7B\u578B:",choices:[{name:"Feature (\u7279\u6027\u5F00\u53D1)",value:"FEATURE"},{name:"Dev (\u6D4B\u8BD5\u73AF\u5883)",value:"DEV"},{name:"Release (\u751F\u4EA7\u73AF\u5883)",value:"RELEASE"}]}),c=n?.project||"mall",f=_(new Date,"yyyyMMdd"),g=await G({message:`\u8BF7\u8F93\u5165\u65E5\u671F (\u683C\u5F0F: YYYYMMDD, \u9ED8\u8BA4: ${f}):`,default:f,validate:p=>/^\d{8}$/.test(p)?p<f?`\u274C \u65E5\u671F\u8FC7\u65E9: \u65E5\u671F\u5FC5\u987B\u5927\u4E8E\u6216\u7B49\u4E8E\u5F53\u524D\u65E5\u671F (${f})`:!0:"\u274C \u683C\u5F0F\u9519\u8BEF: \u8BF7\u8F93\u51658\u4F4D\u6570\u5B57\u65E5\u671F"}),R;return s==="FEATURE"&&(R=await G({message:"\u8BF7\u8F93\u5165\u9700\u6C42\u7F16\u53F7 (\u4F8B\u5982 QZ-8848):",validate:p=>b.test(p)||"\u274C \u683C\u5F0F\u9519\u8BEF: \u9700\u6C42\u7F16\u53F7\u5FC5\u987B\u4E3A QZ \u540E\u63A54\u4F4D\u6570\u5B57 (\u5982 QZ-8848)"})),{type:s,baseBranch:o,project:c,date:g,reqNo:R}}async function I(e){try{r.header("\u521B\u5EFA\u5206\u652F"),await T(),await u();let t=await w(),a=await q(e),{type:n,baseBranch:o,project:s,date:c,reqNo:f}=a,g;n==="FEATURE"?g=`feat/${await U()}-${c}-${f}`:g=`${s}-${n}-${c}`,r.step(`\u6B63\u5728\u4ECE ${o} \u521B\u5EFA ${g}...`),await d(g,!0,o),n!=="FEATURE"&&await x(g),r.done(),n==="FEATURE"?r.success("\u5206\u652F\u521B\u5EFA\u6210\u529F\uFF0C\u5DF2\u5207\u6362\u81F3\u8BE5\u5206\u652F"):(r.success("\u5206\u652F\u521B\u5EFA\u6210\u529F\u5E76\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B"),t!==await w()&&(r.dimRaw(`\u6B63\u5728\u5207\u56DE\u539F\u5206\u652F ${t}...`),await d(t),r.done())),r.footer()}catch(t){r.errorRaw(t.message),r.footer()}}import{confirm as V}from"@inquirer/prompts";async function X(e){await u();let t=await h(),a=S(t,e);if(a||(r.warn(`\u672A\u627E\u5230\u53EF\u7528\u7684 ${e} \u5206\u652F\uFF08\u9700\u4E3A\u4ECA\u65E5\u6216\u672A\u6765\u65F6\u95F4\uFF09\u3002`),await V({message:`\u786E\u5B9A\u8981\u73B0\u5728\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684 ${e} \u5206\u652F\u5417\uFF1F`,default:!0})&&(await I(e),await u(),t=await h(),a=S(t,e))),!a)throw new Error(`\u7EC8\u6B62: \u672A\u80FD\u5B9A\u4F4D\u5230\u6709\u6548\u7684 ${e} \u76EE\u6807\u5206\u652F\u3002`);return a}async function K(e,t){r.step("\u6B63\u5728\u540C\u6B65\u8FDC\u7A0B\u4EE3\u7801..."),await L(e.name),t&&await L(t.name),r.done(),t&&e.name!==t.name&&(r.step(`\u6B63\u5728\u540C\u6B65\u57FA\u51C6 ${t.name} -> ${e.name}...`),await d(e.name),await v(e.name,t.name),r.done())}async function Q(e){let t=await w();try{await T(),r.header("\u5408\u5E76\u5206\u652F"),await u();let a=$(t);if(!a||a.type!=="FEATURE")throw new Error("\u7981\u6B62\u64CD\u4F5C\uFF1A\u8BF7\u5148\u5207\u6362\u5230 Feature \u5206\u652F\u518D\u6267\u884C\u5408\u5E76\u3002");let n=e==="dev"?"DEV":e==="release"?"RELEASE":null;if(!n)throw new Error("\u9519\u8BEF\u53C2\u6570\uFF1A\u8BF7\u6307\u5B9A\u5408\u5E76\u76EE\u6807 (dev \u6216 release)\u3002");r.info(`\u5F53\u524D\u5206\u652F: ${t}`);let o=await X(n),s=await h(),c=n==="DEV"?D(s):j(s);if(r.info(`\u76EE\u6807\u73AF\u5883: ${o.name}${c?` (\u57FA\u51C6: ${c.name})`:""}`),n==="RELEASE"&&!await V({message:`\u26A0\uFE0F \u786E\u5B9A\u8981\u5C06\u7279\u6027\u5206\u652F\u5408\u5E76\u5230\u751F\u4EA7\u73AF\u5883 ${o.name} \u5417\uFF1F`,default:!1})){r.dim("\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002"),r.footer();return}await K(o,c),r.step(`\u6B63\u5728\u5408\u5E76 Feature \u5230 ${o.name}...`),await d(o.name),await v(o.name,t),r.done(),r.step("\u6B63\u5728\u63A8\u9001\u5230\u8FDC\u7A0B..."),await x(o.name),r.done(),await d(t),r.success(`\u6210\u529F\uFF01Feature \u5DF2\u5408\u5E76\u81F3 ${o.name} \u5E76\u63A8\u9001\u5230 origin\u3002`),r.dim(`\u5DF2\u81EA\u52A8\u5207\u56DE ${t}`),r.footer()}catch(a){r.errorRaw(a.message),await w()!==t&&r.warn(`\u6D41\u7A0B\u4E2D\u65AD\uFF0C\u7531\u4E8E\u4EE3\u7801\u51B2\u7A81\u6216\u5176\u4ED6\u9519\u8BEF\uFF0C\u8BF7\u624B\u52A8\u5904\u7406\u540E\u5207\u56DE ${t}\u3002`),r.footer()}}import W from"cli-table3";import B from"chalk";import{format as z}from"date-fns";async function Y(e){try{await u();let t=await h(),a=parseInt(e,10),n=k(t,"RELEASE",a),o=k(t,"DEV",a);r.header(`\u5206\u652F\u5217\u8868 (Latest ${a})`);let s=new W({head:[B.cyan("Type"),B.cyan("Branch Name"),B.cyan("Date"),B.cyan("Project")],style:{head:[],border:[]}}),c=(f,g,R)=>{f.forEach(p=>{s.push([R(g),p.name,p.date?z(p.date,"yyyy-MM-dd"):"-",p.project||"-"])})};if(c(n,"Release",B.green),c(o,"Dev",B.yellow),s.length===0){r.warn("\u672A\u53D1\u73B0\u7B26\u5408\u89C4\u8303\u7684 dev \u6216 release \u5206\u652F\u3002"),r.footer();return}console.log(s.toString()),r.footer()}catch(t){r.errorRaw(`\u83B7\u53D6\u5206\u652F\u5217\u8868\u5931\u8D25: ${t.message}`),r.footer()}}var A=new H;A.name("agf").description("Auto Git Flow CLI - \u81EA\u52A8\u5316 Git \u5206\u652F\u7BA1\u7406\u5DE5\u5177").version("1.0.0");A.command("create").description("\u521B\u5EFA\u65B0\u5206\u652F (Release, Dev, Feature)").action(I);A.command("merge").description("\u5408\u5E76\u5206\u652F (Safe-Merge \u7B56\u7565)").argument("<target>","\u76EE\u6807\u73AF\u5883 (dev \u6216 release)").action(Q);A.command("list").description("\u67E5\u770B\u6700\u65B0\u7684 dev \u548C release \u5206\u652F").argument("[count]","\u5217\u51FA\u7684\u5206\u652F\u4E2A\u6570 (\u9ED8\u8BA4 2)","2").action(Y);A.parse();
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/utils/git.ts","../src/utils/branch.ts","../src/utils/ui.ts","../src/commands/merge.ts","../src/commands/list.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { createAction } from './commands/create.js';\nimport { mergeAction } from './commands/merge.js';\nimport { listAction } from './commands/list.js';\n\nconst program = new Command();\n\nprogram\n .name('agf')\n .description('Auto Git Flow CLI - 自动化 Git 分支管理工具')\n .version('1.0.0');\n\nprogram\n .command('create')\n .description('创建新分支 (Release, Dev, Feature)')\n .action(createAction);\n\nprogram\n .command('merge')\n .description('合并分支 (Safe-Merge 策略)')\n .argument('<target>', '目标环境 (dev 或 release)')\n .action(mergeAction);\n\nprogram\n .command('list')\n .description('查看最新的 dev 和 release 分支')\n .argument('[count]', '列出的分支个数 (默认 2)', '2')\n .action(listAction);\n\nprogram.parse();\n","import { input, select } from '@inquirer/prompts';\nimport { format } from 'date-fns';\nimport { \n checkClean, \n fetchRemote, \n getBranches, \n getUserName, \n checkout, \n push,\n getCurrentBranch\n} from '../utils/git.js';\nimport { \n getLatestRelease, \n REQ_NO_REGEX, \n BranchType \n} from '../utils/branch.js';\nimport { logger } from '../utils/ui.js';\n\ninterface CreateConfig {\n type: BranchType;\n baseBranch: string;\n project: string;\n date: string;\n reqNo?: string | undefined;\n}\n\nasync function getCreateConfig(forcedType?: BranchType): Promise<CreateConfig> {\n const originalBranch = await getCurrentBranch();\n const branches = await getBranches();\n const latestRelease = getLatestRelease(branches);\n const baseBranch = latestRelease?.name || originalBranch;\n\n logger.info(`当前分支: ${originalBranch}`);\n if (latestRelease) {\n logger.info(`基准分支: ${latestRelease.name}`);\n } else {\n logger.warn('未找到 Release 分支,将以当前分支为基准');\n }\n\n const type = forcedType || await select({\n message: '请选择要创建的分支类型:',\n choices: [\n { name: 'Feature (特性开发)', value: BranchType.FEATURE },\n { name: 'Dev (测试环境)', value: BranchType.DEV },\n { name: 'Release (生产环境)', value: BranchType.RELEASE },\n ],\n });\n\n const project = latestRelease?.project || 'mall';\n const today = format(new Date(), 'yyyyMMdd');\n\n const dateInput = await input({\n message: `请输入日期 (格式: YYYYMMDD, 默认: ${today}):`,\n default: today,\n validate: (value) => {\n if (!/^\\d{8}$/.test(value)) return '❌ 格式错误: 请输入8位数字日期';\n if (value < today) return `❌ 日期过早: 日期必须大于或等于当前日期 (${today})`;\n return true;\n },\n });\n\n let reqNo;\n if (type === BranchType.FEATURE) {\n reqNo = await input({\n message: '请输入需求编号 (例如 QZ-8848):',\n validate: (input) => REQ_NO_REGEX.test(input) || '❌ 格式错误: 需求编号必须为 QZ 后接4位数字 (如 QZ-8848)',\n });\n }\n\n return { type, baseBranch, project, date: dateInput, reqNo };\n}\n\nexport async function createAction(forcedType?: BranchType) {\n try {\n logger.header('创建分支');\n await checkClean();\n await fetchRemote();\n\n const originalBranch = await getCurrentBranch();\n const config = await getCreateConfig(forcedType);\n const { type, baseBranch, project, date, reqNo } = config;\n\n let branchName: string;\n if (type === BranchType.FEATURE) {\n const user = await getUserName();\n branchName = `feat/${user}-${date}-${reqNo}`;\n } else {\n branchName = `${project}-${type}-${date}`;\n }\n\n logger.step(`正在从 ${baseBranch} 创建 ${branchName}...`);\n await checkout(branchName, true, baseBranch);\n \n if (type !== BranchType.FEATURE) {\n await push(branchName);\n }\n logger.done();\n\n if (type === BranchType.FEATURE) {\n logger.success('分支创建成功,已切换至该分支');\n } else {\n logger.success('分支创建成功并已推送到远程');\n \n // 非特性分支创建后切回原分支\n if (originalBranch !== (await getCurrentBranch())) {\n logger.dimRaw(`正在切回原分支 ${originalBranch}...`);\n await checkout(originalBranch);\n logger.done();\n }\n }\n\n logger.footer();\n\n } catch (err: any) {\n logger.errorRaw(err.message);\n logger.footer();\n }\n}\n","import { simpleGit, type SimpleGit } from 'simple-git';\nimport chalk from 'chalk';\n\nconst git: SimpleGit = simpleGit();\n\nexport async function checkClean() {\n const status = await git.status();\n if (!status.isClean()) {\n throw new Error('❌ 工作区有未提交的代码,请先 Commit 或 Stash。');\n }\n}\n\nexport async function getUserName(): Promise<string> {\n const name = await git.getConfig('user.name');\n if (!name.value) {\n throw new Error('❌ 获取不到用户名,请执行 git config user.name 配置。');\n }\n return name.value;\n}\n\nexport async function fetchRemote() {\n console.log(chalk.gray('正在拉取远程最新分支列表...'));\n await git.fetch(['--prune']);\n}\n\nexport async function getCurrentBranch(): Promise<string> {\n const branchInfo = await git.branch();\n return branchInfo.current;\n}\n\nexport async function checkout(branch: string, create = false, startPoint?: string) {\n if (create) {\n if (startPoint) {\n await git.checkout(['-b', branch, startPoint]);\n } else {\n await git.checkoutLocalBranch(branch);\n }\n } else {\n await git.checkout(branch);\n }\n}\n\nexport async function merge(target: string, source: string) {\n try {\n await git.merge([source]);\n } catch (err: any) {\n throw new Error(`⚠️ 发生代码冲突!从 ${source} 合并到 ${target} 失败。\\n请手动解决冲突文件并提交,然后切换回原分支。`);\n }\n}\n\nexport async function push(branch: string) {\n await git.push(['-u', 'origin', branch]);\n}\n\nexport async function pullBranch(branch: string) {\n const branches = await git.branch();\n const isLocal = branches.all.includes(branch);\n \n if (!isLocal) {\n // Check if remote exists\n const remoteExists = branches.all.includes(`remotes/origin/${branch}`);\n if (remoteExists) {\n console.log(chalk.gray(`正在从远程拉取分支 ${branch}...`));\n await git.checkout(['-b', branch, `origin/${branch}`]);\n } else {\n throw new Error(`❌ 错误: 远程不存在分支 ${branch}`);\n }\n } else {\n console.log(chalk.gray(`正在更新本地分支 ${branch}...`));\n await git.checkout(branch);\n await git.pull('origin', branch);\n }\n}\n\nexport async function getBranches() {\n const summary = await git.branch(['-a']);\n return Array.from(new Set(summary.all.map(b => b.replace('remotes/origin/', ''))));\n}\n\nexport { git };\n","import { compareDesc, compareAsc, parse } from 'date-fns';\n\nexport enum BranchType {\n RELEASE = 'RELEASE',\n DEV = 'DEV',\n FEATURE = 'FEATURE'\n}\n\nexport const REQ_NO_REGEX = /^QZ-\\d{4}$/;\n\nexport interface BranchInfo {\n name: string;\n type: BranchType;\n date?: Date;\n project?: string;\n}\n\nexport function parseBranch(branchName: string): BranchInfo | null {\n // Release: {project}-RELEASE-{YYYYMMDD}\n const releaseMatch = branchName.match(/^(.+)-RELEASE-(\\d{8})$/);\n if (releaseMatch) {\n return {\n name: branchName,\n type: BranchType.RELEASE,\n project: releaseMatch[1]!,\n date: parse(releaseMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n // Dev: {project}-DEV-{YYYYMMDD}\n // {project}-dev-{YYYYMMDD}\n const devMatch = branchName.match(/^(.+)-(?:DEV|dev)-(\\d{8})$/);\n if (devMatch) {\n return {\n name: branchName,\n type: BranchType.DEV,\n project: devMatch[1]!,\n date: parse(devMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n // Feature: feat/{user}-{date}-{reqNo}\n const featMatch = branchName.match(/^feat\\/(.+)-(\\d{8})-(QZ-\\d{4})$/);\n if (featMatch) {\n return {\n name: branchName,\n type: BranchType.FEATURE,\n date: parse(featMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n return null;\n}\n\nexport function getLatestRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!));\n\n return releases[0] || null;\n}\n\nexport function getPreviousRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!));\n\n return releases[1] || null;\n}\n\nexport function getTargetBranch(branches: string[], type: BranchType): BranchInfo | null {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // Start of today\n\n const targets = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type && !!b.date)\n .filter(b => b.date! >= today) // Only today or future\n .sort((a, b) => compareAsc(a.date!, b.date!));\n\n return targets[0] || null; // Return the earliest one (which is the closest to today)\n}\nexport function getLatestBranches(branches: string[], type: BranchType, limit: number): BranchInfo[] {\n return branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type)\n .sort((a, b) => compareDesc(a.date!, b.date!))\n .slice(0, limit);\n}\n","import chalk from 'chalk';\n\nconst PREFIX = chalk.gray('│');\n\nexport const logger = {\n header: (title: string) => {\n console.log(`\\n${chalk.bgCyan.black.bold(' GIT-FLOW ')} ${chalk.cyan.bold(title)}`);\n console.log(PREFIX);\n },\n info: (msg: string) => console.log(`${PREFIX} ${chalk.blue('ℹ')} ${msg}`),\n step: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.yellow('➜')} ${msg}`);\n },\n success: (msg: string) => console.log(`${PREFIX} ${chalk.green('✔')} ${msg}`),\n done: () => {\n process.stdout.write(chalk.green(' [OK]\\n'));\n },\n warn: (msg: string) => console.log(`${PREFIX} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${PREFIX} ${chalk.red('✘')} ${msg}`),\n errorRaw: (msg: string) => console.error(`${PREFIX} ${chalk.red(msg)}`),\n dim: (msg: string) => console.log(`${PREFIX} ${chalk.gray(msg)}`),\n dimRaw: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.gray(msg)}`);\n },\n footer: () => console.log(PREFIX + '\\n'),\n};\n","import { confirm } from '@inquirer/prompts';\nimport { \n checkClean, \n fetchRemote, \n getBranches, \n getCurrentBranch, \n checkout, \n merge, \n push,\n pullBranch\n} from '../utils/git.js';\nimport { \n getTargetBranch, \n getLatestRelease, \n getPreviousRelease,\n parseBranch, \n BranchType,\n type BranchInfo\n} from '../utils/branch.js';\nimport { createAction } from './create.js';\nimport { logger } from '../utils/ui.js';\n\n/**\n * 确保目标分支存在,如果不存在则引导用户创建\n */\nasync function ensureTargetBranch(type: BranchType): Promise<BranchInfo> {\n await fetchRemote();\n let branches = await getBranches();\n let target = getTargetBranch(branches, type);\n\n if (!target) {\n logger.warn(`未找到可用的 ${type} 分支(需为今日或未来时间)。`);\n const shouldCreate = await confirm({\n message: `确定要现在创建一个新的 ${type} 分支吗?`,\n default: true\n });\n\n if (shouldCreate) {\n await createAction(type);\n await fetchRemote();\n branches = await getBranches();\n target = getTargetBranch(branches, type);\n }\n }\n\n if (!target) {\n throw new Error(`终止: 未能定位到有效的 ${type} 目标分支。`);\n }\n\n return target;\n}\n\n/**\n * 执行同步逻辑:拉取远程最新代码并同步基准分支\n */\nasync function syncAndPrepare(target: BranchInfo, base: BranchInfo | null) {\n logger.step('正在同步远程代码...');\n await pullBranch(target.name);\n if (base) {\n await pullBranch(base.name);\n }\n logger.done();\n\n if (base && target.name !== base.name) {\n logger.step(`正在同步基准 ${base.name} -> ${target.name}...`);\n await checkout(target.name);\n await merge(target.name, base.name);\n logger.done();\n }\n}\n\nexport async function mergeAction(targetArg?: string) {\n const originalBranch = await getCurrentBranch();\n \n try {\n await checkClean();\n logger.header('合并分支');\n await fetchRemote();\n\n // 1. 语法校验与状态检查\n const currentInfo = parseBranch(originalBranch);\n if (!currentInfo || currentInfo.type !== BranchType.FEATURE) {\n throw new Error('禁止操作:请先切换到 Feature 分支再执行合并。');\n }\n\n const targetType = targetArg === 'dev' ? BranchType.DEV : \n targetArg === 'release' ? BranchType.RELEASE : null;\n \n if (!targetType) {\n throw new Error('错误参数:请指定合并目标 (dev 或 release)。');\n }\n\n logger.info(`当前分支: ${originalBranch}`);\n\n // 2. 定位目标与基准\n const targetBranch = await ensureTargetBranch(targetType);\n const branches = await getBranches();\n const baseBranch = targetType === BranchType.DEV ? getLatestRelease(branches) : getPreviousRelease(branches);\n\n logger.info(`目标环境: ${targetBranch.name}${baseBranch ? ` (基准: ${baseBranch.name})` : ''}`);\n\n // 3. 二次确认 (Release)\n if (targetType === BranchType.RELEASE) {\n const isConfirmed = await confirm({\n message: `⚠️ 确定要将特性分支合并到生产环境 ${targetBranch.name} 吗?`,\n default: false,\n });\n if (!isConfirmed) {\n logger.dim('操作已取消。');\n logger.footer();\n return;\n }\n }\n\n // 4. 同步与合并\n await syncAndPrepare(targetBranch, baseBranch);\n\n logger.step(`正在合并 Feature 到 ${targetBranch.name}...`);\n await checkout(targetBranch.name);\n await merge(targetBranch.name, originalBranch);\n logger.done();\n \n logger.step('正在推送到远程...');\n await push(targetBranch.name);\n logger.done();\n\n // 5. 还原\n await checkout(originalBranch);\n logger.success(`成功!Feature 已合并至 ${targetBranch.name} 并推送到 origin。`);\n logger.dim(`已自动切回 ${originalBranch}`);\n \n logger.footer();\n\n } catch (err: any) {\n logger.errorRaw(err.message);\n const nowBranch = await getCurrentBranch();\n if (nowBranch !== originalBranch) {\n logger.warn(`流程中断,由于代码冲突或其他错误,请手动处理后切回 ${originalBranch}。`);\n }\n logger.footer();\n }\n}\n","import Table from 'cli-table3';\nimport chalk from 'chalk';\nimport { getBranches, fetchRemote } from '../utils/git.js';\nimport { BranchType, getLatestBranches, type BranchInfo } from '../utils/branch.js';\nimport { format } from 'date-fns';\nimport { logger } from '../utils/ui.js';\n\nexport async function listAction(count: string) {\n try {\n await fetchRemote();\n const branches = await getBranches();\n\n const limit = parseInt(count, 10);\n const latestRelease = getLatestBranches(branches, BranchType.RELEASE, limit);\n const latestDev = getLatestBranches(branches, BranchType.DEV, limit);\n\n logger.header(`分支列表 (Latest ${limit})`);\n\n const table = new Table({\n head: [chalk.cyan('Type'), chalk.cyan('Branch Name'), chalk.cyan('Date'), chalk.cyan('Project')],\n style: {\n head: [],\n border: [],\n }\n });\n\n const addRows = (branchInfos: BranchInfo[], typeName: string, color: (s: string) => string) => {\n branchInfos.forEach(info => {\n table.push([\n color(typeName),\n info.name,\n info.date ? format(info.date, 'yyyy-MM-dd') : '-',\n info.project || '-'\n ]);\n });\n };\n\n addRows(latestRelease, 'Release', chalk.green);\n addRows(latestDev, 'Dev', chalk.yellow);\n\n if (table.length === 0) {\n logger.warn('未发现符合规范的 dev 或 release 分支。');\n logger.footer();\n return;\n }\n\n console.log(table.toString());\n logger.footer();\n\n } catch (error: any) {\n logger.errorRaw(`获取分支列表失败: ${error.message}`);\n logger.footer();\n }\n}\n"],"mappings":"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","names":["Command","input","select","format","simpleGit","chalk","git","checkClean","getUserName","name","fetchRemote","getCurrentBranch","checkout","branch","create","startPoint","merge","target","source","push","pullBranch","branches","getBranches","summary","b","compareDesc","compareAsc","parse","REQ_NO_REGEX","parseBranch","branchName","releaseMatch","parse","devMatch","featMatch","getLatestRelease","branches","b","compareDesc","getPreviousRelease","getTargetBranch","type","now","today","a","compareAsc","getLatestBranches","limit","chalk","PREFIX","logger","title","msg","getCreateConfig","forcedType","originalBranch","getCurrentBranch","branches","getBranches","latestRelease","getLatestRelease","baseBranch","logger","type","select","project","today","format","dateInput","input","value","reqNo","REQ_NO_REGEX","createAction","checkClean","fetchRemote","config","date","branchName","getUserName","checkout","push","err","confirm","ensureTargetBranch","type","fetchRemote","branches","getBranches","target","getTargetBranch","logger","confirm","createAction","syncAndPrepare","base","pullBranch","checkout","merge","mergeAction","targetArg","originalBranch","getCurrentBranch","checkClean","currentInfo","parseBranch","targetType","targetBranch","baseBranch","getLatestRelease","getPreviousRelease","push","err","Table","chalk","format","listAction","count","fetchRemote","branches","getBranches","limit","latestRelease","getLatestBranches","latestDev","logger","table","Table","chalk","addRows","branchInfos","typeName","color","info","format","error","program","Command","createAction","mergeAction","listAction"]}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@sppk/auto-git-flow",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "type": "module",
6
+ "bin": {
7
+ "agf": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "dev": "tsx src/index.ts",
15
+ "build": "tsup",
16
+ "prepublishOnly": "pnpm build"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "keywords": [],
22
+ "author": "",
23
+ "license": "ISC",
24
+ "packageManager": "pnpm@10.8.0",
25
+ "devDependencies": {
26
+ "@types/node": "^25.0.3",
27
+ "tsup": "^8.5.1",
28
+ "tsx": "^4.21.0",
29
+ "typescript": "^5.9.3"
30
+ },
31
+ "dependencies": {
32
+ "@inquirer/prompts": "^8.1.0",
33
+ "chalk": "^5.6.2",
34
+ "cli-table3": "^0.6.5",
35
+ "commander": "^14.0.2",
36
+ "date-fns": "^4.1.0",
37
+ "simple-git": "^3.30.0"
38
+ }
39
+ }