bzr 0.3.0

A CLI for Bugzilla, inspired by gh
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
use clap::Subcommand;

#[derive(Subcommand)]
#[expect(
    clippy::doc_markdown,
    reason = "doc examples are literal shell commands; wrapping URLs in <> or identifiers in backticks would degrade copy-paste UX"
)]
pub enum BugAction {
    /// List bugs that match the given filters.
    ///
    /// Filter flags (`--product`, `--component`, `--status`,
    /// `--assignee`, `--creator`, `--priority`, `--severity`) are
    /// repeatable for OR semantics within a category and AND across
    /// categories. Prefix any filter value with `!` to invert it
    /// (e.g. `--status '!CLOSED'`).
    ///
    /// `--limit` defaults to 50; raise it for broader scans, but very
    /// large values may exceed the server's max-results setting and
    /// return a truncated list. Use `--fields` / `--exclude-fields` to
    /// trim the response payload.
    ///
    /// Examples:
    ///
    ///   bzr bug list --product Firefox --status NEW --limit 25
    ///   bzr bug list --assignee me@example.com --status '!CLOSED'
    ///   bzr bug list --id 100,101,102
    ///
    /// See bzr-bug-search(1) for free-text search, bzr-bug-my(1) for
    /// caller-relative views, and bzr-query(1) for saving a filter
    /// combination by name.
    #[command(verbatim_doc_comment)]
    List {
        /// Filter by product (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        product: Vec<String>,
        /// Filter by component (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        component: Vec<String>,
        /// Filter by status (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        status: Vec<String>,
        /// Filter by assignee (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        assignee: Vec<String>,
        /// Filter by creator (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        creator: Vec<String>,
        /// Filter by priority (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        priority: Vec<String>,
        /// Filter by severity (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        severity: Vec<String>,
        /// Filter by bug IDs
        #[arg(long)]
        id: Vec<u64>,
        /// Filter by alias
        #[arg(long)]
        alias: Option<String>,
        /// Max number of results
        #[arg(long, default_value = "50")]
        limit: u32,
        /// Only return these fields (comma-separated)
        #[arg(long)]
        fields: Option<String>,
        /// Exclude these fields (comma-separated)
        #[arg(long)]
        exclude_fields: Option<String>,
    },
    /// View a single bug by ID or alias.
    ///
    /// Prints the bug's full record (summary, status, assignee,
    /// priority, CC list, depends-on, blocks, and the most recent
    /// comments) as a formatted table or JSON. Use `--fields` to
    /// fetch only specific fields (faster on large bugs);
    /// `--exclude-fields` is the inverse.
    ///
    /// Examples:
    ///
    ///   bzr bug view 12345
    ///   bzr bug view 12345 --json | jq .summary
    ///   bzr bug view my-alias --fields id,summary,status
    ///
    /// See bzr-bug-history(1) for the change log and
    /// bzr-comment-list(1) for the full comment thread.
    #[command(verbatim_doc_comment)]
    View {
        /// Bug ID or alias
        id: String,
        /// Only return these fields (comma-separated)
        #[arg(long)]
        fields: Option<String>,
        /// Exclude these fields (comma-separated)
        #[arg(long)]
        exclude_fields: Option<String>,
    },
    /// Search bugs by free-text query or by parsing a Bugzilla URL.
    ///
    /// The positional `query` argument is a free-text search across
    /// summary, description, and comments. Mutually exclusive with
    /// `--from-url`, which parses a Bugzilla `buglist.cgi` URL and
    /// reproduces the same filter set against the configured server.
    /// Unrecognized URL parameters are passed through verbatim.
    ///
    /// `--save-as` (only valid with `--from-url`) saves the parsed
    /// query for reuse; if no name is given it defaults to the URL's
    /// `known_name` parameter when present, otherwise an
    /// auto-generated name. Saved queries are managed with
    /// `bzr query`.
    ///
    /// Examples:
    ///
    ///   bzr bug search "kernel panic" --limit 10
    ///   bzr bug search --from-url 'https://bz/buglist.cgi?product=Firefox'
    ///   bzr bug search --from-url '...' --save-as firefox-bugs
    ///
    /// See bzr-bug-list(1) for filter-flag based listing and
    /// bzr-query(1) for managing saved queries directly.
    #[command(verbatim_doc_comment)]
    Search {
        /// Free-text search query (mutually exclusive with `--from-url`).
        ///
        /// Searches across summary, description, and comments using
        /// the Bugzilla server's quicksearch syntax. Use
        /// `--from-url` to instead replay a search composed in the
        /// Bugzilla web UI.
        #[arg(conflicts_with = "from_url")]
        query: Option<String>,
        /// Execute a search from a Bugzilla `buglist.cgi` URL.
        ///
        /// Parses the URL's query parameters into known filters
        /// where possible; unrecognized parameters are passed
        /// through to the API verbatim. Pair with `--save-as` to
        /// persist the parsed query as a named entry usable by
        /// `bzr query run`.
        #[arg(long)]
        from_url: Option<String>,
        /// Save the parsed `--from-url` query for future reuse.
        ///
        /// Only valid with `--from-url`. If a name is provided,
        /// the query is stored under that name. If `--save-as` is
        /// given without a value, the URL's `known_name` query
        /// parameter is used as the name; if neither is present,
        /// the command fails with input-validation (exit code 7).
        /// Saved queries are managed via `bzr query`.
        #[arg(long, requires = "from_url", num_args = 0..=1, default_missing_value = "")]
        save_as: Option<String>,
        /// Max number of results (default: 50)
        #[arg(long)]
        limit: Option<u32>,
        /// Only return these fields (comma-separated)
        #[arg(long)]
        fields: Option<String>,
        /// Exclude these fields (comma-separated)
        #[arg(long)]
        exclude_fields: Option<String>,
    },
    /// Show the change history for a single bug.
    ///
    /// Prints every recorded change to the bug's fields (status,
    /// assignee, comments added, attachments, etc.) in chronological
    /// order, including the user who made each change. Use `--since`
    /// (ISO 8601 date or datetime) to limit the output to changes
    /// after a given point.
    ///
    /// Examples:
    ///
    ///   bzr bug history 12345
    ///   bzr bug history 12345 --since 2026-01-01
    ///   bzr bug history 12345 --since 2026-04-15T00:00:00Z --json
    ///
    /// See bzr-bug-view(1) for the current state of a bug.
    #[command(verbatim_doc_comment)]
    History {
        /// Bug ID
        id: u64,
        /// Only show changes after this date (ISO 8601)
        #[arg(long)]
        since: Option<String>,
    },
    /// Create a new bug under a product and component.
    ///
    /// `--summary` is always required. `--product` and `--component`
    /// are required unless a saved template (`--template`) supplies
    /// them; CLI flags override template values. Some Bugzilla
    /// installations also require `--op-sys` and `--rep-platform` --
    /// the API call fails with exit code 4 (Api) when the server
    /// demands a field that wasn't provided.
    ///
    /// On success, prints the new bug ID, alias (if assigned), and
    /// URL to stdout. With `--json`, the same fields are emitted as
    /// a JSON object suitable for piping into scripts.
    ///
    /// Examples:
    ///
    ///   bzr bug create --product Fedora --component kernel \
    ///     --summary "Boot failure on 6.x" \
    ///     --description "System hangs at initramfs"
    ///   bzr bug create --template security-bug \
    ///     --summary "XSS in login form"
    ///
    /// Exit codes: 0 on success, 4 on Bugzilla API error, 7 on
    /// input validation (e.g. empty summary), 9 on auth failure.
    ///
    /// See bzr-bug-clone(1) for cloning an existing bug,
    /// bzr-template(1) for managing templates, and bzr-field(1) for
    /// discovering valid `--priority`, `--severity`, and `--status`
    /// values.
    #[command(verbatim_doc_comment)]
    Create {
        /// Use a saved template for default field values.
        ///
        /// References a named template from `bzr template list`.
        /// When set, fields stored in the template (product,
        /// component, version, priority, severity, assignee,
        /// op-sys, rep-platform, description) are used as defaults
        /// for this `create` invocation; CLI flags override
        /// template values.
        #[arg(long)]
        template: Option<String>,
        /// Product name (required unless supplied by `--template`).
        ///
        /// Required unless the chosen template provides a product.
        /// When both are set, this CLI value wins.
        #[arg(long)]
        product: Option<String>,
        /// Component name (required unless supplied by `--template`).
        ///
        /// Required unless the chosen template provides a
        /// component. When both are set, this CLI value wins. The
        /// component must exist on the chosen product -- discover
        /// valid names via `bzr product view <product>`.
        #[arg(long)]
        component: Option<String>,
        /// Bug summary
        #[arg(long)]
        summary: String,
        /// Version
        #[arg(long)]
        version: Option<String>,
        /// Bug description
        #[arg(long)]
        description: Option<String>,
        /// Priority
        #[arg(long)]
        priority: Option<String>,
        /// Severity
        #[arg(long)]
        severity: Option<String>,
        /// Assignee
        #[arg(long)]
        assignee: Option<String>,
        /// Operating system (required by some Bugzilla installations)
        #[arg(long)]
        op_sys: Option<String>,
        /// Hardware platform (required by some Bugzilla installations)
        #[arg(long)]
        rep_platform: Option<String>,
        /// Bug IDs that this bug blocks (comma-separated)
        #[arg(long, value_delimiter = ',')]
        blocks: Vec<u64>,
        /// Bug IDs that this bug depends on (comma-separated)
        #[arg(long, value_delimiter = ',')]
        depends_on: Vec<u64>,
    },
    /// Show bugs related to the authenticated user.
    ///
    /// Default view: bugs assigned to the caller. `--created`
    /// switches to bugs the caller filed; `--cc` switches to bugs
    /// the caller is CC'd on; `--all` shows all three categories
    /// at once (assigned, created, CC'd) and conflicts with the
    /// other two flags.
    ///
    /// `--limit` is per category, not total -- with `--all` and
    /// `--limit 50`, up to 150 rows may be returned. `--status`
    /// filters across whichever category is active, with the same
    /// repeatability and `!`-prefix semantics as `bzr bug list`.
    ///
    /// Examples:
    ///
    ///   bzr bug my
    ///   bzr bug my --created --status NEW
    ///   bzr bug my --all --limit 25
    ///
    /// See bzr-bug-list(1) for filter-driven listing without the
    /// caller-relative shortcuts and bzr-whoami(1) to confirm which
    /// account `my` resolves to.
    #[command(verbatim_doc_comment)]
    My {
        /// Show bugs I created (instead of assigned to me).
        ///
        /// Mutually exclusive with `--all`.
        #[arg(long)]
        created: bool,
        /// Show bugs I'm CC'd on (instead of assigned to me).
        ///
        /// Mutually exclusive with `--all`.
        #[arg(long)]
        cc: bool,
        /// Show all bugs related to me (assigned + created + CC'd).
        ///
        /// Mutually exclusive with `--created` and `--cc`. Output
        /// is grouped into the three categories; `--limit` applies
        /// per category, so the total can be up to 3x the limit.
        #[arg(long, conflicts_with_all = ["created", "cc"])]
        all: bool,
        /// Filter by status (repeatable for OR; prefix with ! to exclude)
        #[arg(long)]
        status: Vec<String>,
        /// Max results per category (assigned/created/cc).
        ///
        /// With `--all`, the limit applies independently to each of
        /// the three categories, so up to 3x this value may be
        /// returned. With `--created`, `--cc`, or no view flag,
        /// the limit applies to the single active category.
        #[arg(long, default_value = "50")]
        limit: u32,
        /// Only return these fields (comma-separated)
        #[arg(long)]
        fields: Option<String>,
        /// Exclude these fields (comma-separated)
        #[arg(long)]
        exclude_fields: Option<String>,
    },
    /// Clone an existing bug, optionally overriding fields.
    ///
    /// Copies the source bug's product, component, version, summary,
    /// description, priority, severity, assignee, op-sys,
    /// rep-platform, CC list, and keywords into a new bug. Pass any
    /// of the override flags (`--summary`, `--product`, ...) to
    /// change values for the clone; unspecified fields inherit from
    /// the source.
    ///
    /// By default the new bug gets a "Cloned from bug #N" comment;
    /// disable with `--no-comment`. Use `--add-depends-on` to link
    /// the new bug as a dependency of the source, or `--add-blocks`
    /// to make it block the source. `--no-cc` and `--no-keywords`
    /// skip copying those lists.
    ///
    /// Examples:
    ///
    ///   bzr bug clone 12345
    ///   bzr bug clone 12345 --summary "Backport to RHEL 9" \
    ///     --version "RHEL 9.4" --add-depends-on
    ///
    /// See bzr-bug-create(1) for filing a brand-new bug.
    #[command(verbatim_doc_comment)]
    Clone {
        /// Source bug ID or alias
        id: String,
        /// Override summary
        #[arg(long)]
        summary: Option<String>,
        /// Override product
        #[arg(long)]
        product: Option<String>,
        /// Override component
        #[arg(long)]
        component: Option<String>,
        /// Override version
        #[arg(long)]
        version: Option<String>,
        /// Override description
        #[arg(long)]
        description: Option<String>,
        /// Override priority
        #[arg(long)]
        priority: Option<String>,
        /// Override severity
        #[arg(long)]
        severity: Option<String>,
        /// Override assignee
        #[arg(long)]
        assignee: Option<String>,
        /// Override operating system
        #[arg(long)]
        op_sys: Option<String>,
        /// Override hardware platform
        #[arg(long)]
        rep_platform: Option<String>,
        /// Skip adding "Cloned from bug #N" comment
        #[arg(long)]
        no_comment: bool,
        /// Make the new bug depend on the source bug
        #[arg(long)]
        add_depends_on: bool,
        /// Make the new bug block the source bug
        #[arg(long)]
        add_blocks: bool,
        /// Don't copy the CC list from the source bug
        #[arg(long)]
        no_cc: bool,
        /// Don't copy keywords from the source bug
        #[arg(long)]
        no_keywords: bool,
    },
    /// Update one or more bugs with the same set of changes.
    ///
    /// Accepts one or more bug IDs as positional args. All field
    /// changes (`--status`, `--resolution`, `--assignee`,
    /// `--priority`, `--severity`, `--summary`, `--whiteboard`) are
    /// applied to every bug in the list. When closing a bug, both
    /// `--status` and `--resolution` typically need to be set
    /// together (e.g. `--status RESOLVED --resolution FIXED`).
    ///
    /// `--flag` accepts Bugzilla flag syntax: `name?`, `name+`,
    /// `name-`, `name?(user@example.com)`, or `name?,!` to clear.
    /// Repeatable.
    ///
    /// `--blocks-add` / `--blocks-remove` and `--depends-on-add` /
    /// `--depends-on-remove` are list-typed (comma-separated) and
    /// modify dependency relationships incrementally.
    ///
    /// On batch updates, partial failures (some bugs updated,
    /// others rejected) exit with code 11 (BatchPartialFailure) and
    /// the JSON output enumerates per-bug results.
    ///
    /// Examples:
    ///
    ///   bzr bug update 100 --status RESOLVED --resolution FIXED
    ///   bzr bug update 100 200 300 --priority high --flag review+
    ///   bzr bug update 100 --blocks-add 200,201 \
    ///     --depends-on-remove 99
    ///
    /// See bzr-bug-create(1) for new bugs, bzr-bug-clone(1) for
    /// cloning, and bzr-comment-add(1) for adding a comment as part
    /// of a status change.
    #[command(verbatim_doc_comment)]
    Update {
        /// Bug ID(s).
        ///
        /// One or more IDs. When more than one is supplied, the
        /// same field changes are applied to every bug; partial
        /// failures (some bugs updated, others rejected) exit with
        /// code 11 and the JSON output enumerates per-bug results.
        #[arg(required = true, num_args = 1..)]
        ids: Vec<u64>,
        /// New status (e.g. `NEW`, `ASSIGNED`, `RESOLVED`, `CLOSED`).
        ///
        /// When closing a bug, `--resolution` must usually be set
        /// in the same call. Discover valid values via
        /// `bzr field list status`.
        #[arg(long)]
        status: Option<String>,
        /// Resolution to set when closing a bug.
        ///
        /// Required by most workflows when `--status` transitions
        /// to a closed state (e.g. `RESOLVED`, `VERIFIED`).
        /// Discover valid values via `bzr field list resolution`.
        #[arg(long)]
        resolution: Option<String>,
        /// Reassign
        #[arg(long)]
        assignee: Option<String>,
        /// Priority
        #[arg(long)]
        priority: Option<String>,
        /// Severity
        #[arg(long)]
        severity: Option<String>,
        /// Summary
        #[arg(long)]
        summary: Option<String>,
        /// Whiteboard
        #[arg(long)]
        whiteboard: Option<String>,
        /// Set, request, or clear a flag using Bugzilla flag syntax.
        ///
        /// Repeatable. Accepted forms:
        /// `name+` (granted), `name-` (denied), `name?` (request),
        /// `name?(user@example.com)` (request a specific user), or
        /// `name?,!` to clear an existing flag.
        #[arg(long)]
        flag: Vec<String>,
        /// Add bug IDs to the blocks list (comma-separated).
        ///
        /// Combine with `--blocks-remove` for incremental edits.
        /// To replace the list entirely, the bug must be edited
        /// through the Bugzilla web UI.
        #[arg(long, value_delimiter = ',')]
        blocks_add: Vec<u64>,
        /// Remove bug IDs from the blocks list (comma-separated).
        #[arg(long, value_delimiter = ',')]
        blocks_remove: Vec<u64>,
        /// Add bug IDs to the depends-on list (comma-separated).
        ///
        /// Combine with `--depends-on-remove` for incremental
        /// edits.
        #[arg(long, value_delimiter = ',')]
        depends_on_add: Vec<u64>,
        /// Remove bug IDs from the depends-on list (comma-separated).
        #[arg(long, value_delimiter = ',')]
        depends_on_remove: Vec<u64>,
    },
}