tix-tracker 0.12.0

A terminal issue tracker: markdown + YAML frontmatter issues with a kanban TUI and CLI
Documentation
//! `tix version` — the crate version, and **how** this binary was built.
//!
//! `tix --version` answers "which release is this?". This answers the question a
//! developer actually has when a change seems not to have taken effect: *did the
//! binary I just ran come from the code on disk?* A version number cannot answer
//! that — it only moves when someone bumps it — so the build stamp baked in by
//! `build.rs` (the commit, whether the tree was dirty, and when it was built)
//! does. Rebuilding on unchanged sources prints the same stamp; rebuilding after
//! an edit prints a new one.
//!
//! Read-only and store-free: it needs no `tix.toml` and no issue tree, so it can
//! be run from anywhere — including a directory where the rest of the CLI would
//! refuse to start.

/// The commit this binary was built from, `-dirty` when the working tree had
/// uncommitted changes, and `unknown` when `git` was unavailable at build time.
pub const COMMIT: &str = env!("TIX_BUILD_COMMIT");

/// Print the version and the build provenance.
pub fn print() {
    println!("tix {}", env!("CARGO_PKG_VERSION"));
    println!("commit: {}", COMMIT);
    println!("built:  {}", built_at());
}

/// [`env!("TIX_BUILD_UNIX")`] rendered as a UTC timestamp.
///
/// Falls back to the raw seconds when the value cannot be read as a timestamp —
/// a stamp that cannot be rendered is still worth printing, and never worth
/// panicking over.
fn built_at() -> String {
    let raw = env!("TIX_BUILD_UNIX");
    let Ok(seconds) = raw.parse::<i64>() else {
        return raw.to_string();
    };
    match time::OffsetDateTime::from_unix_timestamp(seconds) {
        Ok(at) => format!(
            "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
            at.year(),
            at.month() as u8,
            at.day(),
            at.hour(),
            at.minute(),
            at.second()
        ),
        Err(_) => raw.to_string(),
    }
}

#[cfg(test)]
mod tests {
    #[allow(clippy::wildcard_imports)]
    use super::*;

    #[test]
    fn the_commit_stamp_is_never_empty() {
        // `unknown` is the documented fallback, so the field is always printable —
        // a blank line would read as "no stamp" rather than "no git here".
        assert_ne!(COMMIT.trim(), "");
    }

    #[test]
    fn the_build_time_renders_as_an_iso_utc_timestamp() {
        let rendered = built_at();
        assert_eq!(rendered.len(), 20, "unexpected stamp: {rendered}");
        assert!(rendered.ends_with('Z'), "unexpected stamp: {rendered}");
        let (date, time) = rendered.split_once('T').expect("an ISO stamp has a `T`");
        assert_eq!(date.split('-').count(), 3, "unexpected date: {date}");
        assert_eq!(time.split(':').count(), 3, "unexpected time: {time}");
        assert!(
            rendered
                .chars()
                .all(|c| c.is_ascii_digit() || "T-:Z".contains(c)),
            "unexpected stamp: {rendered}"
        );
    }

    #[test]
    fn the_crate_version_is_semver_shaped() {
        // The same shape `bin/tix-sync-version.sh` parses out of `Cargo.toml`, so a
        // version this command prints is one the release tooling can read.
        let version = env!("CARGO_PKG_VERSION");
        let parts: Vec<&str> = version.split('.').collect();
        assert_eq!(parts.len(), 3, "expected a semver version, got {version}");
        assert!(
            parts.iter().all(|part| part.parse::<u64>().is_ok()),
            "expected numeric components, got {version}"
        );
    }
}