1use crate::jira_doc_std_field;
2use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
3use regex::Regex;
4use std::error::Error;
5
6#[derive(Parser, Debug)]
9#[command(author, version, about, long_about = None)]
10pub struct JirustCliArgs {
11 #[clap(subcommand)]
13 pub subcmd: Commands,
14}
15
16#[derive(Subcommand, Debug)]
19pub enum Commands {
20 Config(ConfigArgs),
22 Issue(IssueArgs),
24 Link(LinkIssueArgs),
26 Project(ProjectArgs),
28 Transition(TransitionArgs),
30 Version(VersionArgs),
32}
33
34#[derive(Args, Debug)]
39pub struct PaginationArgs {
40 #[clap(
42 long,
43 short = 'l',
44 value_name = "page_size",
45 help = "page size for lists"
46 )]
47 pub page_size: Option<i32>,
48 #[clap(
50 long,
51 short = 's',
52 value_name = "page_offset",
53 help = "page offset for list"
54 )]
55 pub page_offset: Option<i64>,
56}
57
58#[derive(ValueEnum, Debug, Clone, Copy)]
64#[value(rename_all = "kebab-case")]
65pub enum OutputValues {
66 #[value(name = "table", help = "Print output in table format")]
68 Table,
69 #[value(name = "json", help = "Print output in json format")]
71 Json,
72}
73
74#[derive(Args, Debug)]
78pub struct OutputArgs {
79 #[clap(long, short = 'o', value_name = "table|json", help = "Output format")]
81 pub output: Option<OutputValues>,
82}
83
84#[derive(Args, Debug)]
88pub struct ConfigArgs {
89 #[arg(
91 value_name = "auth|jira|setup|show",
92 help_heading = "Configuration management"
93 )]
94 pub cfg_act: ConfigActionValues,
95}
96
97#[derive(ValueEnum, Debug, Clone, Copy)]
105#[value(rename_all = "kebab-case")]
106pub enum ConfigActionValues {
107 #[value(name = "auth", help = "Set Jira API authentication (username, apikey)")]
109 Auth,
110 #[value(name = "jira", help = "Set Jira API base URL")]
112 Jira,
113 #[value(
115 name = "setup",
116 help = "Setup Jira API configuration (authentication data, jira base URL, etc.)"
117 )]
118 Setup,
119 #[value(name = "show", help = "Show current configuration")]
121 Show,
122}
123
124#[derive(Args, Debug)]
142pub struct VersionArgs {
143 #[arg(
145 value_name = "archive|create|delete|list|release|update",
146 help_heading = "Jira Project version management"
147 )]
148 pub version_act: VersionActionValues,
149 #[clap(
151 long,
152 short = 'k',
153 value_name = "project_key",
154 required = true,
155 help = "Jira Project key"
156 )]
157 pub project_key: String,
158 #[clap(long, short = 'i', value_name = "project_id", help = "Jira Project ID")]
160 pub project_id: Option<i64>,
161 #[clap(
163 long,
164 short = 'v',
165 value_name = "version_id",
166 help = "Jira Project version ID"
167 )]
168 pub version_id: Option<String>,
169 #[clap(
171 long,
172 short = 'n',
173 value_name = "version_name",
174 help = "Jira Project version name"
175 )]
176 pub version_name: Option<String>,
177 #[clap(
179 long,
180 short = 'd',
181 value_name = "version_description",
182 help = "Jira Project version description"
183 )]
184 pub version_description: Option<String>,
185 #[clap(
187 long,
188 value_name = "version_start_date",
189 help = "Jira Project version start date"
190 )]
191 pub version_start_date: Option<String>,
192 #[clap(
194 long,
195 value_name = "version_release_date",
196 help = "Jira Project version release date"
197 )]
198 pub version_release_date: Option<String>,
199 #[clap(
201 long,
202 short = 'a',
203 value_name = "version_archived",
204 help = "Jira Project version archived"
205 )]
206 pub version_archived: Option<bool>,
207 #[clap(
209 long,
210 short = 'm',
211 action = ArgAction::SetTrue,
212 value_name = "version_released",
213 help = "Jira Project version released"
214 )]
215 pub version_released: Option<bool>,
216 #[clap(
218 long,
219 short = 'c',
220 value_name = "changelog_file",
221 help = "changelog file path to be used for automatic description generation (if set the script detects automatically the first tagged block in the changelog and use it as description)"
222 )]
223 pub changelog_file: Option<String>,
224 #[clap(
226 long,
227 short = 'r',
228 action = ArgAction::SetTrue,
229 value_name = "resolve_issues",
230 help = "if changelog is set and this flag is set, the script will transition all issues in the changelog of the current version release to the \"resolved\" status setting the version as \"fixVersion\""
231 )]
232 pub transition_issues: Option<bool>,
233 #[clap(
235 long,
236 short = 'u',
237 value_name = "transition_assignee",
238 help = "if changelog is set and the resolve_issues flag is set, the script will assigned all the resolved issue to the user specified in this field (if not set the assignee will not be changed)"
239 )]
240 pub transition_assignee: Option<String>,
241 #[clap(flatten)]
243 pub pagination: PaginationArgs,
244 #[clap(flatten)]
246 pub output: OutputArgs,
247}
248
249#[derive(ValueEnum, Debug, Clone, Copy)]
259#[value(rename_all = "kebab-case")]
260pub enum VersionActionValues {
261 #[value(name = "archive", help = "Archive a Jira Project version")]
263 Archive,
264 #[value(name = "create", help = "Create a Jira Project version")]
266 Create,
267 #[value(name = "delete", help = "Delete a Jira Project version")]
269 Delete,
270 #[value(name = "list", help = "List Jira Project versions")]
272 List,
273 #[value(name = "release", help = "Release a Jira Project version")]
275 Release,
276 #[value(name = "update", help = "Update a Jira Project version")]
278 Update,
279}
280
281#[derive(Args, Debug)]
289pub struct ProjectArgs {
290 #[arg(
292 value_name = "get-issue-types|get-issue-type-fields|list",
293 help_heading = "Jira Project management",
294 required = true
295 )]
296 pub project_act: ProjectActionValues,
297 #[clap(
299 long,
300 short = 'k',
301 value_name = "project_key",
302 help = "Jira Project key",
303 required = true
304 )]
305 pub project_key: Option<String>,
306 #[clap(
308 long,
309 short = 'i',
310 value_name = "project_issue_type",
311 help = "Jira Project issue type ID"
312 )]
313 pub project_issue_type: Option<String>,
314 #[clap(flatten)]
316 pub pagination: PaginationArgs,
317 #[clap(flatten)]
319 pub output: OutputArgs,
320}
321
322#[derive(ValueEnum, Debug, Clone, Copy)]
328#[value(rename_all = "kebab-case")]
329pub enum ProjectActionValues {
330 #[value(
332 name = "get-issue-types",
333 help = "Get Jira Project issue types by Jira project key"
334 )]
335 GetIssueTypes,
336 #[value(
338 name = "get-issue-type-fields",
339 help = "Get Jira Project issue type fields by Jira project key and issue type ID"
340 )]
341 GetIssueTypeFields,
342 #[value(name = "list", help = "List Jira Projects")]
344 List,
345}
346
347#[derive(Args, Debug)]
358pub struct IssueArgs {
359 #[arg(
361 value_name = "assign|create|delete|get|transition|update",
362 help_heading = "Jira Project issue management",
363 required = true
364 )]
365 pub issue_act: IssueActionValues,
366 #[clap(
368 long,
369 short = 'p',
370 value_name = "project_key",
371 help = "Jira Project key",
372 required = true
373 )]
374 pub project_key: String,
375 #[clap(
377 long,
378 short = 'i',
379 value_name = "issue_key",
380 help = "Jira Project issue key"
381 )]
382 pub issue_key: Option<String>,
383 #[clap(long,
385 short = 'f',
386 value_name = "issue_fields",
387 value_parser = parse_key_val::<String, String>,
388 help = "Jira Project issue fields (field_name=value)")]
389 pub issue_fields: Option<Vec<(String, String)>>,
390 #[clap(
392 long,
393 short = 't',
394 value_name = "transition_to",
395 help = "Jira Project issue transition to"
396 )]
397 pub transition_to: Option<String>,
398 #[clap(
400 long,
401 short = 'a',
402 value_name = "assignee",
403 help = "Jira Project issue assignee"
404 )]
405 pub assignee: Option<String>,
406 #[clap(flatten)]
408 pub pagination: PaginationArgs,
409 #[clap(flatten)]
411 pub output: OutputArgs,
412}
413
414#[derive(ValueEnum, Debug, Clone, Copy)]
423#[value(rename_all = "kebab-case")]
424pub enum IssueActionValues {
425 #[value(name = "assign", help = "Assign a Jira Project issue")]
427 Assign,
428 #[value(name = "create", help = "Create a Jira Project issue")]
430 Create,
431 #[value(name = "delete", help = "Delete a Jira Project issue")]
433 Delete,
434 #[value(name = "get", help = "Get a specific Jira Project issue")]
436 Get,
437 #[value(name = "transition", help = "Transition a Jira Project issue")]
439 Transition,
440 #[value(name = "update", help = "Update a Jira Project issue")]
442 Update,
443}
444
445#[derive(Args, Debug)]
454pub struct LinkIssueArgs {
455 #[arg(
457 value_name = "create",
458 help_heading = "Jira issues links management",
459 required = true
460 )]
461 pub link_act: LinkIssueActionValues,
462 #[clap(
464 long,
465 short = 'k',
466 value_name = "project_key",
467 help = "Jira Project key"
468 )]
469 pub project_key: Option<String>,
470 #[clap(
472 long,
473 short = 'i',
474 value_name = "issue_key",
475 help = "Jira issue link origin key",
476 required = true
477 )]
478 pub origin_issue_key: String,
479 #[clap(
481 long,
482 short = 'd',
483 value_name = "issue_key",
484 help = "Jira issue link destination key"
485 )]
486 pub destination_issue_key: Option<String>,
487 #[clap(
489 long,
490 short = 't',
491 value_name = "link_type",
492 help = "Jira issue link type",
493 required = true
494 )]
495 pub link_type: String,
496 #[clap(
498 long,
499 short = 'c',
500 value_name = "changelog_file",
501 help = "changelog file path to be used for automatic issues' links generation (if set the script detects automatically the first tagged block in the changelog and use it as description)"
502 )]
503 pub changelog_file: Option<String>,
504}
505
506#[derive(ValueEnum, Debug, Clone, Copy)]
510#[value(rename_all = "kebab-case")]
511pub enum LinkIssueActionValues {
512 #[value(name = "create", help = "Create a Jira link between issues")]
514 Create,
515}
516
517#[derive(Args, Debug)]
523pub struct TransitionArgs {
524 #[arg(value_name = "list", help_heading = "Jira issue transition list")]
526 pub transition_act: TransitionActionValues,
527 #[clap(
529 long,
530 short = 'i',
531 value_name = "issue_key",
532 help = "Jira Project issue key",
533 required = true
534 )]
535 pub issue_key: String,
536 #[clap(flatten)]
538 pub output: OutputArgs,
539}
540
541#[derive(ValueEnum, Debug, Clone, Copy)]
545#[value(rename_all = "kebab-case")]
546pub enum TransitionActionValues {
547 #[value(name = "list", help = "List Jira issue available transitions")]
549 List,
550}
551
552fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
555where
556 T: std::str::FromStr,
557 T::Err: Error + Send + Sync + 'static,
558 U: std::str::FromStr,
559 U::Err: Error + Send + Sync + 'static,
560{
561 let pos = s
562 .find('=')
563 .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
564 Ok((
565 s[..pos].parse()?,
566 manage_jira_document_field(s[pos + 1..].to_string()).parse()?,
567 ))
568}
569
570fn manage_jira_document_field(value: String) -> String {
573 let re = Regex::new(r"^jira_doc_field\[(.+)\]$").unwrap();
574 let captures = re.captures(&value);
575 let val = if Option::is_some(&captures) {
576 jira_doc_std_field![captures.unwrap().get(1).unwrap().as_str()].to_string()
577 } else {
578 value.to_string()
579 };
580 val
581}