From 03140593e85bfbf2d663a29c697df81c4a1a17d0 Mon Sep 17 00:00:00 2001
From: Yifei Sun <ysun@hey.com>
Date: Fri, 10 Jan 2025 20:30:39 -0500
Subject: [PATCH] flake.nix: refactor and correctly propagate tailscale version
 when deploying with nix

- use flake-parts instead of flake-utils

- fix wrong version info by setting ldflags  and , where  is matched from  using regex

- originally, is set to  by default (which is fine), however, the module does not apply the defined overlay, causing the module to use [the outdated golink from nixpkgs](https://search.nixos.org/packages?channel=unstable&show=golink&from=0&size=50&sort=relevance&type=packages&query=golink)

- update the dev shell go from 1.21 to 1.23

Signed-off-by: Yifei Sun <ysun@hey.com>
---
 flake.lock |  59 +++++++-----
 flake.nix  | 268 +++++++++++++++++++++++++----------------------------
 2 files changed, 162 insertions(+), 165 deletions(-)

diff --git a/flake.lock b/flake.lock
index 355a680..b18a35c 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,30 +1,12 @@
 {
   "nodes": {
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1731533236,
-        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1731890469,
-        "narHash": "sha256-D1FNZ70NmQEwNxpSSdTXCSklBH1z2isPR84J6DQrJGs=",
+        "lastModified": 1735268880,
+        "narHash": "sha256-7QEFnKkzD13SPxs+UFR5bUFN2fRw+GlL0am72ZjNre4=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "5083ec887760adfe12af64830a66807423a859a7",
+        "rev": "7cc0bff31a3a705d3ac4fdceb030a17239412210",
         "type": "github"
       },
       "original": {
@@ -33,10 +15,41 @@
         "type": "indirect"
       }
     },
+    "nixpkgs-lib": {
+      "locked": {
+        "lastModified": 1733096140,
+        "narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
+      }
+    },
+    "parts": {
+      "inputs": {
+        "nixpkgs-lib": "nixpkgs-lib"
+      },
+      "locked": {
+        "lastModified": 1733312601,
+        "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
-        "flake-utils": "flake-utils",
-        "nixpkgs": "nixpkgs"
+        "nixpkgs": "nixpkgs",
+        "parts": "parts",
+        "systems": "systems"
       }
     },
     "systems": {
diff --git a/flake.nix b/flake.nix
index 5c18d91..2b7e456 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,159 +3,143 @@
 
   inputs = {
     nixpkgs.url = "nixpkgs/nixpkgs-unstable";
-    flake-utils.url = "github:numtide/flake-utils";
+    parts.url = "github:hercules-ci/flake-parts";
+    systems.url = "github:nix-systems/default";
   };
 
-  outputs =
-    { self
-    , nixpkgs
-    , flake-utils
-    , ...
-    }:
-    let
-      golinkVersion =
-        if (self ? shortRev)
-        then self.shortRev
-        else "dev";
-    in
-    {
-      overlay = final: prev:
-        let
-          pkgs = nixpkgs.legacyPackages.${prev.system};
-        in
-        rec {
-          golink = pkgs.buildGo123Module rec {
-            pname = "golink";
-            version = golinkVersion;
-            src = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
-
-            vendorHash = "sha256-myGEAOCJkeKGTzyLD6yBC10yHULxcbOnzseGVtYD7qM="; # SHA based on vendoring go.mod
-          };
+  outputs = inputs @ { self, parts, ... }: parts.lib.mkFlake { inherit inputs; } {
+    systems = import inputs.systems;
+
+    perSystem = { pkgs, ... }: {
+      formatter = pkgs.nixpkgs-fmt;
+
+      devShells.default = pkgs.mkShell { buildInputs = [ pkgs.go_1_23 ]; };
+
+      packages.default =
+        pkgs.buildGo123Module {
+          pname = "golink";
+          version =
+            if (self ? shortRev)
+            then self.shortRev
+            else "dev";
+          src = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
+          ldflags =
+            let
+              tsVersion = with builtins; head (match
+                ".*tailscale.com v([0-9]+\.[0-9]+\.[0-9]+-[a-zA-Z]+).*"
+                (readFile ./go.mod));
+            in
+            [
+              "-w"
+              "-s"
+              "-X tailscale.com/version.longStamp=${tsVersion}"
+              "-X tailscale.com/version.shortStamp=${tsVersion}"
+            ];
+          vendorHash = "sha256-myGEAOCJkeKGTzyLD6yBC10yHULxcbOnzseGVtYD7qM="; # SHA based on vendoring go.mod
         };
-    }
-    // flake-utils.lib.eachDefaultSystem
-      (system:
+    };
+
+    flake.overlays.default = final: prev: {
+      golink = self.packages.${prev.system}.default;
+    };
+
+    flake.nixosModules.default = { config, lib, pkgs, ... }:
       let
-        pkgs = import nixpkgs {
-          overlays = [ self.overlay ];
-          inherit system;
-        };
+        cfg = config.services.golink;
+        inherit (lib)
+          concatStringsSep
+          escapeShellArg
+          mkEnableOption
+          mkIf
+          mkOption
+          optionalString
+          optionals
+          types
+          ;
       in
-      rec {
-        # `nix develop`
-        devShell = pkgs.mkShell { buildInputs = [ pkgs.go_1_21 ]; };
+      {
+        options.services.golink = {
+          enable = mkEnableOption "Enable golink";
+
+          package = mkOption {
+            type = types.package;
+            description = ''
+              golink package to use
+            '';
+            default = pkgs.golink;
+          };
 
-        # `nix build`
-        packages = with pkgs; {
-          inherit golink;
-        };
+          dataDir = mkOption {
+            type = types.path;
+            default = "/var/lib/golink";
+            description = "Path to data dir";
+          };
 
-        defaultPackage = pkgs.golink;
+          user = mkOption {
+            type = types.str;
+            default = "golink";
+            description = "User account under which golink runs.";
+          };
+
+          group = mkOption {
+            type = types.str;
+            default = "golink";
+            description = "Group account under which golink runs.";
+          };
 
-        # `nix run`
-        apps.golink = flake-utils.lib.mkApp {
-          drv = packages.golink;
+          databaseFile = mkOption {
+            type = types.path;
+            default = "/var/lib/golink/golink.db";
+            description = "Path to SQLite database";
+          };
+
+          tailscaleAuthKeyFile = mkOption {
+            type = types.path;
+            description = "Path to file containing the Tailscale Auth Key";
+          };
+
+          verbose = mkOption {
+            type = types.bool;
+            default = false;
+          };
         };
-        defaultApp = apps.golink;
-
-        overlays.default = self.overlay;
-      })
-    // {
-      nixosModules.default =
-        { pkgs
-        , lib
-        , config
-        , ...
-        }:
-        let
-          cfg = config.services.golink;
-        in
-        {
-          options = with lib; {
-            services.golink = {
-              enable = mkEnableOption "Enable golink";
-
-              package = mkOption {
-                type = types.package;
-                description = ''
-                  golink package to use
-                '';
-                default = pkgs.golink;
-              };
-
-              dataDir = mkOption {
-                type = types.path;
-                default = "/var/lib/golink";
-                description = "Path to data dir";
-              };
-
-              user = mkOption {
-                type = types.str;
-                default = "golink";
-                description = "User account under which golink runs.";
-              };
-
-              group = mkOption {
-                type = types.str;
-                default = "golink";
-                description = "Group account under which golink runs.";
-              };
-
-              databaseFile = mkOption {
-                type = types.path;
-                default = "/var/lib/golink/golink.db";
-                description = "Path to SQLite database";
-              };
-
-              tailscaleAuthKeyFile = mkOption {
-                type = types.path;
-                description = "Path to file containing the Tailscale Auth Key";
-              };
-
-              verbose = mkOption {
-                type = types.bool;
-                default = false;
-              };
-            };
+
+        config = mkIf cfg.enable {
+          nixpkgs.overlays = [ self.overlays.default ];
+
+          users.groups."${cfg.group}" = { };
+          users.users."${cfg.user}" = {
+            home = cfg.dataDir;
+            createHome = true;
+            group = "${cfg.group}";
+            isSystemUser = true;
+            isNormalUser = false;
+            description = "user for golink service";
           };
-          config = lib.mkIf cfg.enable {
-            users.users."${cfg.user}" = {
-              home = cfg.dataDir;
-              createHome = true;
-              group = "${cfg.group}";
-              isSystemUser = true;
-              isNormalUser = false;
-              description = "user for golink service";
-            };
-            users.groups."${cfg.group}" = { };
-
-            systemd.services.golink = {
-              enable = true;
-              script =
-                let
-                  args =
-                    [
-                      "--sqlitedb ${cfg.databaseFile}"
-                    ]
-                    ++ lib.optionals cfg.verbose [ "--verbose" ];
-                in
-                ''
-                  ${lib.optionalString (cfg.tailscaleAuthKeyFile != null) ''
-                    export TS_AUTHKEY="$(head -n1 ${lib.escapeShellArg cfg.tailscaleAuthKeyFile})"
-                  ''}
-
-                  ${cfg.package}/bin/golink ${builtins.concatStringsSep " " args}
-                '';
-              wantedBy = [ "multi-user.target" ];
-              serviceConfig = {
-                User = cfg.user;
-                Group = cfg.group;
-                Restart = "always";
-                RestartSec = "15";
-                WorkingDirectory = "${cfg.dataDir}";
-              };
+
+          systemd.services.golink = {
+            enable = true;
+            script =
+              let
+                args = [ "--sqlitedb ${cfg.databaseFile}" ] ++ optionals cfg.verbose [ "--verbose" ];
+              in
+              ''
+                ${optionalString (cfg.tailscaleAuthKeyFile != null) ''
+                  export TS_AUTHKEY="$(head -n1 ${escapeShellArg cfg.tailscaleAuthKeyFile})"
+                ''}
+
+                ${cfg.package}/bin/golink ${concatStringsSep " " args}
+              '';
+            wantedBy = [ "multi-user.target" ];
+            serviceConfig = {
+              User = cfg.user;
+              Group = cfg.group;
+              Restart = "always";
+              RestartSec = "15";
+              WorkingDirectory = "${cfg.dataDir}";
             };
           };
         };
-    };
+      };
+  };
 }