forgejo-api 0.11.1 takes no caller-built client, so a request to a forge that accepts the connection and never answers waited forever. Every forge::api() call site now goes through forge::bounded, a 10s timeout that errors naming the operation. The PR-comment calls run inline in swarm_status::drain_swarm_events, the one task serving both swarm subscriptions, so a stalled forge stopped both. Refs #5066
60 lines
2.2 KiB
Rust
60 lines
2.2 KiB
Rust
//! 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<u64> {
|
|
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(())
|
|
}
|