LCOV - code coverage report
Current view: top level - service/src - build_info.rs (source / functions) Coverage Total Hit
Test: Rust Backend Coverage Lines: 100.0 % 31 31
Test Date: 2025-12-20 21:58:40 Functions: 45.8 % 48 22

            Line data    Source code
       1              : use async_graphql::SimpleObject;
       2              : use chrono::{DateTime, Utc};
       3              : use serde::Serialize;
       4              : use std::env;
       5              : use utoipa::ToSchema;
       6              : 
       7              : /// Build metadata exposed via GraphQL, REST, and logs.
       8              : #[derive(Clone, Debug, PartialEq, Eq, Serialize, SimpleObject, ToSchema)]
       9              : #[graphql(rename_fields = "camelCase")]
      10              : #[serde(rename_all = "camelCase")]
      11              : pub struct BuildInfo {
      12              :     pub version: String,
      13              :     pub git_sha: String,
      14              :     pub build_time: String,
      15              :     #[serde(skip_serializing_if = "Option::is_none")]
      16              :     pub message: Option<String>,
      17              : }
      18              : 
      19              : #[derive(Clone, Debug)]
      20              : pub struct BuildInfoProvider {
      21              :     info: BuildInfo,
      22              : }
      23              : 
      24              : impl BuildInfoProvider {
      25              :     /// Construct a provider using environment variables, falling back to sensible defaults.
      26              :     #[must_use]
      27           71 :     pub fn from_env() -> Self {
      28          284 :         Self::from_lookup(|key| env::var(key).ok())
      29           71 :     }
      30              : 
      31              :     /// Construct a provider using a custom lookup function (useful for tests).
      32              :     #[must_use]
      33           75 :     pub fn from_lookup<F>(mut lookup: F) -> Self
      34           75 :     where
      35           75 :         F: FnMut(&str) -> Option<String>,
      36              :     {
      37           75 :         let version = lookup("APP_VERSION")
      38           75 :             .or_else(|| lookup("VERSION"))
      39           75 :             .unwrap_or_else(|| "dev".to_string());
      40              : 
      41           75 :         let git_sha = lookup("GIT_SHA").unwrap_or_else(|| "unknown".to_string());
      42              : 
      43           75 :         let build_time = lookup("BUILD_TIME")
      44           75 :             .and_then(|value| normalize_build_time(&value))
      45           75 :             .unwrap_or_else(|| "unknown".to_string());
      46              : 
      47           75 :         let message = lookup("BUILD_MESSAGE");
      48              : 
      49           75 :         let info = BuildInfo {
      50           75 :             version,
      51           75 :             git_sha,
      52           75 :             build_time,
      53           75 :             message,
      54           75 :         };
      55              : 
      56           75 :         Self { info }
      57           75 :     }
      58              : 
      59              :     /// Fetch the resolved build info values.
      60              :     #[must_use]
      61           13 :     pub fn build_info(&self) -> BuildInfo {
      62           13 :         self.info.clone()
      63           13 :     }
      64              : }
      65              : 
      66           73 : fn normalize_build_time(value: &str) -> Option<String> {
      67           73 :     DateTime::parse_from_rfc3339(value)
      68           73 :         .or_else(|_| DateTime::parse_from_rfc3339(&format!("{value}Z")))
      69           73 :         .map(|dt| dt.with_timezone(&Utc).to_rfc3339())
      70           73 :         .ok()
      71           73 : }
        

Generated by: LCOV version 2.0-1