From 7b372eb2dca0ea66035ad72c5022bf925b786bd1 Mon Sep 17 00:00:00 2001
From: codex-bot-andresmgsl <4+codex-bot-andresmgsl@users.noreply.github.com>
Date: Tue, 18 Aug 2026 00:45:00 +0000
Subject: [PATCH] Add labels to issue creation
---
src/cli.js | 4 +++
test/cli.test.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/src/cli.js b/src/cli.js
index 08a4099..8fe0bcd 100755
--- a/src/cli.js
+++ b/src/cli.js
@@ -686,6 +686,7 @@ issue
.option('-b, --body
', 'issue body (markdown)')
.option('--body-file ', 'read the issue body from a file')
.option('--assignee ', 'assign the issue to one or more users')
+ .option('--label ', 'apply one or more labels by name')
.action(async (options) => {
try {
const config = loadConfig();
@@ -697,6 +698,9 @@ issue
if (options.assignee && options.assignee.length) {
payload.assignees = options.assignee;
}
+ if (options.label && options.label.length) {
+ payload.labels = await resolveLabelIds(client, options.owner, options.repo, options.label);
+ }
const result = await client.createIssue(options.owner, options.repo, payload);
console.log(`Issue created: #${result.number} ${result.title}`);
console.log(`URL: ${result.html_url}`);
diff --git a/test/cli.test.js b/test/cli.test.js
index e08255c..bbe1b43 100644
--- a/test/cli.test.js
+++ b/test/cli.test.js
@@ -77,6 +77,75 @@ test('issue create --body-file reports unreadable files cleanly', () => {
}
});
+test('issue create resolves repeated label names into the initial create payload', async () => {
+ const cfg = path.join(os.tmpdir(), `stoke-cfg-${process.pid}-issue-labels.json`);
+ const requests = [];
+ const server = http.createServer((req, res) => {
+ let data = '';
+ req.on('data', (chunk) => { data += chunk; });
+ req.on('end', () => {
+ requests.push({ method: req.method, url: req.url, body: data });
+ res.writeHead(req.method === 'POST' ? 201 : 200, { 'Content-Type': 'application/json' });
+ if (req.method === 'GET') {
+ res.end(JSON.stringify([
+ { id: 107, name: 'ready', color: '0e8a16' },
+ { id: 100, name: 'enhancement', color: '84b6eb' },
+ ]));
+ } else {
+ res.end(JSON.stringify({ number: 27, title: 'Probe', html_url: 'https://forge.test/o/r/issues/27' }));
+ }
+ });
+ });
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
+ const { port } = server.address();
+ fs.writeFileSync(cfg, JSON.stringify({ url: `http://127.0.0.1:${port}`, token: 'tok' }));
+
+ try {
+ const res = await spawnAsync(
+ ['issue', 'create', '-o', 'o', '-r', 'r', '-t', 'Probe', '--label', 'ready', '--label', 'enhancement'],
+ { STOKE_CONFIG_FILE: cfg },
+ );
+ assert.equal(res.status, 0, res.stderr);
+ assert.deepEqual(requests.map(({ method }) => method), ['GET', 'POST']);
+ assert.match(requests[0].url, /^\/api\/v1\/repos\/o\/r\/labels\?/);
+ assert.equal(requests[1].url, '/api/v1/repos/o/r/issues');
+ assert.deepEqual(JSON.parse(requests[1].body), {
+ title: 'Probe',
+ body: '',
+ labels: [107, 100],
+ });
+ } finally {
+ await new Promise((resolve) => server.close(resolve));
+ fs.unlinkSync(cfg);
+ }
+});
+
+test('issue create rejects an unknown label before creating the issue', async () => {
+ const cfg = path.join(os.tmpdir(), `stoke-cfg-${process.pid}-unknown-issue-label.json`);
+ let createRequests = 0;
+ const server = http.createServer((req, res) => {
+ if (req.method === 'POST') createRequests += 1;
+ res.writeHead(200, { 'Content-Type': 'application/json' });
+ res.end(JSON.stringify([{ id: 107, name: 'ready', color: '0e8a16' }]));
+ });
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
+ const { port } = server.address();
+ fs.writeFileSync(cfg, JSON.stringify({ url: `http://127.0.0.1:${port}`, token: 'tok' }));
+
+ try {
+ const res = await spawnAsync(
+ ['issue', 'create', '-o', 'o', '-r', 'r', '-t', 'Probe', '--label', 'nonexistent'],
+ { STOKE_CONFIG_FILE: cfg },
+ );
+ assert.equal(res.status, 1);
+ assert.match(res.stderr, /Label not found in o\/r: nonexistent/);
+ assert.equal(createRequests, 0);
+ } finally {
+ await new Promise((resolve) => server.close(resolve));
+ fs.unlinkSync(cfg);
+ }
+});
+
test('pr show validates --number before any network call', () => {
const cfg = path.join(os.tmpdir(), `stoke-cfg-${process.pid}.json`);
fs.writeFileSync(cfg, JSON.stringify({ url: 'https://forge.test', token: 'tok' }));