mime-todo-cli/bin/bugzilla.ts
Tiara Rodney 932d4ad420
init
2026-03-15 03:02:41 +01:00

223 lines
7 KiB
JavaScript

#!/usr/bin/env node
// Standalone Bugzilla CLI — interact with Bugzilla REST API directly
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import { BugzillaClient } from "../lib/bugzilla/client"
import { loadConfig } from "../lib/bugzilla/config"
function getClient() {
const config = loadConfig()
return new BugzillaClient(config)
}
yargs(hideBin(process.argv))
.scriptName("bugzilla")
.usage("$0 <command> [options]")
.command(
"get <id>",
"Get a bug by ID",
(y) => y.positional("id", { type: "number", demandOption: true }),
async (argv) => {
const client = getClient()
const bug = await client.getBug(argv.id as number)
console.log(JSON.stringify(bug, null, 2))
}
)
.command(
"search",
"Search for bugs",
(y) =>
y
.option("product", { type: "string", alias: "p" })
.option("component", { type: "string", alias: "c" })
.option("status", { type: "string", alias: "s" })
.option("summary", { type: "string" })
.option("limit", { type: "number", default: 50 }),
async (argv) => {
const client = getClient()
const config = loadConfig()
const bugs = await client.searchBugs({
product: argv.product ?? config.product,
component: argv.component ?? config.component,
status: argv.status,
summary: argv.summary,
limit: argv.limit,
})
for (const bug of bugs) {
console.log(`#${bug.id} [${bug.severity}] (${bug.status}) ${bug.summary}`)
}
console.log(`\n${bugs.length} bug(s) found`)
}
)
.command(
"create",
"Create a new bug",
(y) =>
y
.option("summary", { type: "string", alias: "s", demandOption: true })
.option("description", { type: "string", alias: "d" })
.option("priority", { type: "string", default: "Normal" })
.option("severity", { type: "string", default: "normal" })
.option("product", { type: "string", alias: "p" })
.option("component", { type: "string", alias: "c" }),
async (argv) => {
const client = getClient()
const config = loadConfig()
const id = await client.createBug({
product: argv.product ?? config.product,
component: argv.component ?? config.component,
summary: argv.summary,
description: argv.description,
priority: argv.priority,
severity: argv.severity,
})
console.log(`Created bug #${id}`)
}
)
.command(
"update <id>",
"Update a bug",
(y) =>
y
.positional("id", { type: "number", demandOption: true })
.option("summary", { type: "string", alias: "s" })
.option("status", { type: "string" })
.option("resolution", { type: "string" })
.option("priority", { type: "string" }),
async (argv) => {
const client = getClient()
const payload: Record<string, any> = {}
if (argv.summary) payload.summary = argv.summary
if (argv.status) payload.status = argv.status
if (argv.resolution) payload.resolution = argv.resolution
if (argv.priority) payload.priority = argv.priority
await client.updateBug(argv.id as number, payload)
console.log(`Updated bug #${argv.id}`)
}
)
.command(
"comments <id>",
"List comments on a bug",
(y) => y.positional("id", { type: "number", demandOption: true }),
async (argv) => {
const client = getClient()
const comments = await client.getComments(argv.id as number)
for (const c of comments) {
console.log(`--- Comment #${c.count} by ${c.creator} (${c.time}) ---`)
console.log(c.text)
console.log()
}
}
)
.command(
"comment <id>",
"Add a comment to a bug",
(y) =>
y
.positional("id", { type: "number", demandOption: true })
.option("text", { type: "string", alias: "t", demandOption: true }),
async (argv) => {
const client = getClient()
await client.addComment(argv.id as number, argv.text as string)
console.log(`Comment added to bug #${argv.id}`)
}
)
.command(
"products",
"List accessible products",
() => {},
async () => {
const client = getClient()
const products = await client.getAccessibleProducts()
for (const p of products) {
const compCount = p.components?.length ?? 0
console.log(`#${p.id} ${p.name} (${compCount} components) — ${p.description}`)
}
console.log(`\n${products.length} product(s)`)
}
)
.command(
"product <name>",
"Get product details and its components",
(y) => y.positional("name", { type: "string", demandOption: true }),
async (argv) => {
const client = getClient()
const product = await client.getProduct(argv.name as string)
console.log(`Product: ${product.name} (#${product.id})`)
console.log(`Description: ${product.description}`)
console.log(`Active: ${product.is_active}`)
console.log(`\nComponents:`)
for (const c of product.components ?? []) {
const status = c.is_active ? "active" : "inactive"
console.log(` ${c.name} (${status}) — ${c.description}`)
}
}
)
.command(
"create-product",
"Create a new product",
(y) =>
y
.option("name", { type: "string", alias: "n", demandOption: true })
.option("description", { type: "string", alias: "d", demandOption: true })
.option("version", { type: "string", default: "unspecified" }),
async (argv) => {
const client = getClient()
const id = await client.createProduct({
name: argv.name,
description: argv.description,
version: argv.version,
})
console.log(`Created product #${id}: ${argv.name}`)
}
)
.command(
"components <product>",
"List components for a product",
(y) => y.positional("product", { type: "string", demandOption: true }),
async (argv) => {
const client = getClient()
const components = await client.getComponents(argv.product as string)
for (const c of components) {
const status = c.is_active ? "active" : "inactive"
console.log(`#${c.id} ${c.name} (${status}) — ${c.description}`)
}
console.log(`\n${components.length} component(s)`)
}
)
.command(
"create-component",
"Create a new component",
(y) =>
y
.option("product", { type: "string", alias: "p", demandOption: true })
.option("name", { type: "string", alias: "n", demandOption: true })
.option("description", { type: "string", alias: "d", demandOption: true })
.option("assignee", { type: "string", alias: "a", demandOption: true }),
async (argv) => {
const client = getClient()
const id = await client.createComponent({
product: argv.product,
name: argv.name,
description: argv.description,
default_assignee: argv.assignee,
})
console.log(`Created component #${id}: ${argv.name} (in ${argv.product})`)
}
)
.demandCommand(1, "Please specify a command")
.strict()
.help()
.parse()