]> git.giacomolli.uk - onechat/commitdiff
Version the package and command from the commit
authorAnderson A. Giacomolli <agiacomolli@gmail.com>
Tue, 10 Nov 2026 00:54:15 +0000 (21:54 -0300)
committerAnderson A. Giacomolli <agiacomolli@gmail.com>
Tue, 10 Nov 2026 00:54:15 +0000 (21:54 -0300)
The Nix package and the version command use the commit date and short
revision, with a dirty suffix for a changed tree. Direct Go builds keep
the dev version. The install check compares the binary version with the
package version so a missing linker value fails the build.

README.rst
command_test.go [new file with mode: 0644]
flake.nix
main.go
nix/package.nix

index d32c14bea23925849fa2181a376f453d33d4b98f..16aabce997910ca3c9257a7e47e82d45f9d0617f 100644 (file)
@@ -499,6 +499,9 @@ Build and run:
    nix build
    ./result/bin/onechat
 
+``onechat version`` prints ``yyyy-mm-dd-gitshort`` for a Nix build, adds
+``-dirty`` for a dirty tree, and prints ``dev`` for a direct Go build.
+
 Format and check all files:
 
 .. code:: console
diff --git a/command_test.go b/command_test.go
new file mode 100644 (file)
index 0000000..3d89327
--- /dev/null
@@ -0,0 +1,49 @@
+package main
+
+import (
+       "io"
+       "os"
+       "testing"
+
+       "github.com/stretchr/testify/require"
+)
+
+func TestVersionCommandPrintsBuildVersion(t *testing.T) {
+       original := version
+       version = "test-version"
+       t.Cleanup(func() {
+               version = original
+       })
+
+       require.Equal(t, "test-version\n", commandOutput(t, "version"))
+}
+
+func TestHelpListsVersionCommand(t *testing.T) {
+       require.Contains(t, commandOutput(t, "help"), "  version                  show the build version\n")
+}
+
+func commandOutput(t *testing.T, args ...string) string {
+       t.Helper()
+
+       reader, writer, err := os.Pipe()
+       require.NoError(t, err)
+
+       originalArgs, originalStdout := os.Args, os.Stdout
+       os.Args = append([]string{"onechat"}, args...)
+       os.Stdout = writer
+       t.Cleanup(func() {
+               os.Args, os.Stdout = originalArgs, originalStdout
+
+               require.NoError(t, reader.Close())
+       })
+
+       err = run()
+       require.NoError(t, err)
+
+       require.NoError(t, writer.Close())
+
+       output, err := io.ReadAll(reader)
+       require.NoError(t, err)
+
+       return string(output)
+}
index c2ca691ae7851b43ccf3c766446cf9092735615a..670dc66643744b28dcd7686b4218d296eef383a2 100644 (file)
--- a/flake.nix
+++ b/flake.nix
     }:
     let
       forEachSystem = nixpkgs.lib.genAttrs (import systems);
+      date = self.lastModifiedDate;
+      revision = self.shortRev or self.dirtyShortRev or "unknown";
+      version = "${builtins.substring 0 4 date}-${builtins.substring 4 2 date}-${builtins.substring 6 2 date}-${revision}";
     in
     {
       packages = forEachSystem (
         system:
         let
           pkgs = nixpkgs.legacyPackages.${system};
-          onechat = pkgs.callPackage ./nix/package.nix { src = self; };
+          onechat = pkgs.callPackage ./nix/package.nix {
+            src = self;
+            inherit version;
+          };
         in
         {
           inherit onechat;
diff --git a/main.go b/main.go
index 9c1c8b92f7abf6c301ad4a64c849b623838a13e7..a73407f7c8457e973f0fb7731312a139acb7c3d2 100644 (file)
--- a/main.go
+++ b/main.go
@@ -20,11 +20,15 @@ Commands:
     -n                     print the plan without model calls
   login                    log in to ChatGPT with a device code
   probe LOG COUNT [BUILDS] measure the compactor on a log, with real calls
+  version                  show the build version
   help                     show this help
 
 Chat needs a running daemon. ONECHAT_DIR sets the data directory.
 `
 
+// version is set by the package build and stays dev for direct Go builds.
+var version = "dev"
+
 func main() {
        err := run()
        if err != nil {
@@ -44,6 +48,11 @@ func run() error {
                if err != nil {
                        return fmt.Errorf("write command help: %w", err)
                }
+       case len(args) == 1 && args[0] == "version":
+               _, err := fmt.Println(version)
+               if err != nil {
+                       return fmt.Errorf("write build version: %w", err)
+               }
        case len(args) == 1 && args[0] == "login":
                err := chatgptLogin(ctx, os.Stdout)
                if err != nil {
index b38dcc05783e8b2c95b41c0bbfe28b647346d1e7..f631044dc0f039ad4c0a5bbae78fd52d586a0a38 100644 (file)
@@ -2,13 +2,14 @@
   lib,
   buildGoModule,
   src,
+  version,
 }:
 buildGoModule {
   pname = "onechat";
-  version = "0.1.0";
-  inherit src;
+  inherit src version;
 
   subPackages = [ "." ];
+  ldflags = [ "-X main.version=${version}" ];
   vendorHash = "sha256-35kAjo+7gbOOzNbKJyMYUcAF11HK7WzO3m9ZcrOsqY0=";
 
   # The flake check runs the full replay.
@@ -24,6 +25,7 @@ buildGoModule {
   installCheckPhase = ''
     runHook preInstallCheck
     [[ "$("$out/bin/onechat" help)" == "Usage: onechat "* ]]
+    [[ "$("$out/bin/onechat" version)" == "${version}" ]]
     runHook postInstallCheck
   '';