@snapcommit/cli 3.0.0 ā 3.1.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/dist/commands/cursor-style.js +154 -4
- package/dist/lib/github.js +114 -12
- package/package.json +1 -1
|
@@ -272,9 +272,10 @@ async function executeGitHubCommand(intent) {
|
|
|
272
272
|
try {
|
|
273
273
|
switch (intent.action) {
|
|
274
274
|
case 'pr_create':
|
|
275
|
-
|
|
275
|
+
const isDraft = intent.options?.draft || false;
|
|
276
|
+
console.log(chalk_1.default.blue(`\nš Creating ${isDraft ? 'draft ' : ''}PR...`));
|
|
276
277
|
const pr = await github.createPullRequest(intent.options || {});
|
|
277
|
-
console.log(chalk_1.default.green(`ā PR #${pr.number} created`));
|
|
278
|
+
console.log(chalk_1.default.green(`ā ${isDraft ? 'Draft ' : ''}PR #${pr.number} created`));
|
|
278
279
|
console.log(chalk_1.default.cyan(` ${pr.html_url}\n`));
|
|
279
280
|
break;
|
|
280
281
|
case 'pr_list':
|
|
@@ -302,8 +303,24 @@ async function executeGitHubCommand(intent) {
|
|
|
302
303
|
break;
|
|
303
304
|
case 'ci_check':
|
|
304
305
|
console.log(chalk_1.default.blue('\nš Checking CI status...'));
|
|
305
|
-
|
|
306
|
-
|
|
306
|
+
try {
|
|
307
|
+
const ciStatus = await github.getCommitStatus();
|
|
308
|
+
const state = ciStatus.status.state;
|
|
309
|
+
const totalChecks = ciStatus.checks.length;
|
|
310
|
+
const failedChecks = ciStatus.checks.filter((c) => c.conclusion === 'failure').length;
|
|
311
|
+
if (state === 'success' || (totalChecks > 0 && failedChecks === 0)) {
|
|
312
|
+
console.log(chalk_1.default.green(`ā All checks passed (${totalChecks} checks)\n`));
|
|
313
|
+
}
|
|
314
|
+
else if (state === 'pending') {
|
|
315
|
+
console.log(chalk_1.default.yellow(`ā³ Checks running (${totalChecks} checks)\n`));
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
console.log(chalk_1.default.red(`ā ${failedChecks}/${totalChecks} checks failed\n`));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
console.log(chalk_1.default.gray(' No CI checks found\n'));
|
|
323
|
+
}
|
|
307
324
|
break;
|
|
308
325
|
case 'issue_create':
|
|
309
326
|
console.log(chalk_1.default.blue('\nš Creating issue...'));
|
|
@@ -324,6 +341,139 @@ async function executeGitHubCommand(intent) {
|
|
|
324
341
|
console.log();
|
|
325
342
|
}
|
|
326
343
|
break;
|
|
344
|
+
case 'issue_close':
|
|
345
|
+
const closeIssueNum = intent.target || intent.options?.number;
|
|
346
|
+
if (!closeIssueNum) {
|
|
347
|
+
console.log(chalk_1.default.red('\nā Issue number required\n'));
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
console.log(chalk_1.default.blue(`\nš Closing issue #${closeIssueNum}...`));
|
|
351
|
+
await github.closeIssue(closeIssueNum);
|
|
352
|
+
console.log(chalk_1.default.green(`ā Issue #${closeIssueNum} closed\n`));
|
|
353
|
+
break;
|
|
354
|
+
case 'issue_reopen':
|
|
355
|
+
const reopenIssueNum = intent.target || intent.options?.number;
|
|
356
|
+
if (!reopenIssueNum) {
|
|
357
|
+
console.log(chalk_1.default.red('\nā Issue number required\n'));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
console.log(chalk_1.default.blue(`\nš Reopening issue #${reopenIssueNum}...`));
|
|
361
|
+
await github.reopenIssue(reopenIssueNum);
|
|
362
|
+
console.log(chalk_1.default.green(`ā Issue #${reopenIssueNum} reopened\n`));
|
|
363
|
+
break;
|
|
364
|
+
case 'pr_review':
|
|
365
|
+
const reviewPrNum = intent.target || intent.options?.number;
|
|
366
|
+
if (!reviewPrNum) {
|
|
367
|
+
console.log(chalk_1.default.red('\nā PR number required\n'));
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const reviewType = intent.options?.type || 'APPROVE';
|
|
371
|
+
const reviewBody = intent.options?.body || '';
|
|
372
|
+
console.log(chalk_1.default.blue(`\nš Reviewing PR #${reviewPrNum}...`));
|
|
373
|
+
await github.reviewPullRequest(reviewPrNum, {
|
|
374
|
+
event: reviewType,
|
|
375
|
+
body: reviewBody,
|
|
376
|
+
});
|
|
377
|
+
if (reviewType === 'APPROVE') {
|
|
378
|
+
console.log(chalk_1.default.green(`ā Approved PR #${reviewPrNum}\n`));
|
|
379
|
+
}
|
|
380
|
+
else if (reviewType === 'REQUEST_CHANGES') {
|
|
381
|
+
console.log(chalk_1.default.yellow(`ā ļø Requested changes on PR #${reviewPrNum}\n`));
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
console.log(chalk_1.default.green(`ā Commented on PR #${reviewPrNum}\n`));
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
case 'pr_comment':
|
|
388
|
+
const commentPrNum = intent.target || intent.options?.number;
|
|
389
|
+
if (!commentPrNum) {
|
|
390
|
+
console.log(chalk_1.default.red('\nā PR number required\n'));
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const prComment = intent.options?.body || intent.options?.comment || '';
|
|
394
|
+
if (!prComment) {
|
|
395
|
+
console.log(chalk_1.default.red('\nā Comment text required\n'));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
console.log(chalk_1.default.blue(`\nš¬ Commenting on PR #${commentPrNum}...`));
|
|
399
|
+
await github.commentOnPullRequest(commentPrNum, prComment);
|
|
400
|
+
console.log(chalk_1.default.green(`ā Comment added\n`));
|
|
401
|
+
break;
|
|
402
|
+
case 'issue_comment':
|
|
403
|
+
const commentIssueNum = intent.target || intent.options?.number;
|
|
404
|
+
if (!commentIssueNum) {
|
|
405
|
+
console.log(chalk_1.default.red('\nā Issue number required\n'));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const issueComment = intent.options?.body || intent.options?.comment || '';
|
|
409
|
+
if (!issueComment) {
|
|
410
|
+
console.log(chalk_1.default.red('\nā Comment text required\n'));
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
console.log(chalk_1.default.blue(`\nš¬ Commenting on issue #${commentIssueNum}...`));
|
|
414
|
+
await github.commentOnIssue(commentIssueNum, issueComment);
|
|
415
|
+
console.log(chalk_1.default.green(`ā Comment added\n`));
|
|
416
|
+
break;
|
|
417
|
+
case 'pr_show':
|
|
418
|
+
case 'pr_status':
|
|
419
|
+
const showPrNum = intent.target || intent.options?.number;
|
|
420
|
+
if (!showPrNum) {
|
|
421
|
+
console.log(chalk_1.default.red('\nā PR number required\n'));
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
console.log(chalk_1.default.blue(`\nš PR #${showPrNum}:\n`));
|
|
425
|
+
const prDetails = await github.getPullRequest(showPrNum);
|
|
426
|
+
console.log(chalk_1.default.white.bold(` ${prDetails.title}`));
|
|
427
|
+
console.log(chalk_1.default.gray(` ${prDetails.user.login} wants to merge ${chalk_1.default.cyan(prDetails.head.ref)} ā ${chalk_1.default.cyan(prDetails.base.ref)}`));
|
|
428
|
+
console.log();
|
|
429
|
+
if (prDetails.state === 'open') {
|
|
430
|
+
console.log(chalk_1.default.green(' ā Open'));
|
|
431
|
+
}
|
|
432
|
+
else if (prDetails.merged) {
|
|
433
|
+
console.log(chalk_1.default.magenta(' ā Merged'));
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
console.log(chalk_1.default.red(' ā Closed'));
|
|
437
|
+
}
|
|
438
|
+
console.log(chalk_1.default.gray(` ${prDetails.comments} comments ⢠${prDetails.commits} commits ⢠${prDetails.changed_files} files\n`));
|
|
439
|
+
if (prDetails.body) {
|
|
440
|
+
console.log(chalk_1.default.white(' Description:'));
|
|
441
|
+
console.log(chalk_1.default.gray(` ${prDetails.body.substring(0, 200)}${prDetails.body.length > 200 ? '...' : ''}\n`));
|
|
442
|
+
}
|
|
443
|
+
break;
|
|
444
|
+
case 'pr_diff':
|
|
445
|
+
const diffPrNum = intent.target || intent.options?.number;
|
|
446
|
+
if (!diffPrNum) {
|
|
447
|
+
console.log(chalk_1.default.red('\nā PR number required\n'));
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
console.log(chalk_1.default.blue(`\nš PR #${diffPrNum} changes:\n`));
|
|
451
|
+
const files = await github.getPullRequestFiles(diffPrNum);
|
|
452
|
+
files.forEach((file) => {
|
|
453
|
+
let symbol = 'ā';
|
|
454
|
+
let color = chalk_1.default.yellow;
|
|
455
|
+
if (file.status === 'added') {
|
|
456
|
+
symbol = '+';
|
|
457
|
+
color = chalk_1.default.green;
|
|
458
|
+
}
|
|
459
|
+
else if (file.status === 'removed') {
|
|
460
|
+
symbol = '-';
|
|
461
|
+
color = chalk_1.default.red;
|
|
462
|
+
}
|
|
463
|
+
console.log(color(` ${symbol} ${file.filename}`) + chalk_1.default.gray(` (+${file.additions} -${file.deletions})`));
|
|
464
|
+
});
|
|
465
|
+
console.log();
|
|
466
|
+
break;
|
|
467
|
+
case 'workflow_rerun':
|
|
468
|
+
const runId = intent.target || intent.options?.runId;
|
|
469
|
+
if (!runId) {
|
|
470
|
+
console.log(chalk_1.default.red('\nā Workflow run ID required\n'));
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
console.log(chalk_1.default.blue(`\nš Re-running workflow #${runId}...`));
|
|
474
|
+
await github.rerunWorkflow(runId);
|
|
475
|
+
console.log(chalk_1.default.green(`ā Workflow re-run started\n`));
|
|
476
|
+
break;
|
|
327
477
|
default:
|
|
328
478
|
console.log(chalk_1.default.yellow(`\nā ļø Action not supported: ${intent.action}\n`));
|
|
329
479
|
}
|
package/dist/lib/github.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getCurrentRepo = getCurrentRepo;
|
|
7
4
|
exports.getCurrentBranch = getCurrentBranch;
|
|
@@ -17,13 +14,16 @@ exports.listIssues = listIssues;
|
|
|
17
14
|
exports.closeIssue = closeIssue;
|
|
18
15
|
exports.createRelease = createRelease;
|
|
19
16
|
exports.getRepoInfo = getRepoInfo;
|
|
17
|
+
exports.reviewPullRequest = reviewPullRequest;
|
|
18
|
+
exports.commentOnPullRequest = commentOnPullRequest;
|
|
19
|
+
exports.commentOnIssue = commentOnIssue;
|
|
20
|
+
exports.getPullRequestDiff = getPullRequestDiff;
|
|
21
|
+
exports.reopenIssue = reopenIssue;
|
|
22
|
+
exports.rerunWorkflow = rerunWorkflow;
|
|
23
|
+
exports.getPullRequestFiles = getPullRequestFiles;
|
|
20
24
|
const child_process_1 = require("child_process");
|
|
21
|
-
const
|
|
22
|
-
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
|
|
25
|
+
const github_connect_1 = require("../commands/github-connect");
|
|
23
26
|
const GITHUB_API = 'https://api.github.com';
|
|
24
|
-
if (!GITHUB_TOKEN) {
|
|
25
|
-
console.warn(chalk_1.default.yellow('ā ļø GitHub token not found. GitHub features will be disabled.'));
|
|
26
|
-
}
|
|
27
27
|
/**
|
|
28
28
|
* Get current repository info from git remote
|
|
29
29
|
*/
|
|
@@ -64,15 +64,16 @@ function getCurrentBranch() {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* GitHub API request helper
|
|
67
|
+
* GitHub API request helper - uses locally stored token
|
|
68
68
|
*/
|
|
69
69
|
async function githubRequest(endpoint, options = {}) {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
const token = (0, github_connect_1.getGitHubToken)();
|
|
71
|
+
if (!token) {
|
|
72
|
+
throw new Error('GitHub not connected. Run: snap github connect');
|
|
72
73
|
}
|
|
73
74
|
const url = `${GITHUB_API}${endpoint}`;
|
|
74
75
|
const headers = {
|
|
75
|
-
Authorization: `Bearer ${
|
|
76
|
+
Authorization: `Bearer ${token}`,
|
|
76
77
|
Accept: 'application/vnd.github+json',
|
|
77
78
|
'X-GitHub-Api-Version': '2022-11-28',
|
|
78
79
|
'Content-Type': 'application/json',
|
|
@@ -115,6 +116,7 @@ async function createPullRequest(options) {
|
|
|
115
116
|
body,
|
|
116
117
|
head: currentBranch,
|
|
117
118
|
base: baseBranch,
|
|
119
|
+
draft: options.draft || false,
|
|
118
120
|
}),
|
|
119
121
|
});
|
|
120
122
|
return pr;
|
|
@@ -278,3 +280,103 @@ async function getRepoInfo() {
|
|
|
278
280
|
}
|
|
279
281
|
return await githubRequest(`/repos/${repo.owner}/${repo.name}`);
|
|
280
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Review a Pull Request
|
|
285
|
+
*/
|
|
286
|
+
async function reviewPullRequest(prNumber, options) {
|
|
287
|
+
const repo = getCurrentRepo();
|
|
288
|
+
if (!repo) {
|
|
289
|
+
throw new Error('Not a GitHub repository');
|
|
290
|
+
}
|
|
291
|
+
return await githubRequest(`/repos/${repo.owner}/${repo.name}/pulls/${prNumber}/reviews`, {
|
|
292
|
+
method: 'POST',
|
|
293
|
+
body: JSON.stringify({
|
|
294
|
+
event: options.event,
|
|
295
|
+
body: options.body || '',
|
|
296
|
+
}),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Comment on a Pull Request
|
|
301
|
+
*/
|
|
302
|
+
async function commentOnPullRequest(prNumber, body) {
|
|
303
|
+
const repo = getCurrentRepo();
|
|
304
|
+
if (!repo) {
|
|
305
|
+
throw new Error('Not a GitHub repository');
|
|
306
|
+
}
|
|
307
|
+
return await githubRequest(`/repos/${repo.owner}/${repo.name}/issues/${prNumber}/comments`, {
|
|
308
|
+
method: 'POST',
|
|
309
|
+
body: JSON.stringify({ body }),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Comment on an Issue
|
|
314
|
+
*/
|
|
315
|
+
async function commentOnIssue(issueNumber, body) {
|
|
316
|
+
const repo = getCurrentRepo();
|
|
317
|
+
if (!repo) {
|
|
318
|
+
throw new Error('Not a GitHub repository');
|
|
319
|
+
}
|
|
320
|
+
return await githubRequest(`/repos/${repo.owner}/${repo.name}/issues/${issueNumber}/comments`, {
|
|
321
|
+
method: 'POST',
|
|
322
|
+
body: JSON.stringify({ body }),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get PR diff
|
|
327
|
+
*/
|
|
328
|
+
async function getPullRequestDiff(prNumber) {
|
|
329
|
+
const repo = getCurrentRepo();
|
|
330
|
+
if (!repo) {
|
|
331
|
+
throw new Error('Not a GitHub repository');
|
|
332
|
+
}
|
|
333
|
+
const token = (0, github_connect_1.getGitHubToken)();
|
|
334
|
+
if (!token) {
|
|
335
|
+
throw new Error('GitHub not connected. Run: snap github connect');
|
|
336
|
+
}
|
|
337
|
+
const response = await fetch(`${GITHUB_API}/repos/${repo.owner}/${repo.name}/pulls/${prNumber}`, {
|
|
338
|
+
headers: {
|
|
339
|
+
Authorization: `Bearer ${token}`,
|
|
340
|
+
Accept: 'application/vnd.github.diff',
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
throw new Error('Failed to fetch PR diff');
|
|
345
|
+
}
|
|
346
|
+
return await response.text();
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Reopen an issue
|
|
350
|
+
*/
|
|
351
|
+
async function reopenIssue(issueNumber) {
|
|
352
|
+
const repo = getCurrentRepo();
|
|
353
|
+
if (!repo) {
|
|
354
|
+
throw new Error('Not a GitHub repository');
|
|
355
|
+
}
|
|
356
|
+
return await githubRequest(`/repos/${repo.owner}/${repo.name}/issues/${issueNumber}`, {
|
|
357
|
+
method: 'PATCH',
|
|
358
|
+
body: JSON.stringify({ state: 'open' }),
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Re-run workflow
|
|
363
|
+
*/
|
|
364
|
+
async function rerunWorkflow(runId) {
|
|
365
|
+
const repo = getCurrentRepo();
|
|
366
|
+
if (!repo) {
|
|
367
|
+
throw new Error('Not a GitHub repository');
|
|
368
|
+
}
|
|
369
|
+
await githubRequest(`/repos/${repo.owner}/${repo.name}/actions/runs/${runId}/rerun`, {
|
|
370
|
+
method: 'POST',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get PR files (what changed)
|
|
375
|
+
*/
|
|
376
|
+
async function getPullRequestFiles(prNumber) {
|
|
377
|
+
const repo = getCurrentRepo();
|
|
378
|
+
if (!repo) {
|
|
379
|
+
throw new Error('Not a GitHub repository');
|
|
380
|
+
}
|
|
381
|
+
return await githubRequest(`/repos/${repo.owner}/${repo.name}/pulls/${prNumber}/files`);
|
|
382
|
+
}
|