ai-git-tool 1.1.0 → 1.3.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.
- package/README.md +172 -67
- package/dist/commands/checkout.js +30 -0
- package/dist/commands/commit.js +55 -0
- package/dist/commands/pr.js +74 -0
- package/dist/commands/push.js +78 -0
- package/dist/index.js +37 -933
- package/dist/services/ai.js +520 -0
- package/dist/services/branch.js +37 -0
- package/dist/services/github.js +332 -0
- package/dist/types.js +2 -0
- package/dist/utils/config.js +98 -0
- package/dist/utils/errors.js +81 -0
- package/dist/utils/git.js +157 -0
- package/dist/utils/text.js +23 -0
- package/dist/utils/ui.js +73 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,122 +1,154 @@
|
|
|
1
|
-
# ai-git
|
|
1
|
+
# ai-git-tool
|
|
2
2
|
|
|
3
3
|
Groq API を使って、ステージ済み差分からコミットメッセージと PR 説明文を自動生成する TypeScript 製 CLI です。
|
|
4
4
|
|
|
5
|
-
## 必要環境
|
|
6
|
-
|
|
7
|
-
- Node.js `18` 以上
|
|
8
|
-
- `git`
|
|
9
|
-
- Groq API キー(`GROQ_API_KEY`)
|
|
10
|
-
|
|
11
5
|
## セットアップ
|
|
12
6
|
|
|
13
|
-
### npm からインストール(推奨)
|
|
14
|
-
|
|
15
7
|
```bash
|
|
16
8
|
npm install -g ai-git-tool
|
|
17
9
|
```
|
|
18
10
|
|
|
19
|
-
###
|
|
11
|
+
### 環境変数
|
|
12
|
+
|
|
13
|
+
API キーの取得先: [Groq Console](https://console.groq.com/keys)
|
|
14
|
+
|
|
15
|
+
**macOS / Linux (bash/zsh):**
|
|
20
16
|
|
|
21
17
|
```bash
|
|
22
|
-
|
|
23
|
-
npm run build
|
|
24
|
-
npm link
|
|
18
|
+
export GROQ_API_KEY="your_api_key"
|
|
25
19
|
```
|
|
26
20
|
|
|
27
|
-
|
|
21
|
+
永続化する場合は `~/.bashrc` や `~/.zshrc` に追記してください。
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
**Windows (コマンドプロンプト):**
|
|
30
24
|
|
|
31
|
-
```
|
|
32
|
-
|
|
25
|
+
```cmd
|
|
26
|
+
setx GROQ_API_KEY "your_api_key"
|
|
33
27
|
```
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
**Windows (PowerShell):**
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
[System.Environment]::SetEnvironmentVariable("GROQ_API_KEY", "your_api_key", "User")
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
> `setx` / `SetEnvironmentVariable` はユーザー環境変数として永続保存されます。設定後は**ターミナルを再起動**してください。
|
|
36
|
+
|
|
37
|
+
**Windows (Git Bash):**
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
|
-
export
|
|
40
|
+
echo 'export GROQ_API_KEY="your_api_key"' >> ~/.bashrc
|
|
41
|
+
source ~/.bashrc
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
任意でモデル指定も可能です(デフォルト: `Llama 3.3 70B Versatile`)。
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# macOS / Linux / Git Bash
|
|
48
|
+
export GROQ_MODEL="llama-3.3-70b-versatile"
|
|
49
|
+
|
|
50
|
+
# Windows コマンドプロンプト
|
|
51
|
+
setx GROQ_MODEL "llama-3.3-70b-versatile"
|
|
52
|
+
```
|
|
42
53
|
|
|
43
54
|
## 使い方
|
|
44
55
|
|
|
45
56
|
### コミットメッセージ生成
|
|
46
57
|
|
|
47
|
-
1. コミットメッセージを生成
|
|
48
|
-
|
|
49
58
|
```bash
|
|
50
|
-
# 通常(タイトル + 箇条書き本文)
|
|
51
59
|
ai-git commit
|
|
52
60
|
```
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
デフォルトで `git add .` を実行してからコミットメッセージを生成します。
|
|
55
63
|
|
|
56
64
|
```bash
|
|
57
|
-
#
|
|
65
|
+
# 手動でステージした差分のみ使う
|
|
58
66
|
ai-git commit --no-add
|
|
59
67
|
```
|
|
60
68
|
|
|
61
|
-
|
|
69
|
+
確認プロンプトで操作を選択できます。
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
| 入力 | 動作 |
|
|
72
|
+
| ---- | ------------------------------ |
|
|
73
|
+
| `y` | そのままコミット |
|
|
74
|
+
| `n` | 中止 |
|
|
75
|
+
| `e` | エディタで編集してからコミット |
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
**生成されるコミットメッセージの形式(Conventional Commits):**
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
feat(auth): Google ログインを追加する
|
|
81
|
+
|
|
82
|
+
- GoogleAuthProvider の設定を auth.ts に追加する
|
|
83
|
+
- トークン期限切れ時の更新処理を追加する
|
|
84
|
+
- ネットワーク障害時のエラーハンドリングを追加する
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### コミット & プッシュ
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ai-git push
|
|
70
91
|
```
|
|
71
92
|
|
|
72
|
-
|
|
93
|
+
`git add .` → AI によるコミットメッセージ生成 → コミット → `git push` を一括で実行します。
|
|
73
94
|
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `e`: エディタで編集してからコミット
|
|
95
|
+
- upstream が未設定の場合は `git push -u origin <branch>` で自動設定
|
|
96
|
+
- PR は作成しません(PR を作りたい場合は `ai-git pr` を使用)
|
|
77
97
|
|
|
78
|
-
|
|
98
|
+
確認プロンプトで操作を選択できます。
|
|
79
99
|
|
|
80
|
-
|
|
100
|
+
| 入力 | 動作 |
|
|
101
|
+
| ---- | ----------------------------------------- |
|
|
102
|
+
| `y` | そのままコミット & プッシュ |
|
|
103
|
+
| `n` | 中止 |
|
|
104
|
+
| `e` | エディタで編集してからコミット & プッシュ |
|
|
81
105
|
|
|
82
106
|
```bash
|
|
83
|
-
|
|
84
|
-
git add
|
|
85
|
-
ai-git commit
|
|
107
|
+
# ステージ済みの差分のみ使う
|
|
108
|
+
ai-git push --no-add
|
|
86
109
|
```
|
|
87
110
|
|
|
88
|
-
|
|
111
|
+
### PR 作成
|
|
89
112
|
|
|
90
113
|
```bash
|
|
91
114
|
ai-git pr
|
|
92
|
-
|
|
93
|
-
# 言語指定も可能
|
|
94
|
-
ai-git pr --lang en
|
|
95
115
|
```
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
自動的に以下を実行します。
|
|
118
|
+
|
|
119
|
+
- ブランチがまだ push されていない場合: `git push -u origin <branch>`
|
|
120
|
+
- ローカルに新しいコミットがある場合: `git push`
|
|
121
|
+
- PR 説明文を生成して PR を作成
|
|
122
|
+
|
|
123
|
+
確認プロンプトで操作を選択できます。
|
|
124
|
+
|
|
125
|
+
| 入力 | 動作 |
|
|
126
|
+
| ---- | -------------------------- |
|
|
127
|
+
| `y` | PR を作成 |
|
|
128
|
+
| `n` | 中止 |
|
|
129
|
+
| `e` | エディタで編集してから作成 |
|
|
130
|
+
|
|
131
|
+
**生成される PR 説明文の形式:**
|
|
132
|
+
|
|
133
|
+
```markdown
|
|
134
|
+
## Summary
|
|
135
|
+
|
|
136
|
+
変更の全体像を 1〜2 文で説明
|
|
98
137
|
|
|
99
|
-
|
|
100
|
-
- ローカルに新しいコミットがある場合、`git push` を実行
|
|
101
|
-
- PR説明文を生成してPRを作成
|
|
138
|
+
## Changes
|
|
102
139
|
|
|
103
|
-
3
|
|
140
|
+
- 具体的な変更内容(3〜7 項目)
|
|
104
141
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
142
|
+
## Test plan
|
|
143
|
+
|
|
144
|
+
- テスト・確認方法(2〜4 項目)
|
|
145
|
+
```
|
|
108
146
|
|
|
109
147
|
**前提条件:**
|
|
110
148
|
|
|
111
149
|
- GitHub CLI (`gh`) がインストール済み ([インストール方法](https://cli.github.com/))
|
|
112
150
|
- `gh auth login` で認証済み
|
|
113
151
|
|
|
114
|
-
**生成されるPR説明文のフォーマット:**
|
|
115
|
-
|
|
116
|
-
- ## Summary: 変更の概要(2-3文)
|
|
117
|
-
- ## Changes: 具体的な変更内容(箇条書き)
|
|
118
|
-
- ## Test plan: テスト方法(箇条書き)
|
|
119
|
-
|
|
120
152
|
### ブランチ作成(自動命名)
|
|
121
153
|
|
|
122
154
|
変更差分(ステージ済み + 未ステージ)からブランチ名を推定して作成します。
|
|
@@ -127,21 +159,94 @@ ai-git checkout
|
|
|
127
159
|
|
|
128
160
|
命名例:
|
|
129
161
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
162
|
+
```
|
|
163
|
+
feat/google-login
|
|
164
|
+
fix/api-error-handling
|
|
165
|
+
docs/readme-update
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 言語設定
|
|
169
|
+
|
|
170
|
+
デフォルト言語は日本語です。
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# 今回だけ英語で生成
|
|
174
|
+
ai-git commit --lang en
|
|
175
|
+
ai-git pr --lang en
|
|
176
|
+
|
|
177
|
+
# デフォルト言語を永続化
|
|
178
|
+
ai-git --set-lang en
|
|
179
|
+
ai-git --set-lang ja
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### ヘルプ
|
|
133
183
|
|
|
134
|
-
|
|
184
|
+
```bash
|
|
185
|
+
ai-git --help
|
|
186
|
+
```
|
|
135
187
|
|
|
136
188
|
## 開発
|
|
137
189
|
|
|
138
190
|
```bash
|
|
139
|
-
npm
|
|
191
|
+
npm install
|
|
140
192
|
npm run build
|
|
193
|
+
npm link # どの Git リポジトリでも ai-git が使えるようになります
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npm run dev
|
|
141
198
|
```
|
|
142
199
|
|
|
143
200
|
## トラブルシューティング
|
|
144
201
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
-
|
|
202
|
+
### エラーメッセージについて
|
|
203
|
+
|
|
204
|
+
ai-git は Git 初心者にも優しいエラーメッセージを表示します。エラーが発生した場合、以下の情報が表示されます:
|
|
205
|
+
|
|
206
|
+
- **何が起こったか**(エラーの内容)
|
|
207
|
+
- **なぜ起こったか**(原因)
|
|
208
|
+
- **どうすればいいか**(解決方法)
|
|
209
|
+
- **ai-git のどのコマンドが使えるか**(次のステップ)
|
|
210
|
+
|
|
211
|
+
### よくあるエラーと対処法
|
|
212
|
+
|
|
213
|
+
| エラー | 原因 | 対処 |
|
|
214
|
+
| ---------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------- |
|
|
215
|
+
| `ステージされた変更が見つかりません` | コミットする変更がステージングエリアにない | `git add .` でステージ、または `ai-git push` を使用 |
|
|
216
|
+
| `GROQ_API_KEY が未設定です` | AI 機能に必要な API キーが設定されていない | [Groq Console](https://console.groq.com/keys) で API キーを取得して設定 |
|
|
217
|
+
| `これは Git リポジトリではありません` | Git が初期化されていないディレクトリで実行 | `git init` で初期化、または Git リポジトリに移動 |
|
|
218
|
+
| `GitHub CLI (gh) がインストールされていません` | PR 作成に必要な gh コマンドがない | [GitHub CLI](https://cli.github.com/) をインストール |
|
|
219
|
+
| `GitHub CLI の認証が必要です` | GitHub にログインしていない | `gh auth login` で認証 |
|
|
220
|
+
| `ベースブランチを検出できませんでした` | main/master/develop ブランチが存在しない | リモートから取得: `git fetch origin` |
|
|
221
|
+
| `413 Request too large` / TPM 超過 | 差分が大きすぎる、またはレート制限 | 自動で縮小して再試行されます。それでも失敗する場合は少し待つ |
|
|
222
|
+
|
|
223
|
+
### Git の基本操作
|
|
224
|
+
|
|
225
|
+
ai-git を使う前に、以下の Git コマンドを覚えておくと便利です:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# 現在の状態を確認
|
|
229
|
+
git status
|
|
230
|
+
|
|
231
|
+
# 変更をステージング
|
|
232
|
+
git add <ファイル名> # 特定のファイルだけ
|
|
233
|
+
git add . # すべての変更
|
|
234
|
+
|
|
235
|
+
# コミット履歴を確認
|
|
236
|
+
git log --oneline
|
|
237
|
+
|
|
238
|
+
# ブランチの確認
|
|
239
|
+
git branch -a
|
|
240
|
+
|
|
241
|
+
# リモートの確認
|
|
242
|
+
git remote -v
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 推奨ワークフロー
|
|
246
|
+
|
|
247
|
+
Git 初心者の方は、以下の流れで使うのがおすすめです:
|
|
248
|
+
|
|
249
|
+
1. **変更を加える** - ファイルを編集
|
|
250
|
+
2. **状態を確認** - `git status` で変更を確認
|
|
251
|
+
3. **コミット** - `ai-git commit` または `ai-git push`
|
|
252
|
+
4. **PR 作成** - `ai-git pr`(必要に応じて)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCheckoutCommand = runCheckoutCommand;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const errors_js_1 = require("../utils/errors.js");
|
|
6
|
+
const ai_js_1 = require("../services/ai.js");
|
|
7
|
+
const branch_js_1 = require("../services/branch.js");
|
|
8
|
+
/**
|
|
9
|
+
* checkout コマンドの実行
|
|
10
|
+
*/
|
|
11
|
+
async function runCheckoutCommand() {
|
|
12
|
+
const suggested = await (0, ai_js_1.suggestBranchName)();
|
|
13
|
+
const branchName = (0, branch_js_1.ensureAvailableBranchName)(suggested);
|
|
14
|
+
const result = (0, child_process_1.spawnSync)("git", ["checkout", "-b", branchName], {
|
|
15
|
+
stdio: "inherit",
|
|
16
|
+
});
|
|
17
|
+
if (result.status !== 0) {
|
|
18
|
+
(0, errors_js_1.showFriendlyError)("ブランチ作成に失敗しました", "git checkout -b コマンドが失敗しました(未コミットの変更がある可能性があります)", [
|
|
19
|
+
"現在の変更を確認: git status",
|
|
20
|
+
"変更をコミットしてから新しいブランチを作成する",
|
|
21
|
+
"変更を一時退避: git stash",
|
|
22
|
+
"または、変更を含めたままブランチを作成: git checkout -b <ブランチ名>",
|
|
23
|
+
], [
|
|
24
|
+
"ai-git commit でまず変更をコミット",
|
|
25
|
+
"ai-git push でコミット&プッシュしてから新しいブランチを作成",
|
|
26
|
+
]);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
console.log(`✅ ブランチを作成しました: ${branchName}`);
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCommitCommand = runCommitCommand;
|
|
4
|
+
const git_js_1 = require("../utils/git.js");
|
|
5
|
+
const ui_js_1 = require("../utils/ui.js");
|
|
6
|
+
const errors_js_1 = require("../utils/errors.js");
|
|
7
|
+
const ai_js_1 = require("../services/ai.js");
|
|
8
|
+
/**
|
|
9
|
+
* commit コマンドの実行
|
|
10
|
+
*/
|
|
11
|
+
async function runCommitCommand(language, noAdd) {
|
|
12
|
+
if (!noAdd) {
|
|
13
|
+
console.log("📦 変更をステージしています... (git add .)");
|
|
14
|
+
(0, git_js_1.stageAllChanges)();
|
|
15
|
+
}
|
|
16
|
+
const diff = (0, git_js_1.getStagedDiff)();
|
|
17
|
+
if (!diff.trim()) {
|
|
18
|
+
(0, errors_js_1.showFriendlyError)("ステージされた変更が見つかりません", "コミットする変更がステージングエリアにありません", [
|
|
19
|
+
"変更したファイルを確認: git status",
|
|
20
|
+
"すべての変更をステージ: git add .",
|
|
21
|
+
"特定のファイルだけステージ: git add <ファイル名>",
|
|
22
|
+
], [
|
|
23
|
+
"ai-git commit --no-add (手動で git add した後)",
|
|
24
|
+
"ai-git push (自動で git add してコミット&プッシュ)",
|
|
25
|
+
]);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
console.log("🤖 コミットメッセージを生成中... (compact summary input)");
|
|
29
|
+
const message = await (0, ai_js_1.generateCommitMessage)(diff, language);
|
|
30
|
+
console.log(`\n📝 Generated commit message:\n`);
|
|
31
|
+
message.split("\n").forEach((line) => {
|
|
32
|
+
console.log(` ${line}`);
|
|
33
|
+
});
|
|
34
|
+
console.log();
|
|
35
|
+
const answer = await (0, ui_js_1.askUser)("Use this message? [y/n/e(edit)]: ");
|
|
36
|
+
let finalMessage = message;
|
|
37
|
+
if (answer === "e" || answer === "edit") {
|
|
38
|
+
finalMessage = (0, ui_js_1.editInEditor)(message);
|
|
39
|
+
if (!finalMessage) {
|
|
40
|
+
console.log("Aborted: empty message.");
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
console.log(`\n✏️ Edited message:\n`);
|
|
44
|
+
finalMessage.split("\n").forEach((line) => {
|
|
45
|
+
console.log(` ${line}`);
|
|
46
|
+
});
|
|
47
|
+
console.log();
|
|
48
|
+
}
|
|
49
|
+
else if (answer !== "y" && answer !== "yes") {
|
|
50
|
+
console.log("Aborted.");
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
(0, git_js_1.doCommit)(finalMessage);
|
|
54
|
+
console.log(`\n✅ Committed successfully!`);
|
|
55
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPRCommand = runPRCommand;
|
|
4
|
+
const git_js_1 = require("../utils/git.js");
|
|
5
|
+
const ui_js_1 = require("../utils/ui.js");
|
|
6
|
+
const errors_js_1 = require("../utils/errors.js");
|
|
7
|
+
const github_js_1 = require("../services/github.js");
|
|
8
|
+
const ai_js_1 = require("../services/ai.js");
|
|
9
|
+
/**
|
|
10
|
+
* pr コマンドの実行
|
|
11
|
+
*/
|
|
12
|
+
async function runPRCommand(language) {
|
|
13
|
+
(0, github_js_1.checkGHCLI)(language);
|
|
14
|
+
(0, github_js_1.checkGHAuth)(language);
|
|
15
|
+
const baseBranch = (0, github_js_1.detectBaseBranch)(language);
|
|
16
|
+
const currentBranch = (0, git_js_1.getCurrentBranch)();
|
|
17
|
+
if (currentBranch === baseBranch) {
|
|
18
|
+
if (language === "ja") {
|
|
19
|
+
(0, errors_js_1.showFriendlyError)(`ベースブランチ (${baseBranch}) から PR を作成できません`, "PR は異なるブランチから作成する必要があります", [
|
|
20
|
+
"新しいブランチを作成してください",
|
|
21
|
+
"または、既存のブランチに切り替えてください: git checkout <ブランチ名>",
|
|
22
|
+
], [
|
|
23
|
+
"ai-git checkout で新しいブランチを作成",
|
|
24
|
+
"ブランチ作成後に変更をコミット: ai-git commit",
|
|
25
|
+
"その後 PR を作成: ai-git pr",
|
|
26
|
+
]);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
(0, errors_js_1.showFriendlyError)(`Cannot create PR from base branch (${baseBranch})`, "PRs must be created from a different branch", [
|
|
30
|
+
"Create a new branch",
|
|
31
|
+
"Or switch to an existing branch: git checkout <branch-name>",
|
|
32
|
+
], [
|
|
33
|
+
"Use ai-git checkout to create a new branch",
|
|
34
|
+
"Commit changes after creating branch: ai-git commit",
|
|
35
|
+
"Then create PR: ai-git pr",
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
// ブランチをプッシュ
|
|
41
|
+
(0, github_js_1.pushBranchForPR)(currentBranch, language);
|
|
42
|
+
console.log(`🤖 PR説明文を生成中... (${baseBranch}...${currentBranch}) [compact summary input]`);
|
|
43
|
+
const description = await (0, ai_js_1.generatePRDescription)(baseBranch, language, github_js_1.getBranchDiff);
|
|
44
|
+
console.log(`\n📝 Generated PR:\n`);
|
|
45
|
+
console.log(` Title: ${(0, ai_js_1.extractPRTitle)(description)}`);
|
|
46
|
+
console.log();
|
|
47
|
+
(0, ai_js_1.stripTitleLine)(description)
|
|
48
|
+
.split("\n")
|
|
49
|
+
.forEach((line) => {
|
|
50
|
+
console.log(` ${line}`);
|
|
51
|
+
});
|
|
52
|
+
console.log();
|
|
53
|
+
const answer = await (0, ui_js_1.askUser)("Create PR with this description? [y/n/e(edit)]: ");
|
|
54
|
+
let finalDescription = description;
|
|
55
|
+
if (answer === "e" || answer === "edit") {
|
|
56
|
+
finalDescription = (0, ui_js_1.editInEditor)(description);
|
|
57
|
+
if (!finalDescription) {
|
|
58
|
+
console.log("Aborted: empty description.");
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
console.log(`\n✏️ Edited description:\n`);
|
|
62
|
+
finalDescription.split("\n").forEach((line) => {
|
|
63
|
+
console.log(` ${line}`);
|
|
64
|
+
});
|
|
65
|
+
console.log();
|
|
66
|
+
}
|
|
67
|
+
else if (answer !== "y" && answer !== "yes") {
|
|
68
|
+
console.log("Aborted.");
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
const fallbackURL = (0, github_js_1.getPullRequestURL)(currentBranch);
|
|
72
|
+
(0, github_js_1.createPR)(finalDescription, baseBranch, fallbackURL, language, ai_js_1.extractPRTitle, ai_js_1.stripTitleLine);
|
|
73
|
+
console.log(`\n✅ PR created successfully!`);
|
|
74
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPushCommand = runPushCommand;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const commit_js_1 = require("./commit.js");
|
|
6
|
+
const git_js_1 = require("../utils/git.js");
|
|
7
|
+
/**
|
|
8
|
+
* 未プッシュのコミットがあるかチェック
|
|
9
|
+
*/
|
|
10
|
+
function hasUnpushedCommits(currentBranch) {
|
|
11
|
+
try {
|
|
12
|
+
// upstream が設定されているかチェック
|
|
13
|
+
(0, child_process_1.execSync)(`git rev-parse --abbrev-ref ${currentBranch}@{upstream}`, {
|
|
14
|
+
encoding: "utf-8",
|
|
15
|
+
stdio: "pipe",
|
|
16
|
+
});
|
|
17
|
+
// upstream と比較
|
|
18
|
+
const localCommit = (0, child_process_1.execSync)(`git rev-parse ${currentBranch}`, {
|
|
19
|
+
encoding: "utf-8",
|
|
20
|
+
stdio: "pipe",
|
|
21
|
+
}).trim();
|
|
22
|
+
const remoteCommit = (0, child_process_1.execSync)(`git rev-parse ${currentBranch}@{upstream}`, {
|
|
23
|
+
encoding: "utf-8",
|
|
24
|
+
stdio: "pipe",
|
|
25
|
+
}).trim();
|
|
26
|
+
return localCommit !== remoteCommit;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// upstream が設定されていない場合、コミットがあればプッシュすべき
|
|
30
|
+
try {
|
|
31
|
+
const commitCount = (0, child_process_1.execSync)("git rev-list --count HEAD", {
|
|
32
|
+
encoding: "utf-8",
|
|
33
|
+
stdio: "pipe",
|
|
34
|
+
}).trim();
|
|
35
|
+
return parseInt(commitCount, 10) > 0;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* push コマンドの実行
|
|
44
|
+
*/
|
|
45
|
+
async function runPushCommand(language, noAdd) {
|
|
46
|
+
const currentBranch = (0, git_js_1.getCurrentBranch)();
|
|
47
|
+
// ステージされた変更をチェック(--no-add の場合は git add をスキップ)
|
|
48
|
+
if (!noAdd) {
|
|
49
|
+
console.log("📦 変更をステージしています... (git add .)");
|
|
50
|
+
(0, git_js_1.stageAllChanges)();
|
|
51
|
+
}
|
|
52
|
+
const diff = (0, git_js_1.getStagedDiff)();
|
|
53
|
+
const hasStagedChanges = diff.trim().length > 0;
|
|
54
|
+
if (hasStagedChanges) {
|
|
55
|
+
// ステージされた変更がある場合は、通常のコミットフローを実行
|
|
56
|
+
await (0, commit_js_1.runCommitCommand)(language, true); // noAdd=true(すでにステージ済み)
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// ステージされた変更がない場合、未プッシュのコミットがあるかチェック
|
|
60
|
+
if (hasUnpushedCommits(currentBranch)) {
|
|
61
|
+
console.log("💡 ステージされた変更はありませんが、未プッシュのコミットがあります");
|
|
62
|
+
console.log("📤 コミットをプッシュします...");
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.error("❌ プッシュするものがありません");
|
|
66
|
+
console.error("");
|
|
67
|
+
console.error("📋 原因: ステージされた変更も未プッシュのコミットもありません");
|
|
68
|
+
console.error("");
|
|
69
|
+
console.error("💡 解決方法:");
|
|
70
|
+
console.error(" 1. 変更を確認: git status");
|
|
71
|
+
console.error(" 2. 変更をステージ: git add .");
|
|
72
|
+
console.error(" 3. または、まずコミット: ai-git commit");
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
(0, git_js_1.pushCurrentBranch)(currentBranch);
|
|
77
|
+
console.log(`\n✅ Push 完了!`);
|
|
78
|
+
}
|