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.
Files changed (116) hide show
  1. package/README.md +1 -1
  2. package/lib/api/copilot.d.ts +3 -3
  3. package/lib/api/copilot.js +3 -3
  4. package/lib/cli/input.d.ts +21 -18
  5. package/lib/cli/input.d.ts.map +1 -1
  6. package/lib/cli/input.js +174 -372
  7. package/lib/cli/input.js.map +1 -1
  8. package/lib/cli/menu.d.ts.map +1 -1
  9. package/lib/cli/menu.js +83 -4
  10. package/lib/cli/menu.js.map +1 -1
  11. package/lib/core/copilot-setup.d.ts +2 -2
  12. package/lib/core/copilot-setup.d.ts.map +1 -1
  13. package/lib/core/copilot-setup.js +16 -19
  14. package/lib/core/copilot-setup.js.map +1 -1
  15. package/lib/core/setup.d.ts +1 -1
  16. package/lib/core/setup.js +1 -1
  17. package/lib/index.js +203 -3
  18. package/lib/index.js.map +1 -1
  19. package/lib/utils/branch-naming.d.ts.map +1 -1
  20. package/lib/utils/branch-naming.js +17 -7
  21. package/lib/utils/branch-naming.js.map +1 -1
  22. package/lib/utils/dry-run.d.ts +21 -0
  23. package/lib/utils/dry-run.d.ts.map +1 -0
  24. package/lib/utils/dry-run.js +102 -0
  25. package/lib/utils/dry-run.js.map +1 -0
  26. package/lib/utils/exec.d.ts.map +1 -1
  27. package/lib/utils/exec.js +13 -0
  28. package/lib/utils/exec.js.map +1 -1
  29. package/lib/utils/git-ai.d.ts.map +1 -1
  30. package/lib/utils/git-ai.js +40 -21
  31. package/lib/utils/git-ai.js.map +1 -1
  32. package/lib/utils/git-errors.d.ts.map +1 -1
  33. package/lib/utils/git-errors.js +15 -2
  34. package/lib/utils/git-errors.js.map +1 -1
  35. package/lib/utils/menu-builders.js +1 -1
  36. package/lib/utils/menu-builders.js.map +1 -1
  37. package/lib/utils/scramble.d.ts +117 -0
  38. package/lib/utils/scramble.d.ts.map +1 -0
  39. package/lib/utils/scramble.js +317 -0
  40. package/lib/utils/scramble.js.map +1 -0
  41. package/lib/version.d.ts +1 -1
  42. package/lib/version.js +1 -1
  43. package/lib/workflows/abort.d.ts +9 -0
  44. package/lib/workflows/abort.d.ts.map +1 -0
  45. package/lib/workflows/abort.js +158 -0
  46. package/lib/workflows/abort.js.map +1 -0
  47. package/lib/workflows/ai-provider.js +1 -1
  48. package/lib/workflows/ai-provider.js.map +1 -1
  49. package/lib/workflows/alias.d.ts +6 -0
  50. package/lib/workflows/alias.d.ts.map +1 -0
  51. package/lib/workflows/alias.js +420 -0
  52. package/lib/workflows/alias.js.map +1 -0
  53. package/lib/workflows/amend.d.ts.map +1 -1
  54. package/lib/workflows/amend.js +9 -4
  55. package/lib/workflows/amend.js.map +1 -1
  56. package/lib/workflows/branch-helpers.js +2 -2
  57. package/lib/workflows/branch-helpers.js.map +1 -1
  58. package/lib/workflows/branch-utils.d.ts.map +1 -1
  59. package/lib/workflows/branch-utils.js +4 -3
  60. package/lib/workflows/branch-utils.js.map +1 -1
  61. package/lib/workflows/branch.d.ts.map +1 -1
  62. package/lib/workflows/branch.js +7 -4
  63. package/lib/workflows/branch.js.map +1 -1
  64. package/lib/workflows/cleanup.js +3 -3
  65. package/lib/workflows/cleanup.js.map +1 -1
  66. package/lib/workflows/commit.d.ts.map +1 -1
  67. package/lib/workflows/commit.js +58 -6
  68. package/lib/workflows/commit.js.map +1 -1
  69. package/lib/workflows/dry-run.d.ts +5 -0
  70. package/lib/workflows/dry-run.d.ts.map +1 -0
  71. package/lib/workflows/dry-run.js +127 -0
  72. package/lib/workflows/dry-run.js.map +1 -0
  73. package/lib/workflows/fetch.d.ts +9 -0
  74. package/lib/workflows/fetch.d.ts.map +1 -0
  75. package/lib/workflows/fetch.js +118 -0
  76. package/lib/workflows/fetch.js.map +1 -0
  77. package/lib/workflows/issue.d.ts.map +1 -1
  78. package/lib/workflows/issue.js +317 -72
  79. package/lib/workflows/issue.js.map +1 -1
  80. package/lib/workflows/main-steps.d.ts.map +1 -1
  81. package/lib/workflows/main-steps.js +144 -99
  82. package/lib/workflows/main-steps.js.map +1 -1
  83. package/lib/workflows/main.d.ts.map +1 -1
  84. package/lib/workflows/main.js +14 -6
  85. package/lib/workflows/main.js.map +1 -1
  86. package/lib/workflows/pr.d.ts.map +1 -1
  87. package/lib/workflows/pr.js +307 -39
  88. package/lib/workflows/pr.js.map +1 -1
  89. package/lib/workflows/prune.d.ts +9 -0
  90. package/lib/workflows/prune.d.ts.map +1 -0
  91. package/lib/workflows/prune.js +116 -0
  92. package/lib/workflows/prune.js.map +1 -0
  93. package/lib/workflows/pull.d.ts +9 -0
  94. package/lib/workflows/pull.d.ts.map +1 -0
  95. package/lib/workflows/pull.js +281 -0
  96. package/lib/workflows/pull.js.map +1 -0
  97. package/lib/workflows/release.d.ts.map +1 -1
  98. package/lib/workflows/release.js +50 -38
  99. package/lib/workflows/release.js.map +1 -1
  100. package/lib/workflows/repo-settings.js +2 -2
  101. package/lib/workflows/repo-settings.js.map +1 -1
  102. package/lib/workflows/revert.d.ts +9 -0
  103. package/lib/workflows/revert.d.ts.map +1 -0
  104. package/lib/workflows/revert.js +77 -0
  105. package/lib/workflows/revert.js.map +1 -0
  106. package/lib/workflows/reword.d.ts +9 -0
  107. package/lib/workflows/reword.d.ts.map +1 -0
  108. package/lib/workflows/reword.js +722 -0
  109. package/lib/workflows/reword.js.map +1 -0
  110. package/lib/workflows/settings.js +1 -1
  111. package/lib/workflows/settings.js.map +1 -1
  112. package/lib/workflows/status.d.ts +9 -0
  113. package/lib/workflows/status.d.ts.map +1 -0
  114. package/lib/workflows/status.js +164 -0
  115. package/lib/workflows/status.js.map +1 -0
  116. 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;AAm0BH,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CA6kBlD,CAAA"}
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"}
@@ -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, ProgressBar } from '../cli/input.js';
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 = log.spinner();
275
- spinner.start('Checking GitHub releases...');
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 Copilot (Recommended)', value: 'copilot' },
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 = log.spinner();
394
+ const aiSpinner = new ScrambleProgress();
394
395
  const modelDisplay = getModelValue(copilotModel ?? openrouterModel ?? geminiModel ?? '');
