geeto 0.1.1 → 0.3.3

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 (118) hide show
  1. package/README.md +138 -43
  2. package/lib/api/github.d.ts +91 -0
  3. package/lib/api/github.d.ts.map +1 -0
  4. package/lib/api/github.js +163 -0
  5. package/lib/api/github.js.map +1 -0
  6. package/lib/api/trello.js +1 -1
  7. package/lib/api/trello.js.map +1 -1
  8. package/lib/cli/input.d.ts +1 -0
  9. package/lib/cli/input.d.ts.map +1 -1
  10. package/lib/cli/input.js +349 -0
  11. package/lib/cli/input.js.map +1 -1
  12. package/lib/cli/menu.d.ts +4 -0
  13. package/lib/cli/menu.d.ts.map +1 -1
  14. package/lib/cli/menu.js +452 -31
  15. package/lib/cli/menu.js.map +1 -1
  16. package/lib/core/github-setup.d.ts +8 -0
  17. package/lib/core/github-setup.d.ts.map +1 -0
  18. package/lib/core/github-setup.js +114 -0
  19. package/lib/core/github-setup.js.map +1 -0
  20. package/lib/index.js +291 -29
  21. package/lib/index.js.map +1 -1
  22. package/lib/types/index.d.ts +15 -0
  23. package/lib/types/index.d.ts.map +1 -1
  24. package/lib/utils/branch-naming.js +1 -1
  25. package/lib/utils/branch-naming.js.map +1 -1
  26. package/lib/utils/config.d.ts +17 -1
  27. package/lib/utils/config.d.ts.map +1 -1
  28. package/lib/utils/config.js +53 -1
  29. package/lib/utils/config.js.map +1 -1
  30. package/lib/utils/display.d.ts +20 -0
  31. package/lib/utils/display.d.ts.map +1 -1
  32. package/lib/utils/display.js +84 -21
  33. package/lib/utils/display.js.map +1 -1
  34. package/lib/utils/exec.d.ts +1 -1
  35. package/lib/utils/exec.d.ts.map +1 -1
  36. package/lib/utils/exec.js +2 -2
  37. package/lib/utils/exec.js.map +1 -1
  38. package/lib/utils/git-errors.js +3 -3
  39. package/lib/utils/git-errors.js.map +1 -1
  40. package/lib/utils/git.d.ts +9 -0
  41. package/lib/utils/git.d.ts.map +1 -1
  42. package/lib/utils/git.js +15 -0
  43. package/lib/utils/git.js.map +1 -1
  44. package/lib/utils/logging.d.ts +2 -0
  45. package/lib/utils/logging.d.ts.map +1 -1
  46. package/lib/utils/logging.js +7 -1
  47. package/lib/utils/logging.js.map +1 -1
  48. package/lib/workflows/amend.d.ts +9 -0
  49. package/lib/workflows/amend.d.ts.map +1 -0
  50. package/lib/workflows/amend.js +241 -0
  51. package/lib/workflows/amend.js.map +1 -0
  52. package/lib/workflows/branch.d.ts.map +1 -1
  53. package/lib/workflows/branch.js +2 -1
  54. package/lib/workflows/branch.js.map +1 -1
  55. package/lib/workflows/cherry-pick.d.ts +9 -0
  56. package/lib/workflows/cherry-pick.d.ts.map +1 -0
  57. package/lib/workflows/cherry-pick.js +237 -0
  58. package/lib/workflows/cherry-pick.js.map +1 -0
  59. package/lib/workflows/cleanup.d.ts +1 -1
  60. package/lib/workflows/cleanup.d.ts.map +1 -1
  61. package/lib/workflows/cleanup.js +93 -69
  62. package/lib/workflows/cleanup.js.map +1 -1
  63. package/lib/workflows/commit.d.ts.map +1 -1
  64. package/lib/workflows/commit.js +38 -19
  65. package/lib/workflows/commit.js.map +1 -1
  66. package/lib/workflows/compare.d.ts +9 -0
  67. package/lib/workflows/compare.d.ts.map +1 -0
  68. package/lib/workflows/compare.js +231 -0
  69. package/lib/workflows/compare.js.map +1 -0
  70. package/lib/workflows/history.d.ts +9 -0
  71. package/lib/workflows/history.d.ts.map +1 -0
  72. package/lib/workflows/history.js +194 -0
  73. package/lib/workflows/history.js.map +1 -0
  74. package/lib/workflows/issue.d.ts +9 -0
  75. package/lib/workflows/issue.d.ts.map +1 -0
  76. package/lib/workflows/issue.js +211 -0
  77. package/lib/workflows/issue.js.map +1 -0
  78. package/lib/workflows/main-steps.d.ts.map +1 -1
  79. package/lib/workflows/main-steps.js +12 -10
  80. package/lib/workflows/main-steps.js.map +1 -1
  81. package/lib/workflows/main.d.ts.map +1 -1
  82. package/lib/workflows/main.js +29 -38
  83. package/lib/workflows/main.js.map +1 -1
  84. package/lib/workflows/pr.d.ts +9 -0
  85. package/lib/workflows/pr.d.ts.map +1 -0
  86. package/lib/workflows/pr.js +280 -0
  87. package/lib/workflows/pr.js.map +1 -0
  88. package/lib/workflows/release.d.ts +7 -0
  89. package/lib/workflows/release.d.ts.map +1 -0
  90. package/lib/workflows/release.js +445 -0
  91. package/lib/workflows/release.js.map +1 -0
  92. package/lib/workflows/security-gate.d.ts.map +1 -1
  93. package/lib/workflows/security-gate.js +91 -7
  94. package/lib/workflows/security-gate.js.map +1 -1
  95. package/lib/workflows/settings.d.ts +5 -1
  96. package/lib/workflows/settings.d.ts.map +1 -1
  97. package/lib/workflows/settings.js +62 -3
  98. package/lib/workflows/settings.js.map +1 -1
  99. package/lib/workflows/stash.d.ts +9 -0
  100. package/lib/workflows/stash.d.ts.map +1 -0
  101. package/lib/workflows/stash.js +341 -0
  102. package/lib/workflows/stash.js.map +1 -0
  103. package/lib/workflows/stats.d.ts +9 -0
  104. package/lib/workflows/stats.d.ts.map +1 -0
  105. package/lib/workflows/stats.js +288 -0
  106. package/lib/workflows/stats.js.map +1 -0
  107. package/lib/workflows/switch.d.ts +9 -0
  108. package/lib/workflows/switch.d.ts.map +1 -0
  109. package/lib/workflows/switch.js +154 -0
  110. package/lib/workflows/switch.js.map +1 -0
  111. package/lib/workflows/trello-menu.d.ts.map +1 -1
  112. package/lib/workflows/trello-menu.js +59 -19
  113. package/lib/workflows/trello-menu.js.map +1 -1
  114. package/lib/workflows/undo.d.ts +9 -0
  115. package/lib/workflows/undo.d.ts.map +1 -0
  116. package/lib/workflows/undo.js +464 -0
  117. package/lib/workflows/undo.js.map +1 -0
  118. package/package.json +2 -2
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Release/Tag Manager workflow
3
+ * Create releases with semver bumping, package.json update,
4
+ * RELEASE.MD (user-friendly) and CHANGELOG.md (developer-facing)
5
+ */
6
+ import { readFileSync, writeFileSync } from 'node:fs';
7
+ import { askQuestion, confirm, ProgressBar } from '../cli/input.js';
8
+ import { select } from '../cli/menu.js';
9
+ import { colors } from '../utils/colors.js';
10
+ import { exec, execAsync, execSilent } from '../utils/exec.js';
11
+ import { log } from '../utils/logging.js';
12
+ // ─── Helpers ───
13
+ const parseSemver = (version) => {
14
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
15
+ if (!match)
16
+ return null;
17
+ return {
18
+ major: Number.parseInt(match[1] ?? '0', 10),
19
+ minor: Number.parseInt(match[2] ?? '0', 10),
20
+ patch: Number.parseInt(match[3] ?? '0', 10),
21
+ };
22
+ };
23
+ const getCurrentVersion = () => {
24
+ try {
25
+ const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
26
+ return pkg.version ?? '0.0.0';
27
+ }
28
+ catch {
29
+ return '0.0.0';
30
+ }
31
+ };
32
+ const getExistingTags = () => {
33
+ try {
34
+ const output = execSilent('git tag --list --sort=-v:refname').trim();
35
+ return output ? output.split('\n').filter(Boolean) : [];
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ };
41
+ const getCommitsSinceTag = (tag) => {
42
+ try {
43
+ const sep = '<<GTO>>';
44
+ const range = tag ? `${tag}..HEAD` : 'HEAD';
45
+ const output = execSilent(`git log ${range} --format="%H${sep}%h${sep}%s${sep}%an${sep}%ci" --no-merges`).trim();
46
+ if (!output)
47
+ return [];
48
+ return output
49
+ .split('\n')
50
+ .filter(Boolean)
51
+ .map((line) => {
52
+ const parts = line.split(sep);
53
+ return {
54
+ hash: parts[0] ?? '',
55
+ short: parts[1] ?? '',
56
+ subject: parts[2] ?? '',
57
+ author: parts[3] ?? '',
58
+ date: parts[4] ?? '',
59
+ };
60
+ });
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ };
66
+ const categorizeCommits = (commits) => {
67
+ const result = {
68
+ features: [],
69
+ fixes: [],
70
+ breaking: [],
71
+ other: [],
72
+ };
73
+ for (const c of commits) {
74
+ if (c.subject.includes('BREAKING CHANGE') || c.subject.includes('!:')) {
75
+ result.breaking = [...result.breaking, c];
76
+ }
77
+ else if (c.subject.startsWith('feat')) {
78
+ result.features = [...result.features, c];
79
+ }
80
+ else if (c.subject.startsWith('fix')) {
81
+ result.fixes = [...result.fixes, c];
82
+ }
83
+ else {
84
+ result.other = [...result.other, c];
85
+ }
86
+ }
87
+ return result;
88
+ };
89
+ const getRepoUrl = () => {
90
+ try {
91
+ return execSilent('git config --get remote.origin.url')
92
+ .trim()
93
+ .replace(/\.git$/, '')
94
+ .replace(/^git@github\.com:/, 'https://github.com/');
95
+ }
96
+ catch {
97
+ return '';
98
+ }
99
+ };
100
+ const updatePackageVersion = (newVersion) => {
101
+ const content = readFileSync('package.json', 'utf8');
102
+ const pkg = JSON.parse(content);
103
+ pkg.version = newVersion;
104
+ writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n', 'utf8');
105
+ };
106
+ // ─── stripConventional helpers ───
107
+ const stripFeatPrefix = (s) => {
108
+ const idx = s.indexOf(': ');
109
+ if (idx !== -1 && s.slice(0, idx).startsWith('feat'))
110
+ return s.slice(idx + 2);
111
+ return s.replace(/^feat:\s*/, '');
112
+ };
113
+ const stripFixPrefix = (s) => {
114
+ const idx = s.indexOf(': ');
115
+ if (idx !== -1 && s.slice(0, idx).startsWith('fix'))
116
+ return s.slice(idx + 2);
117
+ return s.replace(/^fix:\s*/, '');
118
+ };
119
+ const stripBreakingPrefix = (s) => {
120
+ const idx = s.indexOf('!: ');
121
+ if (idx !== -1)
122
+ return s.slice(idx + 3);
123
+ return s.replace(/BREAKING CHANGE:\s*/, '');
124
+ };
125
+ const stripConventionalPrefix = (s) => {
126
+ const idx = s.indexOf(': ');
127
+ if (idx !== -1)
128
+ return s.slice(idx + 2);
129
+ return s;
130
+ };
131
+ // ─── RELEASE.MD generator (user-facing, simple language) ───
132
+ const generateReleaseMd = (version, commits, prevVersion) => {
133
+ const now = new Date();
134
+ const date = now.toLocaleDateString('en-US', {
135
+ year: 'numeric',
136
+ month: 'long',
137
+ day: 'numeric',
138
+ });
139
+ const cat = categorizeCommits(commits);
140
+ const header = [
141
+ `# Release v${version}`,
142
+ '',
143
+ `**Release date:** ${date}`,
144
+ `**Previous version:** v${prevVersion}`,
145
+ '',
146
+ "## What's New?",
147
+ '',
148
+ ];
149
+ const featureSection = cat.features.length > 0
150
+ ? ['### New Features', '', ...cat.features.map((f) => `- ${stripFeatPrefix(f.subject)}`), '']
151
+ : [];
152
+ const fixSection = cat.fixes.length > 0
153
+ ? ['### Bug Fixes', '', ...cat.fixes.map((f) => `- ${stripFixPrefix(f.subject)}`), '']
154
+ : [];
155
+ const breakingSection = cat.breaking.length > 0
156
+ ? [
157
+ '### Important Changes',
158
+ '',
159
+ '> Note: Some changes in this version may require adjustments.',
160
+ '',
161
+ ...cat.breaking.map((b) => `- ${stripBreakingPrefix(b.subject)}`),
162
+ '',
163
+ ]
164
+ : [];
165
+ const otherSection = cat.other.length > 0
166
+ ? [
167
+ '### Other Improvements',
168
+ '',
169
+ ...cat.other.map((o) => `- ${stripConventionalPrefix(o.subject)}`),
170
+ '',
171
+ ]
172
+ : [];
173
+ const empty = commits.length === 0 ? ['No significant changes in this version.', ''] : [];
174
+ const footer = [
175
+ '---',
176
+ '',
177
+ '*This document was automatically generated by [Geeto CLI](https://github.com/rust142/geeto)*',
178
+ '',
179
+ ];
180
+ return [
181
+ ...header,
182
+ ...featureSection,
183
+ ...fixSection,
184
+ ...breakingSection,
185
+ ...otherSection,
186
+ ...empty,
187
+ ...footer,
188
+ ].join('\n');
189
+ };
190
+ // ─── CHANGELOG.md generator (developer-facing, per-commit) ───
191
+ const generateChangelogEntry = (version, commits, prevVersion) => {
192
+ const repoUrl = getRepoUrl();
193
+ const dateStr = new Date().toISOString().slice(0, 10);
194
+ const cat = categorizeCommits(commits);
195
+ const commitLink = (c) => repoUrl ? `[${c.short}](${repoUrl}/commit/${c.short})` : c.short;
196
+ const versionLink = repoUrl
197
+ ? `[${version}](${repoUrl}/compare/v${prevVersion}...v${version})`
198
+ : version;
199
+ const header = [`## ${versionLink} (${dateStr})`, ''];
200
+ const breakingSection = cat.breaking.length > 0
201
+ ? [
202
+ '### BREAKING CHANGES',
203
+ '',
204
+ ...cat.breaking.map((c) => `* ${c.subject} (${commitLink(c)})`),
205
+ '',
206
+ ]
207
+ : [];
208
+ const featureSection = cat.features.length > 0
209
+ ? ['### Features', '', ...cat.features.map((c) => `* ${c.subject} (${commitLink(c)})`), '']
210
+ : [];
211
+ const fixSection = cat.fixes.length > 0
212
+ ? ['### Bug Fixes', '', ...cat.fixes.map((c) => `* ${c.subject} (${commitLink(c)})`), '']
213
+ : [];
214
+ const otherSection = cat.other.length > 0
215
+ ? ['### Other Changes', '', ...cat.other.map((c) => `* ${c.subject} (${commitLink(c)})`), '']
216
+ : [];
217
+ return [...header, ...breakingSection, ...featureSection, ...fixSection, ...otherSection].join('\n');
218
+ };
219
+ // ─── Main handler ───
220
+ export const handleRelease = async () => {
221
+ log.banner();
222
+ log.step(`${colors.cyan}Release / Tag Manager${colors.reset}\n`);
223
+ const currentVersion = getCurrentVersion();
224
+ const semver = parseSemver(currentVersion);
225
+ if (!semver) {
226
+ log.error(`Invalid version in package.json: ${currentVersion}`);
227
+ return;
228
+ }
229
+ const tags = getExistingTags();
230
+ const lastTag = tags[0] ?? '';
231
+ // Show current state
232
+ const line = '─'.repeat(56);
233
+ console.log(`${colors.cyan}┌${line}┐${colors.reset}`);
234
+ console.log(`${colors.cyan}│${colors.reset} ${colors.bright}Current version: ${colors.yellow}v${currentVersion}${colors.reset}`);
235
+ if (lastTag) {
236
+ console.log(`${colors.cyan}│${colors.reset} ${colors.gray}Last tag: ${lastTag}${colors.reset}`);
237
+ }
238
+ console.log(`${colors.cyan}│${colors.reset} ${colors.gray}Total tags: ${tags.length}${colors.reset}`);
239
+ console.log(`${colors.cyan}└${line}┘${colors.reset}`);
240
+ // Get commits since last tag
241
+ const commits = getCommitsSinceTag(lastTag || undefined);
242
+ if (commits.length === 0) {
243
+ console.log('');
244
+ log.warn('No new commits since last tag.');
245
+ const force = confirm('Create a release anyway?');
246
+ if (!force)
247
+ return;
248
+ }
249
+ else {
250
+ console.log('');
251
+ log.info(`${colors.bright}${commits.length}${colors.reset} commits since last tag`);
252
+ }
253
+ // Version bump selection
254
+ console.log('');
255
+ const { major, minor, patch } = semver;
256
+ const bumpType = await select('Version bump:', [
257
+ {
258
+ label: `Patch ${colors.gray}${major}.${minor}.${patch + 1}${colors.reset} — bug fixes`,
259
+ value: 'patch',
260
+ },
261
+ {
262
+ label: `Minor ${colors.gray}${major}.${minor + 1}.0${colors.reset} — new features`,
263
+ value: 'minor',
264
+ },
265
+ {
266
+ label: `Major ${colors.gray}${major + 1}.0.0${colors.reset} — breaking changes`,
267
+ value: 'major',
268
+ },
269
+ { label: 'Custom — enter version manually', value: 'custom' },
270
+ { label: 'Cancel', value: 'cancel' },
271
+ ]);
272
+ if (bumpType === 'cancel')
273
+ return;
274
+ let newVersion;
275
+ switch (bumpType) {
276
+ case 'custom': {
277
+ if (process.stdin.isTTY) {
278
+ process.stdin.setRawMode(false);
279
+ }
280
+ const input = askQuestion('Enter version (e.g. 1.2.3): ').trim();
281
+ if (!parseSemver(input)) {
282
+ log.error('Invalid semver format.');
283
+ return;
284
+ }
285
+ newVersion = input;
286
+ break;
287
+ }
288
+ case 'major': {
289
+ newVersion = `${major + 1}.0.0`;
290
+ break;
291
+ }
292
+ case 'minor': {
293
+ newVersion = `${major}.${minor + 1}.0`;
294
+ break;
295
+ }
296
+ default: {
297
+ newVersion = `${major}.${minor}.${patch + 1}`;
298
+ }
299
+ }
300
+ // Show plan
301
+ console.log('');
302
+ console.log(`${colors.cyan}┌${line}┐${colors.reset}`);
303
+ console.log(`${colors.cyan}│${colors.reset} ${colors.bright}Release Plan${colors.reset}`);
304
+ console.log(`${colors.cyan}├${line}┤${colors.reset}`);
305
+ console.log(`${colors.cyan}│${colors.reset} Version ${colors.yellow}v${currentVersion}${colors.reset} → ${colors.green}v${newVersion}${colors.reset}`);
306
+ console.log(`${colors.cyan}│${colors.reset} Tag ${colors.bright}v${newVersion}${colors.reset}`);
307
+ console.log(`${colors.cyan}│${colors.reset} Files ${colors.gray}package.json, RELEASE.MD, CHANGELOG.md${colors.reset}`);
308
+ console.log(`${colors.cyan}│${colors.reset} Commits ${colors.bright}${commits.length}${colors.reset} changes included`);
309
+ console.log(`${colors.cyan}└${line}┘${colors.reset}`);
310
+ // Preview commit categories
311
+ if (commits.length > 0) {
312
+ const cat = categorizeCommits(commits);
313
+ console.log('');
314
+ if (cat.features.length > 0) {
315
+ log.info(` ${colors.green}+${cat.features.length}${colors.reset} features`);
316
+ }
317
+ if (cat.fixes.length > 0) {
318
+ log.info(` ${colors.yellow}~${cat.fixes.length}${colors.reset} fixes`);
319
+ }
320
+ if (cat.breaking.length > 0) {
321
+ log.info(` ${colors.red}!${cat.breaking.length}${colors.reset} breaking`);
322
+ }
323
+ if (cat.other.length > 0) {
324
+ log.info(` ${colors.gray}○${cat.other.length}${colors.reset} other`);
325
+ }
326
+ }
327
+ console.log('');
328
+ const proceed = confirm('Create this release?');
329
+ if (!proceed) {
330
+ log.info('Cancelled.');
331
+ return;
332
+ }
333
+ // Execute release steps
334
+ const spinner = log.spinner();
335
+ // 1. Update package.json
336
+ spinner.start('Updating package.json...');
337
+ try {
338
+ updatePackageVersion(newVersion);
339
+ spinner.succeed(`package.json → v${newVersion}`);
340
+ }
341
+ catch {
342
+ spinner.fail('Failed to update package.json');
343
+ return;
344
+ }
345
+ // 2. Generate RELEASE.MD
346
+ spinner.start('Generating RELEASE.MD...');
347
+ try {
348
+ writeFileSync('RELEASE.MD', generateReleaseMd(newVersion, commits, currentVersion), 'utf8');
349
+ spinner.succeed('RELEASE.MD generated');
350
+ }
351
+ catch {
352
+ spinner.fail('Failed to generate RELEASE.MD');
353
+ }
354
+ // 3. Update CHANGELOG.md
355
+ spinner.start('Updating CHANGELOG.md...');
356
+ try {
357
+ const newEntry = generateChangelogEntry(newVersion, commits, currentVersion);
358
+ let existing = '';
359
+ try {
360
+ existing = readFileSync('CHANGELOG.md', 'utf8');
361
+ }
362
+ catch {
363
+ // File doesn't exist yet
364
+ }
365
+ let changelog;
366
+ if (existing.startsWith('# Changelog')) {
367
+ const headerEnd = existing.indexOf('\n') + 1;
368
+ changelog = existing.slice(0, headerEnd) + '\n' + newEntry + existing.slice(headerEnd);
369
+ }
370
+ else if (existing) {
371
+ changelog = '# Changelog\n\n' + newEntry + existing;
372
+ }
373
+ else {
374
+ changelog = '# Changelog\n\n' + newEntry;
375
+ }
376
+ writeFileSync('CHANGELOG.md', changelog, 'utf8');
377
+ spinner.succeed('CHANGELOG.md updated');
378
+ }
379
+ catch {
380
+ spinner.fail('Failed to update CHANGELOG.md');
381
+ }
382
+ // 4. Stage, commit, tag
383
+ spinner.start('Creating release commit...');
384
+ try {
385
+ exec('git add package.json RELEASE.MD CHANGELOG.md', true);
386
+ exec(`git commit --no-verify -m "chore(release): v${newVersion}"`, true);
387
+ spinner.succeed('Release commit created');
388
+ }
389
+ catch {
390
+ spinner.fail('Failed to create release commit');
391
+ return;
392
+ }
393
+ spinner.start(`Creating tag v${newVersion}...`);
394
+ try {
395
+ exec(`git tag -a v${newVersion} -m "Release v${newVersion}"`, true);
396
+ spinner.succeed(`Tag v${newVersion} created`);
397
+ }
398
+ catch {
399
+ spinner.fail('Failed to create tag');
400
+ return;
401
+ }
402
+ // 5. Push
403
+ console.log('');
404
+ const pushChoice = await select('Push to remote?', [
405
+ { label: 'Push commit + tag', value: 'both' },
406
+ { label: 'Push commit only', value: 'commit' },
407
+ { label: 'Skip pushing', value: 'skip' },
408
+ ]);
409
+ if (pushChoice === 'both' || pushChoice === 'commit') {
410
+ const progressBar = new ProgressBar(100, 'Pushing to remote');
411
+ let progress = 0;
412
+ const interval = setInterval(() => {
413
+ progress = Math.min(95, progress + Math.max(1, Math.floor(Math.random() * 6)));
414
+ progressBar.update(progress);
415
+ }, 250);
416
+ try {
417
+ await execAsync(`git push`, true);
418
+ if (pushChoice === 'both') {
419
+ await execAsync(`git push origin v${newVersion}`, true);
420
+ }
421
+ clearInterval(interval);
422
+ progressBar.update(100);
423
+ progressBar.complete();
424
+ console.log('');
425
+ log.success(pushChoice === 'both' ? 'Pushed commit + tag' : 'Pushed commit');
426
+ }
427
+ catch {
428
+ clearInterval(interval);
429
+ progressBar.complete();
430
+ console.log('');
431
+ log.error('Failed to push');
432
+ }
433
+ }
434
+ // Summary
435
+ console.log('');
436
+ console.log(`${colors.cyan}┌${line}┐${colors.reset}`);
437
+ console.log(`${colors.cyan}│${colors.reset} ${colors.green}✓${colors.reset} ${colors.bright}Release v${newVersion} created!${colors.reset}`);
438
+ console.log(`${colors.cyan}├${line}┤${colors.reset}`);
439
+ console.log(`${colors.cyan}│${colors.reset} ${colors.green}✓${colors.reset} package.json updated`);
440
+ console.log(`${colors.cyan}│${colors.reset} ${colors.green}✓${colors.reset} RELEASE.MD generated ${colors.gray}(user-facing)${colors.reset}`);
441
+ console.log(`${colors.cyan}│${colors.reset} ${colors.green}✓${colors.reset} CHANGELOG.md updated ${colors.gray}(developer-facing)${colors.reset}`);
442
+ console.log(`${colors.cyan}│${colors.reset} ${colors.green}✓${colors.reset} Tag v${newVersion} created`);
443
+ console.log(`${colors.cyan}└${line}┘${colors.reset}`);
444
+ };
445
+ //# sourceMappingURL=release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.js","sourceRoot":"","sources":["../../src/workflows/release.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"security-gate.d.ts","sourceRoot":"","sources":["../../src/workflows/security-gate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqbH;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2G1D"}
1
+ {"version":3,"file":"security-gate.d.ts","sourceRoot":"","sources":["../../src/workflows/security-gate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAggBH;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2I1D"}
@@ -4,7 +4,7 @@
4
4
  import fs from 'node:fs/promises';
5
5
  import path from 'node:path';
6
6
  import { confirm } from '../cli/input.js';
7
- import { select } from '../cli/menu.js';
7
+ import { multiSelect, select } from '../cli/menu.js';
8
8
  import { colors } from '../utils/colors.js';
9
9
  import { exec } from '../utils/exec.js';
10
10
  import { getCurrentBranch, getStagedFiles } from '../utils/git.js';
@@ -44,6 +44,65 @@ function collectSecurityData() {
44
44
  hasDependencies,
45
45
  };
46
46
  }
47
+ /**
48
+ * Collect data from specific commits for security analysis
49
+ */
50
+ function collectCommitData(commitHashes) {
51
+ let diff = '';
52
+ const allFiles = new Set();
53
+ for (const hash of commitHashes) {
54
+ try {
55
+ const commitDiff = exec(`git show ${hash} --format="" --patch`, true);
56
+ diff += commitDiff + '\n';
57
+ }
58
+ catch {
59
+ // skip if commit can't be read
60
+ }
61
+ try {
62
+ const files = exec(`git show ${hash} --format="" --name-only`, true)
63
+ .split('\n')
64
+ .filter(Boolean);
65
+ for (const f of files)
66
+ allFiles.add(f);
67
+ }
68
+ catch {
69
+ // skip
70
+ }
71
+ }
72
+ const files = [...allFiles];
73
+ // Truncate if too long
74
+ const truncatedDiff = diff.length > 10000 ? diff.slice(0, 10000) + '\n\n... (diff truncated)' : diff;
75
+ const hasDependencies = files.some((f) => f.includes('package.json') ||
76
+ f.includes('requirements.txt') ||
77
+ f.includes('Gemfile') ||
78
+ f.includes('pom.xml') ||
79
+ f.includes('go.mod'));
80
+ return { diff: truncatedDiff, files, hasDependencies };
81
+ }
82
+ /**
83
+ * Get recent commits for selection
84
+ */
85
+ function getRecentCommits(count = 30) {
86
+ try {
87
+ const logOutput = exec(`git log -${count} --no-merges --format="%H|%h|%s|%cr"`, true);
88
+ return logOutput
89
+ .split('\n')
90
+ .filter(Boolean)
91
+ .map((line) => {
92
+ const [hash, shortHash, subject, date] = line.split('|');
93
+ return {
94
+ hash: hash ?? '',
95
+ shortHash: shortHash ?? '',
96
+ subject: subject ?? '',
97
+ date: date ?? '',
98
+ };
99
+ })
100
+ .filter((c) => c.hash !== '');
101
+ }
102
+ catch {
103
+ return [];
104
+ }
105
+ }
47
106
  /**
48
107
  * Build AI prompt for security analysis
49
108
  */
@@ -254,7 +313,6 @@ async function runSecurityScan(data, aiProvider, model) {
254
313
  }
255
314
  spinner.stop();
256
315
  if (result) {
257
- log.success('Security analysis complete!');
258
316
  return result;
259
317
  }
260
318
  log.warn('AI returned empty response');
@@ -386,16 +444,42 @@ export async function showSecurityGateMenu() {
386
444
  const scanChoice = await select('What would you like to analyze?', [
387
445
  { label: 'Staged changes', value: 'staged' },
388
446
  { label: 'All uncommitted changes', value: 'all' },
447
+ { label: 'Specific commits', value: 'commits' },
389
448
  { label: 'Cancel', value: 'cancel' },
390
449
  ]);
391
450
  if (scanChoice === 'cancel') {
392
451
  return;
393
452
  }
394
- // Collect data
395
- const spinner = log.spinner();
396
- spinner.start('Collecting code changes...');
397
- const scanData = collectSecurityData();
398
- spinner.stop();
453
+ let scanData;
454
+ if (scanChoice === 'commits') {
455
+ // Fetch recent commits and let user pick
456
+ const commits = getRecentCommits();
457
+ if (commits.length === 0) {
458
+ log.warn('No commits found.');
459
+ return;
460
+ }
461
+ const commitChoices = commits.map((c) => ({
462
+ label: `${colors.yellow}${c.shortHash}${colors.reset} ${c.subject} ${colors.gray}(${c.date})${colors.reset}`,
463
+ value: c.hash,
464
+ }));
465
+ const selectedHashes = await multiSelect('Select commits to analyze:', commitChoices);
466
+ if (selectedHashes.length === 0) {
467
+ log.warn('No commits selected. Cancelled.');
468
+ return;
469
+ }
470
+ log.info(`Analyzing ${colors.cyan}${selectedHashes.length}${colors.reset} commits`);
471
+ const spinner = log.spinner();
472
+ spinner.start('Collecting commit changes...');
473
+ scanData = collectCommitData(selectedHashes);
474
+ spinner.stop();
475
+ }
476
+ else {
477
+ // Collect staged or all uncommitted changes
478
+ const spinner = log.spinner();
479
+ spinner.start('Collecting code changes...');
480
+ scanData = collectSecurityData();
481
+ spinner.stop();
482
+ }
399
483
  if (!scanData.diff || scanData.diff === 'No diff available' || scanData.diff.trim() === '') {
400
484
  log.warn('No code changes detected. Nothing to analyze.');
401
485
  return;