Skip to content
Open
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
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,21 @@ linear-cli g branch LIN-123 # Show branch name
linear-cli g create LIN-123 # Create branch (no checkout)
linear-cli g commits # Commits with Linear trailers (jj)
linear-cli g pr LIN-123 --draft # Create GitHub PR
linear-cli g review-url LIN-123 # Linear review URL for the issue's PR
```

`review-url` reads the review URL from the issue's pull request notifications —
the one public place a pull request is paired with its review page — and falls
back to the pull requests linked to the issue's agent sessions. A pull request
that has produced neither (a brand-new PR with no CI result, comment, or review
activity yet) has nothing to resolve, and the command reports it instead of
guessing a URL.

Unresolved pull requests are part of the output, not a silent omission: `-o json`
returns `{"resolved": [...], "unresolved": [...]}`, and the plain-text form prints
the review URLs on stdout while naming any unresolved pull request on stderr. The
command fails only when it resolved nothing at all.

### Import / Export

Round-trip CSV and JSON import/export with field resolution for status, assignee, and labels.
Expand Down
21 changes: 20 additions & 1 deletion src/commands/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ use std::process::Command;

use crate::api::LinearClient;
use crate::display_options;
use crate::output::OutputOptions;
use crate::text::truncate;
use crate::vcs::{generate_branch_name, git_branch_exists, run_git_command, validate_branch_name};

mod review_url;

use review_url::show_review_url;

/// Version control system type
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
pub enum Vcs {
Expand Down Expand Up @@ -82,6 +87,19 @@ pub enum GitCommands {
#[arg(long, value_enum)]
vcs: Option<Vcs>,
},
/// Show the Linear review URL for an issue's pull request(s)
#[command(after_help = r#"EXAMPLES:
linear git review-url LIN-123 # Print the review URL(s)
linear g review-url LIN-123 -o json # Resolved and unresolved PRs

NOTE: The review URL is read from the issue's pull request notifications, falling
back to the pull requests linked to its agent sessions. A pull request that has
produced neither has no review URL to resolve; it is listed as unresolved rather
than dropped, on stderr in plain text and under "unresolved" in JSON."#)]
ReviewUrl {
/// Issue identifier (e.g., "LIN-123") or ID
issue: String,
},
/// Create a GitHub PR from a Linear issue
#[command(after_help = r#"EXAMPLES:
linear git pr LIN-123 # Create PR for issue
Expand Down Expand Up @@ -140,8 +158,9 @@ fn get_vcs(vcs_flag: Option<Vcs>) -> Result<Vcs> {
}
}

pub async fn handle(cmd: GitCommands) -> Result<()> {
pub async fn handle(cmd: GitCommands, output: &OutputOptions) -> Result<()> {
match cmd {
GitCommands::ReviewUrl { issue } => show_review_url(&issue, output).await,
GitCommands::Checkout { issue, branch, vcs } => {
let vcs = get_vcs(vcs)?;
checkout_issue(&issue, branch, vcs).await
Expand Down
Loading