395
- aiSpinner.start(`Generating notes for ${tag} with ${getAIProviderShortName(aiProvider)}` +
396
- (modelDisplay ? ` (${modelDisplay})` : '') +
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 = log.spinner();
438
+ const releaseSpinner = new ScrambleProgress();
436
439
  // Ensure tag exists on remote before creating GitHub Release
437
- releaseSpinner.start(`Pushing tag ${colors.yellow}${tag}${colors.reset} to remote...`);
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 = log.spinner();
447
- createSpinner.start(`Creating release ${colors.yellow}${tag}${colors.reset}...`);
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 = log.spinner();
491
- spinner.start('Fetching GitHub releases...');
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 = log.spinner();
517
- releaseSpinner.start(`Deleting release ${colors.yellow}${release}${colors.reset}...`);
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 = log.spinner();
658
- pushSpinner.start('Pushing tags to remote...');
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 Copilot (Recommended)', value: 'copilot' },
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 = log.spinner();
875
+ const spinner = new ScrambleProgress();
869
876
  const modelDisplay = getModelValue(copilotModel ?? openrouterModel ?? geminiModel ?? '');
870
- spinner.start(`Generating release notes with ${getAIProviderShortName(aiProvider)}` +
871
- (modelDisplay ? ` (${modelDisplay})` : '') +
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: 'GitHub Copilot', value: 'copilot' },
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
- const progressBar = new ProgressBar(100, 'Pushing to remote');
1103
- let progress = 0;
1104
- const interval = setInterval(() => {
1105
- progress = Math.min(95, progress + Math.max(1, Math.floor(Math.random() * 6)));
1106
- progressBar.update(progress);
1107
- }, 250);
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
- clearInterval(interval);
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
- clearInterval(interval);
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 = log.spinner();
1144
- releaseSpinner.start('Creating GitHub Release...');
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');