From d836bde888e74b9ab01c9d8cfa1fa94b8b8304f4 Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 16 Oct 2026 11:41:48 +0200 Subject: [PATCH] forge: warn when the core avatar marker cannot be written The one-shot marker was written with create_dir_all(..).ok() and fs::write(..).ok(), so a failure was invisible and the avatar upload repeated on every start. Log the path and error; startup still succeeds. --- hive-c0re/src/forge/users.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/hive-c0re/src/forge/users.rs b/hive-c0re/src/forge/users.rs index 4f514e61..22e854bc 100644 --- a/hive-c0re/src/forge/users.rs +++ b/hive-c0re/src/forge/users.rs @@ -180,14 +180,21 @@ pub(super) async fn ensure_core_avatar(token: &str) -> Result<()> { ) .await? .context("set core avatar")?; - if let Some(parent) = marker.parent() { - std::fs::create_dir_all(parent).ok(); + if let Err(e) = write_marker(&marker) { + tracing::warn!(marker = %marker.display(), error = ?e, "forge: could not write the avatar marker; the upload repeats on the next start"); } - std::fs::write(marker, "").ok(); tracing::info!("forge: set core user avatar to hyperhive logo"); Ok(()) } +/// Create the one-shot marker file, and its directory if needed. +fn write_marker(marker: &Path) -> std::io::Result<()> { + if let Some(parent) = marker.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write(marker, "") +} + /// Outcome of probing whether the persisted core token still works /// against the *current* forge. Existence on disk is not validity: a /// token minted before a forge rebuild / re-provision is unknown to the @@ -301,10 +308,28 @@ pub fn core_token() -> Option { #[cfg(test)] mod tests { - use super::{CoreTokenCheck, classify_core_token_error}; + use super::{CoreTokenCheck, classify_core_token_error, write_marker}; use forgejo_api::{ApiError, ApiErrorKind, ForgejoError}; use reqwest::StatusCode; + #[test] + fn write_marker_creates_the_missing_parent_dir() { + let dir = tempfile::tempdir().expect("tempdir"); + let marker = dir.path().join("not-yet").join("nested").join("avatar-set"); + write_marker(&marker).expect("write"); + assert!(marker.is_file()); + } + + /// A parent that is a regular file makes `create_dir_all` fail for any + /// uid, root included. + #[test] + fn write_marker_reports_a_path_it_cannot_create() { + let dir = tempfile::tempdir().expect("tempdir"); + let file = dir.path().join("a-file"); + std::fs::write(&file, "").expect("file"); + assert!(write_marker(&file.join("sub").join("avatar-set")).is_err()); + } + fn api_err(kind: ApiErrorKind) -> ForgejoError { ForgejoError::ApiError(ApiError { message: None,