geeto 0.4.3 → 0.6.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 +1 -1
- package/lib/api/copilot.d.ts +3 -3
- package/lib/api/copilot.js +3 -3
- package/lib/cli/input.d.ts +21 -18
- package/lib/cli/input.d.ts.map +1 -1
- package/lib/cli/input.js +174 -372
- package/lib/cli/input.js.map +1 -1
- package/lib/cli/menu.d.ts.map +1 -1
- package/lib/cli/menu.js +83 -4
- package/lib/cli/menu.js.map +1 -1
- package/lib/core/copilot-setup.d.ts +2 -2
- package/lib/core/copilot-setup.d.ts.map +1 -1
- package/lib/core/copilot-setup.js +16 -19
- package/lib/core/copilot-setup.js.map +1 -1
- package/lib/core/setup.d.ts +1 -1
- package/lib/core/setup.js +1 -1
- package/lib/index.js +203 -3
- package/lib/index.js.map +1 -1
- package/lib/utils/branch-naming.d.ts.map +1 -1
- package/lib/utils/branch-naming.js +17 -7
- package/lib/utils/branch-naming.js.map +1 -1
- package/lib/utils/dry-run.d.ts +21 -0
- package/lib/utils/dry-run.d.ts.map +1 -0
- package/lib/utils/dry-run.js +102 -0
- package/lib/utils/dry-run.js.map +1 -0
- package/lib/utils/exec.d.ts.map +1 -1
- package/lib/utils/exec.js +13 -0
- package/lib/utils/exec.js.map +1 -1
- package/lib/utils/git-ai.d.ts.map +1 -1
- package/lib/utils/git-ai.js +40 -21
- package/lib/utils/git-ai.js.map +1 -1
- package/lib/utils/git-errors.d.ts.map +1 -1
- package/lib/utils/git-errors.js +15 -2
- package/lib/utils/git-errors.js.map +1 -1
- package/lib/utils/menu-builders.js +1 -1
- package/lib/utils/menu-builders.js.map +1 -1
- package/lib/utils/scramble.d.ts +117 -0
- package/lib/utils/scramble.d.ts.map +1 -0
- package/lib/utils/scramble.js +317 -0
- package/lib/utils/scramble.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/workflows/abort.d.ts +9 -0
- package/lib/workflows/abort.d.ts.map +1 -0
- package/lib/workflows/abort.js +158 -0
- package/lib/workflows/abort.js.map +1 -0
- package/lib/workflows/ai-provider.js +1 -1
- package/lib/workflows/ai-provider.js.map +1 -1
- package/lib/workflows/alias.d.ts +6 -0
- package/lib/workflows/alias.d.ts.map +1 -0
- package/lib/workflows/alias.js +420 -0
- package/lib/workflows/alias.js.map +1 -0
- package/lib/workflows/amend.d.ts.map +1 -1
- package/lib/workflows/amend.js +9 -4
- package/lib/workflows/amend.js.map +1 -1
- package/lib/workflows/branch-helpers.js +2 -2
- package/lib/workflows/branch-helpers.js.map +1 -1
- package/lib/workflows/branch-utils.d.ts.map +1 -1
- package/lib/workflows/branch-utils.js +4 -3
- package/lib/workflows/branch-utils.js.map +1 -1
- package/lib/workflows/branch.d.ts.map +1 -1
- package/lib/workflows/branch.js +7 -4
- package/lib/workflows/branch.js.map +1 -1
- package/lib/workflows/cleanup.js +3 -3
- package/lib/workflows/cleanup.js.map +1 -1
- package/lib/workflows/commit.d.ts.map +1 -1
- package/lib/workflows/commit.js +58 -6
- package/lib/workflows/commit.js.map +1 -1
- package/lib/workflows/dry-run.d.ts +5 -0
- package/lib/workflows/dry-run.d.ts.map +1 -0
- package/lib/workflows/dry-run.js +127 -0
- package/lib/workflows/dry-run.js.map +1 -0
- package/lib/workflows/fetch.d.ts +9 -0
- package/lib/workflows/fetch.d.ts.map +1 -0
- package/lib/workflows/fetch.js +118 -0
- package/lib/workflows/fetch.js.map +1 -0
- package/lib/workflows/issue.d.ts.map +1 -1
- package/lib/workflows/issue.js +317 -72
- package/lib/workflows/issue.js.map +1 -1
- package/lib/workflows/main-steps.d.ts.map +1 -1
- package/lib/workflows/main-steps.js +144 -99
- package/lib/workflows/main-steps.js.map +1 -1
- package/lib/workflows/main.d.ts.map +1 -1
- package/lib/workflows/main.js +14 -6
- package/lib/workflows/main.js.map +1 -1
- package/lib/workflows/pr.d.ts.map +1 -1
- package/lib/workflows/pr.js +307 -39
- package/lib/workflows/pr.js.map +1 -1
- package/lib/workflows/prune.d.ts +9 -0
- package/lib/workflows/prune.d.ts.map +1 -0
- package/lib/workflows/prune.js +116 -0
- package/lib/workflows/prune.js.map +1 -0
- package/lib/workflows/pull.d.ts +9 -0
- package/lib/workflows/pull.d.ts.map +1 -0
- package/lib/workflows/pull.js +281 -0
- package/lib/workflows/pull.js.map +1 -0
- package/lib/workflows/release.d.ts.map +1 -1
- package/lib/workflows/release.js +50 -38
- package/lib/workflows/release.js.map +1 -1
- package/lib/workflows/repo-settings.js +2 -2
- package/lib/workflows/repo-settings.js.map +1 -1
- package/lib/workflows/revert.d.ts +9 -0
- package/lib/workflows/revert.d.ts.map +1 -0
- package/lib/workflows/revert.js +77 -0
- package/lib/workflows/revert.js.map +1 -0
- package/lib/workflows/reword.d.ts +9 -0
- package/lib/workflows/reword.d.ts.map +1 -0
- package/lib/workflows/reword.js +722 -0
- package/lib/workflows/reword.js.map +1 -0
- package/lib/workflows/settings.js +1 -1
- package/lib/workflows/settings.js.map +1 -1
- package/lib/workflows/status.d.ts +9 -0
- package/lib/workflows/status.d.ts.map +1 -0
- package/lib/workflows/status.js +164 -0
- package/lib/workflows/status.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull workflow
|
|
3
|
+
* Interactive git pull with strategy selection and remote awareness
|
|
4
|
+
*/
|
|
5
|
+
import { confirm } from '../cli/input.js';
|
|
6
|
+
import { select } from '../cli/menu.js';
|
|
7
|
+
import { colors } from '../utils/colors.js';
|
|
8
|
+
import { exec, execAsync, execSilent } from '../utils/exec.js';
|
|
9
|
+
import { getCurrentBranch } from '../utils/git.js';
|
|
10
|
+
import { log } from '../utils/logging.js';
|
|
11
|
+
import { ScrambleProgress } from '../utils/scramble.js';
|
|
12
|
+
/**
|
|
13
|
+
* Get list of configured remotes
|
|
14
|
+
*/
|
|
15
|
+
const getRemotes = () => {
|
|
16
|
+
try {
|
|
17
|
+
return execSilent('git remote').trim().split('\n').filter(Boolean);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Get tracking info for current branch
|
|
25
|
+
*/
|
|
26
|
+
const getTrackingInfo = () => {
|
|
27
|
+
try {
|
|
28
|
+
const upstream = execSilent('git rev-parse --abbrev-ref @{upstream}').trim();
|
|
29
|
+
if (!upstream)
|
|
30
|
+
return null;
|
|
31
|
+
const [remote, ...branchParts] = upstream.split('/');
|
|
32
|
+
return { remote: remote ?? 'origin', branch: branchParts.join('/') };
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Get ahead/behind count relative to upstream
|
|
40
|
+
*/
|
|
41
|
+
const getAheadBehind = () => {
|
|
42
|
+
try {
|
|
43
|
+
const output = execSilent('git rev-list --left-right --count HEAD...@{upstream}').trim();
|
|
44
|
+
const [ahead, behind] = output.split('\t').map(Number);
|
|
45
|
+
return { ahead: ahead ?? 0, behind: behind ?? 0 };
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Check if working tree is dirty
|
|
53
|
+
*/
|
|
54
|
+
const hasUncommittedChanges = () => {
|
|
55
|
+
try {
|
|
56
|
+
const status = execSilent('git status --porcelain').trim();
|
|
57
|
+
return status.length > 0;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Handle the pull workflow
|
|
65
|
+
*/
|
|
66
|
+
export const handlePull = async () => {
|
|
67
|
+
const C = colors.cyan;
|
|
68
|
+
const R = colors.reset;
|
|
69
|
+
const G = colors.green;
|
|
70
|
+
const Y = colors.yellow;
|
|
71
|
+
const GR = colors.gray;
|
|
72
|
+
const RED = colors.red;
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(` ${C}⬇ Git Pull${R}`);
|
|
75
|
+
console.log(` ${GR}${'─'.repeat(35)}${R}`);
|
|
76
|
+
console.log('');
|
|
77
|
+
const currentBranch = getCurrentBranch();
|
|
78
|
+
const remotes = getRemotes();
|
|
79
|
+
if (remotes.length === 0) {
|
|
80
|
+
log.error('No remotes configured.');
|
|
81
|
+
console.log(` ${GR}Add a remote: git remote add origin <url>${R}`);
|
|
82
|
+
console.log('');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Show current state
|
|
86
|
+
console.log(` ${GR}Branch:${R} ${G}${currentBranch}${R}`);
|
|
87
|
+
const tracking = getTrackingInfo();
|
|
88
|
+
if (tracking) {
|
|
89
|
+
console.log(` ${GR}Tracks:${R} ${C}${tracking.remote}/${tracking.branch}${R}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.log(` ${GR}Tracks:${R} ${Y}(no upstream)${R}`);
|
|
93
|
+
}
|
|
94
|
+
// Fetch to get latest state
|
|
95
|
+
console.log('');
|
|
96
|
+
const fetchProgress = new ScrambleProgress();
|
|
97
|
+
fetchProgress.start(['fetching latest from remote...']);
|
|
98
|
+
try {
|
|
99
|
+
const fetchRemote = tracking?.remote ?? 'origin';
|
|
100
|
+
await execAsync(`git fetch ${fetchRemote} --quiet`, true);
|
|
101
|
+
fetchProgress.succeed('Fetched latest from remote');
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
fetchProgress.fail('Could not fetch from remote');
|
|
105
|
+
log.warn('Continuing with local info...');
|
|
106
|
+
}
|
|
107
|
+
const counts = getAheadBehind();
|
|
108
|
+
if (counts) {
|
|
109
|
+
const { ahead, behind } = counts;
|
|
110
|
+
if (behind === 0 && ahead === 0) {
|
|
111
|
+
console.log('');
|
|
112
|
+
log.success('Already up to date.');
|
|
113
|
+
console.log('');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (behind === 0) {
|
|
117
|
+
console.log('');
|
|
118
|
+
log.info(`Already up to date (${ahead} commit${ahead === 1 ? '' : 's'} ahead).`);
|
|
119
|
+
console.log('');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.log(` ${GR}Status:${R} ${behind > 0 ? `${RED}${behind} behind${R}` : ''}` +
|
|
123
|
+
`${ahead > 0 && behind > 0 ? ' ' : ''}` +
|
|
124
|
+
`${ahead > 0 ? `${G}${ahead} ahead${R}` : ''}`);
|
|
125
|
+
}
|
|
126
|
+
// Warn about uncommitted changes
|
|
127
|
+
const dirty = hasUncommittedChanges();
|
|
128
|
+
if (dirty) {
|
|
129
|
+
console.log('');
|
|
130
|
+
console.log(` ${Y}⚠ You have uncommitted changes.${R}`);
|
|
131
|
+
console.log(` ${GR}Pull may fail if there are conflicts with local changes.${R}`);
|
|
132
|
+
}
|
|
133
|
+
console.log('');
|
|
134
|
+
// Choose remote (if multiple)
|
|
135
|
+
let remote = tracking?.remote ?? 'origin';
|
|
136
|
+
if (remotes.length > 1) {
|
|
137
|
+
remote = await select('Pull from which remote?', remotes.map((r) => ({
|
|
138
|
+
label: `${r}${r === tracking?.remote ? ` ${GR}(tracking)${R}` : ''}`,
|
|
139
|
+
value: r,
|
|
140
|
+
})));
|
|
141
|
+
}
|
|
142
|
+
// Choose strategy
|
|
143
|
+
const strategy = await select('Pull strategy:', [
|
|
144
|
+
{
|
|
145
|
+
label: `Merge ${GR}(default — preserves history)${R}`,
|
|
146
|
+
value: 'merge',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: `Rebase ${GR}(linear history — replays commits on top)${R}`,
|
|
150
|
+
value: 'rebase',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
label: `Fast-forward only ${GR}(fails if diverged)${R}`,
|
|
154
|
+
value: 'ff-only',
|
|
155
|
+
},
|
|
156
|
+
]);
|
|
157
|
+
// Build the pull command
|
|
158
|
+
let pullCmd = `git pull ${remote} ${currentBranch}`;
|
|
159
|
+
switch (strategy) {
|
|
160
|
+
case 'rebase': {
|
|
161
|
+
pullCmd = `git pull --rebase ${remote} ${currentBranch}`;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case 'ff-only': {
|
|
165
|
+
pullCmd = `git pull --ff-only ${remote} ${currentBranch}`;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Stash if dirty and user wants
|
|
170
|
+
let stashed = false;
|
|
171
|
+
if (dirty) {
|
|
172
|
+
const useStash = confirm('Stash uncommitted changes before pull?', true);
|
|
173
|
+
if (useStash) {
|
|
174
|
+
try {
|
|
175
|
+
exec('git stash push -m "geeto: auto-stash before pull"', true);
|
|
176
|
+
stashed = true;
|
|
177
|
+
log.info('Changes stashed.');
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
log.warn('Failed to stash changes. Proceeding anyway...');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Execute pull — count objects before animation (sync, but local = fast)
|
|
185
|
+
let pullObjectCount = 0;
|
|
186
|
+
let pullDeltaCount = 0;
|
|
187
|
+
try {
|
|
188
|
+
const objCount = Number(exec(`git rev-list --objects ${remote}/${currentBranch} ^HEAD 2>/dev/null | wc -l`, true).trim()) || 0;
|
|
189
|
+
if (objCount > 0)
|
|
190
|
+
pullObjectCount = objCount;
|
|
191
|
+
if (counts?.behind)
|
|
192
|
+
pullDeltaCount = counts.behind;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
/* ignore */
|
|
196
|
+
}
|
|
197
|
+
console.log('');
|
|
198
|
+
const pullProgress = new ScrambleProgress();
|
|
199
|
+
pullProgress.start([
|
|
200
|
+
'fetching remote refs...',
|
|
201
|
+
pullObjectCount > 0
|
|
202
|
+
? { text: 'downloading objects', countTo: pullObjectCount }
|
|
203
|
+
: 'downloading objects...',
|
|
204
|
+
pullDeltaCount > 0
|
|
205
|
+
? { text: 'resolving deltas', countTo: pullDeltaCount }
|
|
206
|
+
: 'resolving deltas...',
|
|
207
|
+
`merging ${remote}/${currentBranch} → ${currentBranch}...`,
|
|
208
|
+
]);
|
|
209
|
+
try {
|
|
210
|
+
const result = await execAsync(pullCmd, true);
|
|
211
|
+
pullProgress.succeed('Pull completed successfully');
|
|
212
|
+
if (result.stdout.trim()) {
|
|
213
|
+
console.log(result.stdout);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
pullProgress.fail('Pull failed');
|
|
218
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
219
|
+
if (msg.includes('CONFLICT') || msg.includes('conflict')) {
|
|
220
|
+
console.log('');
|
|
221
|
+
log.error('Merge conflicts detected!');
|
|
222
|
+
console.log(` ${GR}Resolve conflicts, then:${R}`);
|
|
223
|
+
if (strategy === 'rebase') {
|
|
224
|
+
console.log(` ${C}git rebase --continue${R} ${GR}(after resolving)${R}`);
|
|
225
|
+
console.log(` ${C}git rebase --abort${R} ${GR}(to cancel)${R}`);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.log(` ${C}git add <files>${R} ${GR}(mark resolved)${R}`);
|
|
229
|
+
console.log(` ${C}git commit${R} ${GR}(complete merge)${R}`);
|
|
230
|
+
console.log(` ${C}git merge --abort${R} ${GR}(to cancel)${R}`);
|
|
231
|
+
}
|
|
232
|
+
console.log('');
|
|
233
|
+
console.log(` ${GR}Or use: ${C}geeto --abort${R}`);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
log.error(`Pull failed: ${msg}`);
|
|
237
|
+
}
|
|
238
|
+
// Restore stash if we stashed
|
|
239
|
+
if (stashed) {
|
|
240
|
+
console.log('');
|
|
241
|
+
const restore = confirm('Restore stashed changes?', true);
|
|
242
|
+
if (restore) {
|
|
243
|
+
try {
|
|
244
|
+
exec('git stash pop', true);
|
|
245
|
+
log.info('Stashed changes restored.');
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
log.warn('Could not auto-restore stash. Run: git stash pop');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
console.log('');
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Restore stash after successful pull
|
|
256
|
+
if (stashed) {
|
|
257
|
+
try {
|
|
258
|
+
exec('git stash pop', true);
|
|
259
|
+
log.info('Stashed changes restored.');
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
log.warn('Could not auto-restore stash (may have conflicts). Run: git stash pop');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Show summary
|
|
266
|
+
console.log('');
|
|
267
|
+
try {
|
|
268
|
+
const logOutput = execSilent('git log --oneline -3').trim();
|
|
269
|
+
if (logOutput) {
|
|
270
|
+
console.log(` ${GR}Latest commits:${R}`);
|
|
271
|
+
for (const line of logOutput.split('\n')) {
|
|
272
|
+
console.log(` ${GR}${line}${R}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Non-critical
|
|
278
|
+
}
|
|
279
|
+
console.log('');
|
|
280
|
+
};
|
|
281
|
+
//# sourceMappingURL=pull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/workflows/pull.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../src/workflows/release.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../src/workflows/release.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAw0BH,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAglBlD,CAAA"}
|
package/lib/workflows/release.js
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* RELEASE.MD (user-friendly) and CHANGELOG.md (developer-facing)
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
-
import { askQuestion, confirm, editInline
|
|
7
|
+
import { askQuestion, confirm, editInline } from '../cli/input.js';
|
|
8
8
|
import { select } from '../cli/menu.js';
|
|
9
9
|
import { colors } from '../utils/colors.js';
|
|
10
10
|
import { exec, execAsync, execSilent } from '../utils/exec.js';
|
|
11
11
|
import { chooseModelForProvider, generateReleaseNotesWithProvider, getAIProviderShortName, getModelValue, } from '../utils/git-ai.js';
|
|
12
12
|
import { log } from '../utils/logging.js';
|
|
13
|
+
import { ScrambleProgress } from '../utils/scramble.js';
|
|
13
14
|
import { loadState } from '../utils/state.js';
|
|
14
15
|
// ─── Helpers ───
|
|
15
16
|
/**
|
|
@@ -271,8 +272,8 @@ const handleSyncReleases = async () => {
|
|
|
271
272
|
return;
|
|
272
273
|
}
|
|
273
274
|
console.log('');
|
|
274
|
-
const spinner =
|
|
275
|
-
spinner.start('
|
|
275
|
+
const spinner = new ScrambleProgress();
|
|
276
|
+
spinner.start(['connecting to github...', 'fetching releases...', 'comparing tags...']);
|
|
276
277
|
const localTags = getExistingTags();
|
|
277
278
|
const ghReleases = getExistingGithubReleases();
|
|
278
279
|
const missingTags = localTags.filter((t) => !ghReleases.includes(t));
|
|
@@ -338,7 +339,7 @@ const handleSyncReleases = async () => {
|
|
|
338
339
|
let providerChosen = false;
|
|
339
340
|
while (!providerChosen) {
|
|
340
341
|
aiProvider = (await select('Choose AI Provider:', [
|
|
341
|
-
{ label: 'GitHub
|
|
342
|
+
{ label: 'GitHub (Recommended)', value: 'copilot' },
|
|
342
343
|
{ label: 'Gemini', value: 'gemini' },
|
|
343
344
|
{ label: 'OpenRouter', value: 'openrouter' },
|
|
344
345
|
]));
|
|
@@ -390,11 +391,13 @@ const handleSyncReleases = async () => {
|
|
|
390
391
|
let releaseBody;
|
|
391
392
|
if (useAI && commits.length > 0) {
|
|
392
393
|
console.log('');
|
|
393
|
-
const aiSpinner =
|
|
394
|
+
const aiSpinner = new ScrambleProgress();
|
|
394
395
|
const modelDisplay = getModelValue(copilotModel ?? openrouterModel ?? geminiModel ?? '');
|
|
395
|
-
aiSpinner.start(
|
|
396
|
-
|
|
397
|
-
'
|
|
396
|
+
aiSpinner.start([
|
|
397
|
+
'preparing release context...',
|
|
398
|
+
`generating notes with ${getAIProviderShortName(aiProvider)}${modelDisplay ? ` (${modelDisplay})` : ''}...`,
|
|
399
|
+
'processing results...',
|
|
400
|
+
]);
|
|
398
401
|
const aiResult = await generateReleaseNotesWithProvider(aiProvider, commitList, language, undefined, copilotModel, openrouterModel, geminiModel);
|
|
399
402
|
if (aiResult) {
|
|
400
403
|
aiSpinner.succeed(`Notes generated for ${tag}`);
|
|
@@ -432,9 +435,9 @@ const handleSyncReleases = async () => {
|
|
|
432
435
|
.trim();
|
|
433
436
|
}
|
|
434
437
|
console.log('');
|
|
435
|
-
const releaseSpinner =
|
|
438
|
+
const releaseSpinner = new ScrambleProgress();
|
|
436
439
|
// Ensure tag exists on remote before creating GitHub Release
|
|
437
|
-
releaseSpinner.start(
|
|
440
|
+
releaseSpinner.start(['connecting to remote...', 'pushing tag...', 'verifying remote refs...']);
|
|
438
441
|
try {
|
|
439
442
|
await execAsync(`git push origin ${tag} --no-verify`, true);
|
|
440
443
|
releaseSpinner.succeed(`Tag ${tag} pushed to remote`);
|
|
@@ -443,8 +446,12 @@ const handleSyncReleases = async () => {
|
|
|
443
446
|
// Tag might already exist on remote — that's fine, continue
|
|
444
447
|
}
|
|
445
448
|
console.log('');
|
|
446
|
-
const createSpinner =
|
|
447
|
-
createSpinner.start(
|
|
449
|
+
const createSpinner = new ScrambleProgress();
|
|
450
|
+
createSpinner.start([
|
|
451
|
+
'preparing release data...',
|
|
452
|
+
'creating github release...',
|
|
453
|
+
'confirming creation...',
|
|
454
|
+
]);
|
|
448
455
|
const os = await import('node:os');
|
|
449
456
|
const tempFile = `${os.tmpdir()}/geeto-sync-${Date.now()}.md`;
|
|
450
457
|
writeFileSync(tempFile, releaseBody, 'utf8');
|
|
@@ -487,8 +494,8 @@ const handleDeleteReleases = async () => {
|
|
|
487
494
|
return;
|
|
488
495
|
}
|
|
489
496
|
console.log('');
|
|
490
|
-
const spinner =
|
|
491
|
-
spinner.start('
|
|
497
|
+
const spinner = new ScrambleProgress();
|
|
498
|
+
spinner.start(['connecting to github...', 'fetching releases...', 'processing results...']);
|
|
492
499
|
const ghReleases = getExistingGithubReleases();
|
|
493
500
|
spinner.succeed(`Found ${ghReleases.length} GitHub releases`);
|
|
494
501
|
if (ghReleases.length === 0) {
|
|
@@ -513,8 +520,8 @@ const handleDeleteReleases = async () => {
|
|
|
513
520
|
let successCount = 0;
|
|
514
521
|
for (const release of selected) {
|
|
515
522
|
console.log('');
|
|
516
|
-
const releaseSpinner =
|
|
517
|
-
releaseSpinner.start(
|
|
523
|
+
const releaseSpinner = new ScrambleProgress();
|
|
524
|
+
releaseSpinner.start(['connecting to github...', 'deleting release...', 'cleaning up...']);
|
|
518
525
|
try {
|
|
519
526
|
await execAsync(`gh release delete ${release} --yes`, true);
|
|
520
527
|
if (alsoDeleteTag) {
|
|
@@ -654,8 +661,8 @@ const handleRecoverTags = async () => {
|
|
|
654
661
|
const pushTags = confirm('Push recovered tags to remote?');
|
|
655
662
|
if (pushTags) {
|
|
656
663
|
console.log('');
|
|
657
|
-
const pushSpinner =
|
|
658
|
-
pushSpinner.start('
|
|
664
|
+
const pushSpinner = new ScrambleProgress();
|
|
665
|
+
pushSpinner.start(['connecting to remote...', 'pushing tags...', 'verifying remote refs...']);
|
|
659
666
|
try {
|
|
660
667
|
await execAsync('git push --tags --no-verify', true);
|
|
661
668
|
pushSpinner.succeed('Tags pushed to remote');
|
|
@@ -837,7 +844,7 @@ export const handleRelease = async () => {
|
|
|
837
844
|
let providerChosen = false;
|
|
838
845
|
while (!providerChosen) {
|
|
839
846
|
aiProvider = (await select('Choose AI Provider:', [
|
|
840
|
-
{ label: 'GitHub
|
|
847
|
+
{ label: 'GitHub (Recommended)', value: 'copilot' },
|
|
841
848
|
{ label: 'Gemini', value: 'gemini' },
|
|
842
849
|
{ label: 'OpenRouter', value: 'openrouter' },
|
|
843
850
|
]));
|
|
@@ -865,11 +872,13 @@ export const handleRelease = async () => {
|
|
|
865
872
|
let correction;
|
|
866
873
|
let accepted = false;
|
|
867
874
|
while (!accepted) {
|
|
868
|
-
const spinner =
|
|
875
|
+
const spinner = new ScrambleProgress();
|
|
869
876
|
const modelDisplay = getModelValue(copilotModel ?? openrouterModel ?? geminiModel ?? '');
|
|
870
|
-
spinner.start(
|
|
871
|
-
|
|
872
|
-
'
|
|
877
|
+
spinner.start([
|
|
878
|
+
'preparing release context...',
|
|
879
|
+
`generating notes with ${getAIProviderShortName(aiProvider)}${modelDisplay ? ` (${modelDisplay})` : ''}...`,
|
|
880
|
+
'processing results...',
|
|
881
|
+
]);
|
|
873
882
|
const result = await generateReleaseNotesWithProvider(aiProvider, commitList, language, correction, copilotModel, openrouterModel, geminiModel);
|
|
874
883
|
spinner.succeed('Release notes generated');
|
|
875
884
|
console.log('');
|
|
@@ -942,7 +951,7 @@ export const handleRelease = async () => {
|
|
|
942
951
|
}
|
|
943
952
|
case 'change-provider': {
|
|
944
953
|
const prov = (await select('Choose AI provider:', [
|
|
945
|
-
{ label: '
|
|
954
|
+
{ label: 'Copilot', value: 'copilot' },
|
|
946
955
|
{ label: 'Gemini', value: 'gemini' },
|
|
947
956
|
{ label: 'OpenRouter', value: 'openrouter' },
|
|
948
957
|
]));
|
|
@@ -1099,27 +1108,26 @@ export const handleRelease = async () => {
|
|
|
1099
1108
|
{ label: 'Skip pushing', value: 'skip' },
|
|
1100
1109
|
]);
|
|
1101
1110
|
if (pushChoice === 'both' || pushChoice === 'commit') {
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1111
|
+
console.log('');
|
|
1112
|
+
const pushProgress = new ScrambleProgress();
|
|
1113
|
+
pushProgress.start([
|
|
1114
|
+
'initializing push...',
|
|
1115
|
+
'collecting objects...',
|
|
1116
|
+
{ text: 'compressing deltas', countTo: 100, suffix: '%' },
|
|
1117
|
+
'uploading to remote...',
|
|
1118
|
+
'verifying remote refs...',
|
|
1119
|
+
]);
|
|
1108
1120
|
try {
|
|
1109
1121
|
await execAsync(`git push`, true);
|
|
1110
1122
|
if (pushChoice === 'both') {
|
|
1111
1123
|
await execAsync(`git push origin v${newVersion} --no-verify`, true);
|
|
1112
1124
|
}
|
|
1113
|
-
|
|
1114
|
-
progressBar.update(100);
|
|
1115
|
-
progressBar.complete();
|
|
1125
|
+
pushProgress.stop();
|
|
1116
1126
|
console.log('');
|
|
1117
1127
|
log.success(pushChoice === 'both' ? 'Pushed release + tag' : 'Pushed release');
|
|
1118
1128
|
}
|
|
1119
1129
|
catch {
|
|
1120
|
-
|
|
1121
|
-
progressBar.complete();
|
|
1122
|
-
console.log('');
|
|
1130
|
+
pushProgress.fail('Push failed');
|
|
1123
1131
|
log.error('Failed to push');
|
|
1124
1132
|
}
|
|
1125
1133
|
}
|
|
@@ -1140,8 +1148,12 @@ export const handleRelease = async () => {
|
|
|
1140
1148
|
const os = await import('node:os');
|
|
1141
1149
|
const tempFile = `${os.tmpdir()}/geeto-release-${Date.now()}.md`;
|
|
1142
1150
|
writeFileSync(tempFile, releaseBody, 'utf8');
|
|
1143
|
-
const releaseSpinner =
|
|
1144
|
-
releaseSpinner.start(
|
|
1151
|
+
const releaseSpinner = new ScrambleProgress();
|
|
1152
|
+
releaseSpinner.start([
|
|
1153
|
+
'preparing release data...',
|
|
1154
|
+
'creating github release...',
|
|
1155
|
+
'confirming creation...',
|
|
1156
|
+
]);
|
|
1145
1157
|
try {
|
|
1146
1158
|
await execAsync(`gh release create v${newVersion} --title "v${newVersion}" --notes-file "${tempFile}"`, true);
|
|
1147
1159
|
releaseSpinner.succeed('GitHub Release created');
|