add --version flag with calver-dev version string
build.rs computes the dev version as YYYY-MM-DD-dev+COMMIT using git.
Release builds override via the RANGER_VERSION env var set in the
GitHub Actions workflow.

Cargo.toml version set to 0.0.0 since it is never used directly.
change zuqtyuytlvzwpwwlwturksnvmqswnptz
commit 41db850d7aa89a35d65f3b55aca1bd812fdf5f7b
author Alpha Chen <alpha@kejadlen.dev>
date
parent okzskoxq
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 687655f..33c9a57 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -29,6 +29,8 @@ jobs:
           echo "version=${CALVER}+${SHORT_SHA}" >> $GITHUB_OUTPUT
 
       - name: Build
+        env:
+          RANGER_VERSION: ${{ steps.version.outputs.version }}
         run: |
           cargo build --release
           tar -czf ranger-aarch64-apple-darwin.tar.gz -C target/release ranger
diff --git a/Cargo.lock b/Cargo.lock
index bbd646e..6156cd0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1498,7 +1498,7 @@ dependencies = [
 
 [[package]]
 name = "ranger"
-version = "0.1.0"
+version = "0.0.0"
 dependencies = [
  "assert_cmd",
  "axum",
diff --git a/Cargo.toml b/Cargo.toml
index 4b62f2c..eee5950 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ranger"
-version = "0.1.0"
+version = "0.0.0"
 edition = "2024"
 
 [[bin]]
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..9b45b4a
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,23 @@
+use std::process::Command;
+
+fn main() {
+    // Release builds set RANGER_VERSION externally; don't override.
+    if std::env::var("RANGER_VERSION").is_ok() {
+        return;
+    }
+
+    let date = cmd("date", &["-u", "+%Y-%m-%d"]).unwrap_or("0000-00-00".into());
+    let commit = cmd("git", &["rev-parse", "--short=8", "HEAD"]).unwrap_or("unknown".into());
+    let version = format!("{date}-dev+{commit}");
+
+    println!("cargo:rustc-env=RANGER_VERSION={version}");
+}
+
+fn cmd(program: &str, args: &[&str]) -> Option<String> {
+    let output = Command::new(program).args(args).output().ok()?;
+    if !output.status.success() {
+        return None;
+    }
+    let s = String::from_utf8_lossy(&output.stdout).trim().to_string();
+    if s.is_empty() { None } else { Some(s) }
+}
diff --git a/src/bin/ranger/main.rs b/src/bin/ranger/main.rs
index 45f2623..eb11752 100644
--- a/src/bin/ranger/main.rs
+++ b/src/bin/ranger/main.rs
@@ -7,8 +7,11 @@ use clap_complete::engine::ArgValueCompleter;
 use std::path::PathBuf;
 use tracing_subscriber::{EnvFilter, fmt, prelude::*};
 
+/// Build-time version set by build.rs (dev) or release workflow.
+const VERSION: &str = env!("RANGER_VERSION");
+
 #[derive(Parser)]
-#[command(name = "ranger", about = "Personal task tracker")]
+#[command(name = "ranger", version = VERSION, about = "Personal task tracker")]
 struct Cli {
     /// Output as JSON
     #[arg(long, global = true)]
diff --git a/tests/cli.rs b/tests/cli.rs
index 40d223b..df2a893 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -498,4 +498,12 @@ fn full_workflow() {
         stdout.contains("Ranger"),
         "backlog name completions should include backlog names"
     );
+
+    // --version prints version string
+    ranger(db_path)
+        .args(["--version"])
+        .assert()
+        .success()
+        .stdout(predicates::str::contains("ranger "))
+        .stdout(predicates::str::is_match(r"ranger \S+").unwrap());
 }