codeberg-cli 0.5.5

CLI Tool for codeberg similar to gh and glab
Documentation
use super::display_pull_request;
use crate::actions::text_manipulation::select_prompt_for;
use crate::render::json::JsonToStdout;
use crate::render::option::option_display;
use crate::render::spinner::spin_until_ready;
use crate::render::ui::fuzzy_select_with_key;
use crate::types::context::BergContext;
use crate::types::git::OwnerRepo;
use crate::{actions::GlobalArgs, types::output::OutputMode};
use clap::Parser;
use forgejo_api::structs::{CreateIssueCommentOption, PullRequest, RepoListPullRequestsQuery};
use miette::{Context, IntoDiagnostic};

/// Add comment to selected pull request
#[derive(Parser, Debug)]
pub struct CommentPullRequestArgs {}

impl CommentPullRequestArgs {
    pub async fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
        let ctx = BergContext::new(self, global_args).await?;

        let OwnerRepo { owner, repo } = ctx.owner_repo()?;
        let pull_request = select_pull_request(&ctx).await?;
        let pull_request_id = pull_request
            .id
            .context("Selected milestone doesn't have an ID")?;

        let options = create_options(&ctx, &pull_request).await?;

        let comment = ctx
            .client
            .issue_create_comment(owner.as_str(), repo.as_str(), pull_request_id, options)
            .await
            .into_diagnostic()?;

        match ctx.global_args.output_mode {
            OutputMode::Pretty => {
                tracing::debug!("{comment:?}");
            }
            OutputMode::Json => comment.print_json()?,
        }

        Ok(())
    }
}

async fn create_options(
    ctx: &BergContext<CommentPullRequestArgs>,
    pull_request: &PullRequest,
) -> miette::Result<CreateIssueCommentOption> {
    let body = ctx.editor_for(
        "a comment",
        format!(
            "Write a comment for pull_request \"{}\"",
            option_display(&pull_request.title)
        )
        .as_str(),
    )?;

    Ok(CreateIssueCommentOption {
        body,
        updated_at: None,
    })
}

async fn select_pull_request(
    ctx: &BergContext<CommentPullRequestArgs>,
) -> miette::Result<PullRequest> {
    let OwnerRepo { owner, repo } = ctx.owner_repo()?;
    let (_, pull_requests_list) = spin_until_ready(
        ctx.client
            .repo_list_pull_requests(
                owner.as_str(),
                repo.as_str(),
                RepoListPullRequestsQuery::default(),
            )
            .send(),
    )
    .await
    .into_diagnostic()?;

    fuzzy_select_with_key(
        &pull_requests_list,
        select_prompt_for("pull request"),
        display_pull_request,
    )
    .cloned()
}