//! Commenting on an agent's config PRs as the core forge user — how a hive //! reports a merged config commit it refused to deploy back onto the PR that //! merged it. Finding that PR only reads, so it uses [`reader_token`]. use anyhow::{Context, Result}; use super::{CONFIG_ORG, api, bounded, core_token, reader_token}; /// Full `owner/name` path of an agent's config repo on the forge. pub fn config_repo(agent: &str) -> String { format!("{CONFIG_ORG}/{agent}") } /// The number of the merged PR that put commit `sha` on `repo`'s base branch. /// /// # Errors /// No read token, malformed repo, no such PR, or transport/API failure. pub async fn merged_pr_for_commit(repo: &str, sha: &str) -> Result { let reader = reader_token().await.context("no forge read token")?; let (owner, name) = repo .split_once('/') .with_context(|| format!("forge repo `{repo}` is not owner/name"))?; let pull = bounded( "GET pull request of commit", api(reader.value())?.repo_get_commit_pull_request(owner, name, sha), ) .await? .context("GET pull request of commit")?; pull.number .and_then(|n| u64::try_from(n).ok()) .with_context(|| format!("pull request of {sha} in {repo} carries no number")) } /// Post a comment to PR (= issue) `pr` on `repo` as the core forge user. /// PRs are issues in Forgejo, so the PR number is the issue index. /// /// # Errors /// Absent core token, malformed repo, or transport/API failure. pub async fn post_pr_comment(repo: &str, pr: u64, body: &str) -> Result<()> { let token = core_token().context("forge core token absent")?; let (owner, name) = repo .split_once('/') .with_context(|| format!("forge repo `{repo}` is not owner/name"))?; let index = i64::try_from(pr).with_context(|| format!("PR index {pr} overflows i64"))?; bounded( "post PR comment", api(&token)?.issue_create_comment( owner, name, index, forgejo_api::structs::CreateIssueCommentOption { body: body.to_owned(), updated_at: None, }, ), ) .await? .context("post PR comment")?; Ok(()) }