fix(#2289): wire sync_agent failures to dashboard warning banner
sync_agent() now returns bool (false if any step fails). ensure_all() collects the names of agents whose sync failed and raises a single set_boot_warning with the aggregated list: forge: per-agent sync failed for: alice, bob (see journal for per-step detail) The static_kind() leak is already used for per-org boot warnings in the same file — the leak is bounded (one per hive-c0re boot, not per request) so reusing it here is appropriate. The rebuild call site in job_queue/exec.rs discards the bool return and keeps its existing tracing::warn! lines, which is the right separation: rebuilds are their own retry loop and don't need to post a persistent boot warning.
This commit is contained in:
parent
66c715842f
commit
06bc7e31c0
1 changed files with 30 additions and 2 deletions
|
|
@ -169,9 +169,15 @@ pub(crate) fn api(token: &str) -> Result<Forgejo> {
|
|||
///
|
||||
/// Called by both `ensure_all()` (startup sweep) and `rebuild_agent`
|
||||
/// (per-rebuild) so the two paths stay equivalent.
|
||||
pub async fn sync_agent(name: &str, core_token: Option<&str>) {
|
||||
/// Returns `true` if all steps succeeded, `false` if any step failed. The
|
||||
/// caller can use the return value to aggregate per-agent failures into a
|
||||
/// dashboard warning (see [`ensure_all`]); the rebuild path ignores it and
|
||||
/// relies on the journal `warn!` lines alone (a rebuild is its own retry).
|
||||
pub async fn sync_agent(name: &str, core_token: Option<&str>) -> bool {
|
||||
let mut ok = true;
|
||||
if let Err(e) = ensure_user_for(name).await {
|
||||
tracing::warn!(%name, error = ?e, "forge: ensure_user failed");
|
||||
ok = false;
|
||||
}
|
||||
// Align email to match the git user.email set by meta::render_flake
|
||||
// so commits link to the agent's Forgejo profile. Best-effort;
|
||||
|
|
@ -188,9 +194,11 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) {
|
|||
// was down.
|
||||
if let Err(e) = ensure_config_repo(name).await {
|
||||
tracing::warn!(%name, error = ?e, "forge: ensure_config_repo failed");
|
||||
ok = false;
|
||||
}
|
||||
if let Err(e) = push_config(name).await {
|
||||
tracing::warn!(%name, error = ?e, "forge: push_config failed");
|
||||
ok = false;
|
||||
}
|
||||
// Grant read-only access to core/meta and wire the `meta` remote
|
||||
// into the proposed repo so agents can fetch their deployment context.
|
||||
|
|
@ -198,9 +206,11 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) {
|
|||
&& let Err(e) = meta_read_access(name, token).await
|
||||
{
|
||||
tracing::warn!(%name, error = ?e, "forge: ensure_meta_read_access failed");
|
||||
ok = false;
|
||||
}
|
||||
if let Err(e) = ensure_meta_remote(name).await {
|
||||
tracing::warn!(%name, error = ?e, "forge: ensure_meta_remote failed");
|
||||
ok = false;
|
||||
}
|
||||
// Grant read-only access to internal/docs so the agent can clone
|
||||
// the operator-curated shared skills/runbook repo. Best-effort.
|
||||
|
|
@ -208,8 +218,10 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) {
|
|||
&& let Err(e) = shared_docs_access(name, token).await
|
||||
{
|
||||
tracing::warn!(%name, error = ?e, "forge: shared_docs_access failed");
|
||||
ok = false;
|
||||
}
|
||||
// internal/knowledge is public — no per-agent collaborator grant needed.
|
||||
ok
|
||||
}
|
||||
|
||||
/// The `core_token.is_some()` half of [`ensure_all`]: orgs, teams, the meta
|
||||
|
|
@ -346,11 +358,27 @@ pub async fn ensure_all() {
|
|||
);
|
||||
return;
|
||||
};
|
||||
let mut sync_failed: Vec<String> = Vec::new();
|
||||
for c in containers {
|
||||
let Some(name) = c.strip_prefix(crate::lifecycle::AGENT_PREFIX) else {
|
||||
continue;
|
||||
};
|
||||
sync_agent(name, core_token.as_deref()).await;
|
||||
if !sync_agent(name, core_token.as_deref()).await {
|
||||
sync_failed.push(name.to_owned());
|
||||
}
|
||||
}
|
||||
if !sync_failed.is_empty() {
|
||||
// Use static_kind to mint a `&'static str` key from the failed-agent
|
||||
// list (bounded leak: one per hive-c0re boot, not per request).
|
||||
let key = static_kind(format!("forge_sync_agent_{}", sync_failed.join("_")));
|
||||
crate::warnings::set_boot_warning(
|
||||
key,
|
||||
"warn",
|
||||
format!(
|
||||
"forge: per-agent sync failed for: {} (see journal for per-step detail)",
|
||||
sync_failed.join(", ")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue