223 lines
7 KiB
JavaScript
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.js"
|
|
import { loadConfig } from "../lib/bugzilla/config.js"
|
|
|
|
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()
|