Watch
0
0
Fork
You've already forked hyperhive
0

hive-forge: review-reply adds the comment to the answered comment's review, as the web UI does

This commit is contained in:
damocles 2026-11-05 07:52:03 +01:00 • committed by mara
commit 3ff4dc7be0

View file

@ -1,12 +1,12 @@
//! `pr review-reply <number> <comment-id>` - answer an inline review comment.
//!
//! Forgejo's API has no reply endpoint, so the reply is a one-comment
//! `COMMENT` review anchored at the same path and line as the comment it
//! answers; the forge shows comments with one anchor as one conversation.
//! Forgejo's API has no reply endpoint. The web UI stores a reply in the same
//! review as the comment it answers, so this adds a comment to that review at
//! the same path and line. A new review at the same anchor is not enough: the
//! forge shows it as a conversation of its own.
use anyhow::{Result, bail};
use clap::Args as ClapArgs;
use forgejo_api::structs::{CreatePullReviewComment, CreatePullReviewOptions};
use serde_json::{Value, json};
use crate::body;
@ -66,8 +66,9 @@ fn anchor_of(comment: &Value) -> Result<Anchor> {
})
}
/// Find the inline comment with `id` among the PR's reviews.
fn find_comment(client: &Client, number: u64, id: i64) -> Result<Value> {
/// Find the inline comment with `id` among the PR's reviews, with the id of the
/// review it belongs to.
fn find_comment(client: &Client, number: u64, id: i64) -> Result<(i64, Value)> {
let (owner, name) = client.owner_repo()?;
let reviews = all_pages(|page, size| {
let (_, batch) = client
@ -86,7 +87,7 @@ fn find_comment(client: &Client, number: u64, id: i64) -> Result<Value> {
.into_iter()
.find(|c| c.get("id").and_then(Value::as_i64) == Some(id));
if let Some(c) = found {
return Ok(c);
return Ok((review_id, c));
}
}
bail!("no inline review comment #{id} on PR #{number}; `pr reviews {number}` lists their ids")
@ -102,34 +103,28 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
args.body_file.as_deref(),
"pr review-reply",
)?;
let target = find_comment(client, args.number, args.comment_id)?;
let (review_id, target) = find_comment(client, args.number, args.comment_id)?;
let anchor = anchor_of(&target)?;
let (owner, name) = client.owner_repo()?;
let review = client
let comment = client
.api()
.repo_create_pull_review(
.repo_create_pull_review_comment(
owner,
name,
index(args.number)?,
CreatePullReviewOptions {
body: Some(String::new()),
comments: Some(vec![CreatePullReviewComment {
body: Some(text),
extra_lines_count: Some(anchor.extra_lines),
new_position: Some(anchor.line),
old_position: Some(0),
path: Some(anchor.path),
}]),
commit_id: target
.get("commit_id")
.and_then(Value::as_str)
.map(str::to_owned),
event: Some("COMMENT".to_owned()),
},
review_id,
json!({
"body": text,
"extra_lines_count": anchor.extra_lines,
"new_position": anchor.line,
"old_position": 0,
"path": anchor.path,
}),
)
.send()?;
print_json(&json!({
"review": review.id,
"comment": comment.id,
"review": review_id,
"in_reply_to": args.comment_id,
"at": comment_location(&target),
}))