Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"nullable": true,
"type": "string"
},
"fixPr": {
"$ref": "#/components/schemas/FixPr"
},
"id": {
"$ref": "#/components/schemas/BugId"
},
Expand Down Expand Up @@ -184,7 +187,8 @@
"jira",
"asana",
"github_issue",
"bug_fix_check"
"bug_fix_check",
"detail_fix_pr"
],
"type": "string"
},
Expand All @@ -209,6 +213,30 @@
},
"type": "object"
},
"FixPr": {
"properties": {
"prNumber": {
"type": "integer"
},
"state": {
"enum": [
"open",
"merged",
"closed"
],
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"prNumber",
"url",
"state"
],
"type": "object"
},
"IntroducedIn": {
"properties": {
"author": {
Expand Down
58 changes: 54 additions & 4 deletions src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use crate::utils::datetime::{format_date, format_datetime};
// Re-export generated types as the public API for this crate.
pub use super::generated::types::{
Bug, BugCounts, BugDismissalReason, BugId, BugReview, BugReviewId, BugReviewState,
CreatePublicBugReviewBody, CreateRuleInput, CreateRuleResponse, IntroducedIn, LinkedIssue,
LinkedIssueTracker, ListPublicBugsWorkflowRequestId, Org, OrgId, Repo, RepoId, Rule,
RuleCreationRequestId, RuleId, RuleListItem, RuleRequestResult, RuleRequestStatus, RuleStatus,
Scan, ScanInitiator, ScanType, WorkflowStatus,
CreatePublicBugReviewBody, CreateRuleInput, CreateRuleResponse, FixPr, IntroducedIn,
LinkedIssue, LinkedIssueTracker, ListPublicBugsWorkflowRequestId, Org, OrgId, Repo, RepoId,
Rule, RuleCreationRequestId, RuleId, RuleListItem, RuleRequestResult, RuleRequestStatus,
RuleStatus, Scan, ScanInitiator, ScanType, WorkflowStatus,
};

// Friendlier aliases for the generated response-wrapper names.
Expand Down Expand Up @@ -82,6 +82,15 @@ pub fn format_linked_issue(issue: &LinkedIssue) -> String {
}
}

/// Format the Detail-generated fix PR (number, state, and URL) for the
/// detail/show view, rendered as `#<number> (<state>) — <url>`.
pub fn format_fix_pr(fix_pr: &FixPr) -> String {
format!(
"#{} ({}) \u{2014} {}",
fix_pr.pr_number, fix_pr.state, fix_pr.url
)
}

// ── clap::ValueEnum ──────────────────────────────────────────────────

impl clap::ValueEnum for BugReviewState {
Expand Down Expand Up @@ -177,6 +186,12 @@ impl Formattable for Bug {
.join(", ");
pairs.push(("Linked Issues", formatted));
}
if let Some(fix_pr) = &self.fix_pr {
pairs.push((
"Fix PR",
format!("#{} ({})", fix_pr.pr_number, fix_pr.state),
));
}
(self.title.clone(), pairs)
}
}
Expand Down Expand Up @@ -452,6 +467,41 @@ mod tests {
);
}

// ── fix PR ───────────────────────────────────────────────────────

#[test]
fn bug_card_includes_fix_pr_when_present() {
let bug: Bug = serde_json::from_value(serde_json::json!({
"id": "bug_fixed", "title": "...", "summary": "...",
"createdAt": 1, "repoId": "repo_1", "linkedIssues": [],
"fixPr": { "prNumber": 42, "url": "https://x/pull/42", "state": "merged" }
}))
.expect("valid Bug JSON");
let (_, pairs) = bug.to_card();
let v = pairs.iter().find(|(k, _)| *k == "Fix PR").map(|(_, v)| v);
assert_eq!(v, Some(&"#42 (merged)".to_string()));
}

#[test]
fn bug_card_omits_fix_pr_when_absent() {
let (_, pairs) = sample_bug().to_card();
assert!(!pairs.iter().any(|(k, _)| *k == "Fix PR"));
}

#[test]
fn format_fix_pr_includes_number_state_and_url() {
let fix_pr: FixPr = serde_json::from_value(serde_json::json!({
"prNumber": 42,
"url": "https://github.com/acme/repo/pull/42",
"state": "open"
}))
.expect("valid FixPr JSON");
assert_eq!(
format_fix_pr(&fix_pr),
"#42 (open) \u{2014} https://github.com/acme/repo/pull/42"
);
}

// ── format_introduced_in ─────────────────────────────────────────

#[test]
Expand Down
8 changes: 6 additions & 2 deletions src/commands/bugs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use dialoguer::{Input, Select};

use crate::api::client::ApiClient;
use crate::api::types::{
dismissal_reason_label, format_introduced_in, format_linked_issue, review_state_label, Bug,
BugDismissalReason, BugId, BugReviewState, ListPublicBugsWorkflowRequestId, RepoId,
dismissal_reason_label, format_fix_pr, format_introduced_in, format_linked_issue,
review_state_label, Bug, BugDismissalReason, BugId, BugReviewState,
ListPublicBugsWorkflowRequestId, RepoId,
};
use crate::output::{output_list, SectionRenderer};
use crate::utils::datetime::{format_datetime, parse_time_spec};
Expand Down Expand Up @@ -333,6 +334,9 @@ fn render_bug_show(bug: &Bug) -> Result<()> {
for issue in &bug.linked_issues {
pairs.push(("Issue", format_linked_issue(issue)));
}
if let Some(fix_pr) = &bug.fix_pr {
pairs.push(("Fix PR", format_fix_pr(fix_pr)));
}
SectionRenderer::new()
.key_value("", &pairs)
.markdown("", &bug.summary)
Expand Down
Loading