Add build version metadata, changelog, and version display

Embed git commit hash, dirty flag, and target triple in all binaries
via a zero-dependency build.rs. Wire clap short/long version output
so -V shows "0.1.0 (rev abc1234)" and --version adds the target
triple. Log version at daemon startup.

Add version field to show_status control socket API response. Show
the daemon's version in fipstop's tab bar title and Runtime section.

Add CHANGELOG.md in Keep a Changelog format with the 0.1.0-alpha
release (2026-02-24) and unreleased work since then.
This commit is contained in:
Johnathan Corgan
2026-03-08 02:19:33 +00:00
parent bf117df0ca
commit c086ee3edf
10 changed files with 166 additions and 6 deletions
+8 -2
View File
@@ -4,6 +4,7 @@
use clap::Parser;
use fips::config::{resolve_identity, IdentitySource};
use fips::version;
use fips::{Config, Node};
use std::path::PathBuf;
use tracing::{error, info, warn, Level};
@@ -11,7 +12,12 @@ use tracing_subscriber::{fmt, EnvFilter};
/// FIPS mesh network daemon
#[derive(Parser, Debug)]
#[command(name = "fips", version, about)]
#[command(
name = "fips",
version = version::short_version(),
long_version = version::long_version(),
about
)]
struct Args {
/// Path to configuration file (overrides default search paths)
#[arg(short, long, value_name = "FILE")]
@@ -32,7 +38,7 @@ async fn main() {
let args = Args::parse();
info!("FIPS starting");
info!("FIPS {} starting", version::short_version());
// Load configuration
info!("Loading configuration");
+7 -1
View File
@@ -5,6 +5,7 @@
use clap::{Parser, Subcommand};
use fips::config::{write_key_file, write_pub_file};
use fips::version;
use fips::{encode_nsec, Identity};
use std::io::{BufRead, BufReader, Write};
use std::os::unix::net::UnixStream;
@@ -13,7 +14,12 @@ use std::time::Duration;
/// FIPS control client
#[derive(Parser, Debug)]
#[command(name = "fipsctl", version, about = "Query a running FIPS daemon")]
#[command(
name = "fipsctl",
version = version::short_version(),
long_version = version::long_version(),
about = "Query a running FIPS daemon"
)]
struct Cli {
/// Control socket path override
#[arg(short = 's', long)]
+7 -1
View File
@@ -7,13 +7,19 @@ use app::{App, ConnectionState, SelectedTreeItem, Tab};
use clap::Parser;
use client::ControlClient;
use event::{Event, EventHandler};
use fips::version;
use ratatui::crossterm::event::{KeyCode, KeyModifiers};
use std::path::{Path, PathBuf};
use std::time::Duration;
/// FIPS mesh monitoring TUI
#[derive(Parser, Debug)]
#[command(name = "fipstop", version, about = "Monitor a running FIPS daemon")]
#[command(
name = "fipstop",
version = version::short_version(),
long_version = version::long_version(),
about = "Monitor a running FIPS daemon"
)]
struct Cli {
/// Control socket path override
#[arg(short = 's', long)]
+4 -1
View File
@@ -41,6 +41,7 @@ fn draw_runtime(frame: &mut Frame, data: &serde_json::Value, area: Rect) {
let inner = block.inner(area);
frame.render_widget(block, area);
let version = helpers::str_field(data, "version");
let pid = helpers::u64_field(data, "pid");
let exe = helpers::str_field(data, "exe_path");
let uptime_secs = data.get("uptime_secs").and_then(|v| v.as_u64()).unwrap_or(0);
@@ -52,7 +53,9 @@ fn draw_runtime(frame: &mut Frame, data: &serde_json::Value, area: Rect) {
let lines = vec![
Line::from(vec![
Span::styled(" pid: ", label),
Span::styled(" ver: ", label),
Span::raw(version.to_string()),
Span::styled(" pid: ", label),
Span::raw(pid),
Span::styled(" uptime: ", label),
Span::raw(uptime),
+2 -1
View File
@@ -30,7 +30,8 @@ pub fn draw(frame: &mut Frame, app: &mut App) {
}
fn draw_tab_bar(frame: &mut Frame, app: &App, area: Rect) {
let block = Block::default().borders(Borders::ALL).title(" fipstop ");
let title = format!(" fipstop {} ", fips::version::short_version());
let block = Block::default().borders(Borders::ALL).title(title);
let inner = block.inner(area);
frame.render_widget(block, area);
+1
View File
@@ -40,6 +40,7 @@ pub fn show_status(node: &Node) -> Value {
let fwd = node.stats().snapshot().forwarding;
json!({
"version": crate::version::short_version(),
"npub": node.npub(),
"node_addr": hex::encode(node.node_addr().as_bytes()),
"ipv6_addr": format!("{}", node.identity().address()),
+1
View File
@@ -3,6 +3,7 @@
//! A distributed, decentralized network routing protocol for mesh nodes
//! connecting over arbitrary transports.
pub mod version;
pub mod bloom;
pub mod cache;
pub mod config;
+38
View File
@@ -0,0 +1,38 @@
//! Build version information for FIPS binaries.
use std::sync::LazyLock;
/// Package version from Cargo.toml.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
/// Short git commit hash (empty if not available).
const GIT_HASH: &str = env!("FIPS_GIT_HASH");
/// Dirty flag ("-dirty" or empty).
const GIT_DIRTY: &str = env!("FIPS_GIT_DIRTY");
/// Build target triple.
const TARGET: &str = env!("FIPS_TARGET");
/// Short version string for `-V`: `0.1.0 (rev abc1234567)`
#[allow(clippy::const_is_empty)]
static SHORT_VERSION: LazyLock<String> = LazyLock::new(|| {
if GIT_HASH.is_empty() {
VERSION.to_string()
} else {
format!("{VERSION} (rev {GIT_HASH}{GIT_DIRTY})")
}
});
/// Long version string for `--version` with build metadata.
static LONG_VERSION: LazyLock<String> = LazyLock::new(|| {
format!("{}\ntarget: {TARGET}", *SHORT_VERSION)
});
pub fn short_version() -> &'static str {
&SHORT_VERSION
}
pub fn long_version() -> &'static str {
&LONG_VERSION
}