From 57bc76ea69e02179342f87ac762716e67e4453af Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 7 Aug 2026 12:05:40 +0000 Subject: [PATCH] fix(build): publish the deployed source revision Production ngit_build_info reports commit="unknown", forcing every stabilisation cycle to reconstruct the running revision from the deployment pin, store path, and activation time. The metrics reader also expected GIT_HASH while build.rs emitted GIT_COMMIT_SHORT. Use one full GIT_COMMIT compile-time value for metrics and retain its eight-character form for NIP-11 and the landing page. Nix package and module outputs inject the locked flake revision because filtered Nix sources do not contain .git; ordinary Cargo builds continue to derive HEAD from Git. Correctness assumes production consumes ngit-grasp through its exported flake module, which captures self.rev. Direct module imports remain supported but deliberately report unknown when no revision is supplied. Runtime configuration and deployment policy are unchanged. Validated with the 21 metrics-related library tests, nix flake check --no-build, and evaluation of the dirty-tree revision injection. A clean Nix package build and production endpoint verification follow on this committed revision. --- CHANGELOG.md | 3 +++ build.rs | 37 +++++++++++++++++++++++++------------ flake.nix | 12 +++++++++++- nix/module.nix | 3 ++- src/metrics/mod.rs | 2 +- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6605d9c..57392cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Published the source revision in build metrics, NIP-11 metadata, and the + landing page for Nix-built releases, where the filtered source archive does + not contain Git metadata. - Stopped routine client connection resets without a WebSocket close handshake from being reported as server errors, while retaining other embedded-relay failures at their original severity. diff --git a/build.rs b/build.rs index d93d74d..d28ba5f 100644 --- a/build.rs +++ b/build.rs @@ -1,20 +1,33 @@ -use std::process::Command; +use std::{env, process::Command}; fn main() { - // Get the short git commit hash - let output = Command::new("git") - .args(["rev-parse", "--short", "HEAD"]) - .output(); - - if let Ok(output) = output { - if output.status.success() { - let commit = String::from_utf8_lossy(&output.stdout); - let commit = commit.trim(); - println!("cargo:rustc-env=GIT_COMMIT_SHORT={}", commit); - } + if let Some(commit) = build_revision() { + let short: String = commit.chars().take(8).collect(); + println!("cargo:rustc-env=GIT_COMMIT={commit}"); + println!("cargo:rustc-env=GIT_COMMIT_SHORT={short}"); } + // Nix builds inject the locked flake revision because their source archive + // intentionally excludes .git. Development builds fall back to Git. + println!("cargo:rerun-if-env-changed=NGIT_BUILD_REVISION"); // Re-run if HEAD changes (new commits) println!("cargo:rerun-if-changed=.git/HEAD"); println!("cargo:rerun-if-changed=.git/refs/heads/"); } + +fn build_revision() -> Option { + env::var("NGIT_BUILD_REVISION") + .ok() + .filter(|revision| !revision.is_empty() && revision != "unknown") + .or_else(|| { + let output = Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .ok()?; + output + .status + .success() + .then(|| String::from_utf8_lossy(&output.stdout).trim().to_owned()) + .filter(|revision| !revision.is_empty()) + }) +} diff --git a/flake.nix b/flake.nix index 00dab13..e673c02 100644 --- a/flake.nix +++ b/flake.nix @@ -8,6 +8,12 @@ }; outputs = { self, nixpkgs, rust-overlay, flake-utils }: + let + sourceRevision = + if self ? rev then self.rev + else if self ? dirtyRev then self.dirtyRev + else "unknown"; + in (flake-utils.lib.eachDefaultSystem (system: let overlays = [ (import rust-overlay) ]; @@ -44,6 +50,7 @@ pname = "ngit-grasp"; version = "2.0.0"; src = ./.; + NGIT_BUILD_REVISION = sourceRevision; cargoLock = { lockFile = ./Cargo.lock; }; @@ -80,7 +87,10 @@ }; })) // { # NixOS module for deployment - nixosModules.default = import ./nix/module.nix; + nixosModules.default = { ... }: { + imports = [ ./nix/module.nix ]; + _module.args.ngitGraspSourceRevision = sourceRevision; + }; nixosModules.ngit-grasp = self.nixosModules.default; }; } diff --git a/nix/module.nix b/nix/module.nix index eca9b76..68cf379 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, ngitGraspSourceRevision ? "unknown", ... }: with lib; @@ -8,6 +8,7 @@ let pname = "ngit-grasp"; version = "2.0.0"; src = ../.; + NGIT_BUILD_REVISION = ngitGraspSourceRevision; cargoLock = { lockFile = ../Cargo.lock; }; diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index c9b1b36..87d03fb 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -832,7 +832,7 @@ impl MetricsInner { build_info .with_label_values(&[ env!("CARGO_PKG_VERSION"), - option_env!("GIT_HASH").unwrap_or("unknown"), + option_env!("GIT_COMMIT").unwrap_or("unknown"), ]) .set(1.0);