From e1b1a6a6ba1bf8908220f3310b16156e2c62c7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Wed, 8 Apr 2026 00:12:50 +0000 Subject: [PATCH] feat: add issue update command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support updating issue title, body, assignee, state, and labels. Both personal and enterprise API endpoints supported (--enterprise flag). gitee issue update --repo owner/repo [--title] [--body] [--assignee] [--state] [--labels] [--enterprise] Closes feedback from 星月 🌙 (SORA Team) 小橘 🍊(NEKO Team) --- package.json | 2 +- src/commands/issue.ts | 64 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index b894f1c..2e55b8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@oc-forge/gitee-cli", - "version": "0.1.1", + "version": "0.2.0", "description": "Gitee (码云) command-line tool — like gh, but for Gitee", "type": "module", "bin": { diff --git a/src/commands/issue.ts b/src/commands/issue.ts index 459ff5e..52ca5e5 100644 --- a/src/commands/issue.ts +++ b/src/commands/issue.ts @@ -146,6 +146,70 @@ export function registerIssueCommands(program: Command): void { } }); + issue + .command('update ') + .description('Update an issue (title, body, assignee, state, labels)') + .option('--repo ', 'Repository (owner/repo)') + .option('--title ', 'New title') + .option('--body <body>', 'New body/description') + .option('--assignee <username>', 'Reassign to user') + .option('--state <state>', 'State: open|closed|progressing|rejected') + .option('--labels <labels>', 'Comma-separated label names') + .option('--enterprise <enterprise>', 'Enterprise name (use enterprise API endpoint)') + .option('--json', 'Output raw JSON') + .action(async (number: string, opts: { + repo?: string; title?: string; body?: string; assignee?: string; + state?: string; labels?: string; enterprise?: string; json?: boolean; + }) => { + const token = getToken(); + if (!token) { + console.error('Error: Authentication required. Run `gitee auth login` or set GITEE_TOKEN.'); + process.exit(1); + } + + // Must have at least one field to update + if (!opts.title && !opts.body && !opts.assignee && !opts.state && !opts.labels) { + console.error('Error: Provide at least one field to update (--title, --body, --assignee, --state, --labels).'); + process.exit(1); + } + + const repoName = resolveRepo(opts.repo); + const [owner, repo] = repoName.split('/'); + + // Build update payload + const payload: Record<string, unknown> = { repo }; + if (opts.title) payload.title = opts.title; + if (opts.body) payload.body = opts.body; + if (opts.assignee) payload.assignee = opts.assignee; + if (opts.state) payload.state = opts.state; + if (opts.labels) payload.labels = opts.labels; + + try { + // Enterprise vs personal API endpoint + const endpoint = opts.enterprise + ? `/enterprises/${opts.enterprise}/issues/${number}` + : `/repos/${owner}/issues/${number}`; + + const updated = await apiRequest<GiteeIssue>(endpoint, { + method: 'PATCH', + token, + body: payload, + }); + + if (opts.json) { + console.log(JSON.stringify(updated, null, 2)); + return; + } + + console.log(`✓ Updated issue #${number}: ${updated.title}`); + if (opts.state) console.log(` State: ${updated.state}`); + if (opts.assignee) console.log(` Assignee: ${updated.assignee?.login || opts.assignee}`); + console.log(` URL: ${updated.html_url}`); + } catch (err) { + handleError(err); + } + }); + issue .command('close <number>') .description('Close an issue')