diff --git a/flake.lock b/flake.lock index 9d9152b2..f177d84d 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,50 @@ { "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" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762808025, + "narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1770141374, - "narHash": "sha256-yD4K/vRHPwXbJf5CK3JkptBA6nFWUKNX/jlFp2eKEQc=", + "lastModified": 1779259093, + "narHash": "sha256-7DKWmH23hL2eYdkxCKeqj2i+yljTKuU+3Nk1UPHOnxc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "41965737c1797c1d83cfb0b644ed0840a6220bd1", + "rev": "d99b013d5d1931ad77fe3912ed218170dec5d9a4", "type": "github" }, "original": { @@ -18,8 +56,25 @@ }, "root": { "inputs": { + "flake-utils": "flake-utils", + "gitignore": "gitignore", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 5ab26075..1967dda1 100644 --- a/flake.nix +++ b/flake.nix @@ -1,51 +1,65 @@ { + description = "msgvault — offline Gmail archive with full-text search"; + inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + gitignore.url = "github:hercules-ci/gitignore.nix"; + gitignore.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = - { nixpkgs, ... }: - let - forAllSystems = - fn: - nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ] ( - system: fn nixpkgs.legacyPackages.${system} - ); - - # Pin Go 1.26.3 until nixpkgs-unstable catches up from staging - goPinned = pkgs: pkgs.go_1_26.overrideAttrs (old: rec { - version = "1.26.3"; - src = pkgs.fetchurl { - url = "https://go.dev/dl/go${version}.src.tar.gz"; - hash = "sha256-HGRoddCqh5kTMYTtV895/yS97+jIggRwYCqdPW2Rkrg="; - }; - }); - in { - packages = forAllSystems (pkgs: { - default = (pkgs.buildGoModule.override { go = goPinned pkgs; }) { - pname = "msgvault"; - version = "0.14.1"; - src = ./.; - vendorHash = "sha256-/C+svBQ4b9+l8nY8BZ5Lvd072XLKpRDIR2fvqVqLJUE="; - proxyVendor = true; - subPackages = [ "cmd/msgvault" ]; - tags = [ "fts5" ]; - ldflags = [ - "-X github.com/wesm/msgvault/cmd/msgvault/cmd.Version=nix-dev" - ]; + nixpkgs, + flake-utils, + gitignore, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + # Pin Go 1.26.3 until nixpkgs-unstable ships it (currently 1.26.2). + # Scoped to msgvault only — do NOT export via overlay, that would + # invalidate every Go derivation in the transitive closure. + goPinned = pkgs.go_1_26.overrideAttrs (_: rec { + version = "1.26.3"; + src = pkgs.fetchurl { + url = "https://go.dev/dl/go${version}.src.tar.gz"; + hash = "sha256-HGRoddCqh5kTMYTtV895/yS97+jIggRwYCqdPW2Rkrg="; + }; + }); + + buildGoModule = pkgs.buildGoModule.override { go = goPinned; }; + + msgvault = pkgs.callPackage ./nix/package.nix { + inherit buildGoModule; + inherit (gitignore.lib) gitignoreSource; + }; + in + { + packages = { + default = msgvault; + msgvault = msgvault; }; - }); - devShells = forAllSystems (pkgs: { - default = pkgs.mkShell { + apps.default = flake-utils.lib.mkApp { drv = msgvault; }; + + devShells.default = pkgs.mkShell { packages = [ - (goPinned pkgs) + goPinned + pkgs.gopls + pkgs.gotools pkgs.golangci-lint + pkgs.delve pkgs.gcc pkgs.prek + pkgs.sqlite-interactive ]; }; - }); - }; + + formatter = pkgs.nixfmt-rfc-style; + } + ); } diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 00000000..e45b68bf --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,48 @@ +{ + lib, + buildGoModule, + gitignoreSource, + sqlite, +}: +let + version = "0.14.1"; +in +buildGoModule { + pname = "msgvault"; + inherit version; + + src = gitignoreSource ../.; + + vendorHash = "sha256-/C+svBQ4b9+l8nY8BZ5Lvd072XLKpRDIR2fvqVqLJUE="; + proxyVendor = true; + + subPackages = [ "cmd/msgvault" ]; + + # mattn/go-sqlite3, marcboeker/go-duckdb, and asg017/sqlite-vec-go-bindings + # all link C code. buildGoModule defaults CGO_ENABLED to 1, but be explicit. + env.CGO_ENABLED = 1; + + # sqlite-vec-go-bindings does `#include "sqlite3.h"` but ships no sqlite + # source — provide the system header via buildInputs. + buildInputs = [ sqlite ]; + + tags = [ + "fts5" + "sqlite_vec" + ]; + + ldflags = [ + "-s" + "-w" + "-X github.com/wesm/msgvault/cmd/msgvault/cmd.Version=${version}" + ]; + + doCheck = false; + + meta = { + description = "Offline Gmail archive with full-text search"; + homepage = "https://github.com/wesm/msgvault"; + license = lib.licenses.asl20; + mainProgram = "msgvault"; + }; +} diff --git a/scripts/update-nix-flake.sh b/scripts/update-nix-flake.sh index 86934d39..d80565fa 100755 --- a/scripts/update-nix-flake.sh +++ b/scripts/update-nix-flake.sh @@ -1,5 +1,5 @@ #!/bin/bash -# update-nix-flake.sh — Update flake.nix vendorHash (and optionally version), +# update-nix-flake.sh — Update nix/package.nix vendorHash (and optionally version), # then open a PR. Designed to be run after dependency changes or releases. # # Usage: @@ -11,6 +11,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$REPO_ROOT" +PACKAGE_NIX="nix/package.nix" + VERSION_TAG="${1:-}" # Require nix and gh @@ -36,7 +38,7 @@ echo "==> Creating branch $BRANCH from origin/main..." git fetch origin git checkout -b "$BRANCH" origin/main -# Step 1: Update version in flake.nix if a version tag was provided +# Step 1: Update version in nix/package.nix if a version tag was provided if [ -n "$VERSION_TAG" ]; then # Strip leading 'v' if present VERSION="${VERSION_TAG#v}" @@ -46,17 +48,16 @@ if [ -n "$VERSION_TAG" ]; then exit 1 fi echo "==> Updating version to $VERSION..." - # Only replace the msgvault version (after pname), not the Go version - sed -i.bak -E '/pname = "msgvault"/,/version = "[^"]+"/ s/version = "[^"]+"/version = "'"$VERSION"'"/' flake.nix - rm -f flake.nix.bak + sed -i.bak -E 's/version = "[^"]+"/version = "'"$VERSION"'"/' "$PACKAGE_NIX" + rm -f "${PACKAGE_NIX}.bak" fi # Step 2: Compute the correct vendorHash echo "==> Computing vendorHash (this runs nix build with a fake hash)..." # Set a fake hash to force nix to report the correct one -sed -i.bak -E 's|vendorHash = "sha256-[^"]+"|vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="|' flake.nix -rm -f flake.nix.bak +sed -i.bak -E 's|vendorHash = "sha256-[^"]+"|vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="|' "$PACKAGE_NIX" +rm -f "${PACKAGE_NIX}.bak" # Run nix build — it will fail and print the correct hash CORRECT_HASH="" @@ -67,21 +68,21 @@ CORRECT_HASH=$(echo "$BUILD_OUTPUT" | sed -n 's/.*got:[[:space:]]*\(sha256-[A-Za if [ -z "$CORRECT_HASH" ] || ! echo "$CORRECT_HASH" | grep -qE '^sha256-[A-Za-z0-9+/]{43}=$'; then echo "Error: Could not extract valid vendorHash from nix build output:" >&2 echo "$BUILD_OUTPUT" >&2 - git checkout -- flake.nix + git checkout -- "$PACKAGE_NIX" git checkout - git branch -D "$BRANCH" exit 1 fi echo "==> Got vendorHash: $CORRECT_HASH" -sed -i.bak -E "s|vendorHash = \"sha256-[^\"]+\"|vendorHash = \"$CORRECT_HASH\"|" flake.nix -rm -f flake.nix.bak +sed -i.bak -E "s|vendorHash = \"sha256-[^\"]+\"|vendorHash = \"$CORRECT_HASH\"|" "$PACKAGE_NIX" +rm -f "${PACKAGE_NIX}.bak" # Step 3: Verify it actually builds echo "==> Verifying nix build succeeds..." if ! nix build; then echo "Error: nix build failed even with updated hash" >&2 - git checkout -- flake.nix + git checkout -- "$PACKAGE_NIX" git checkout - git branch -D "$BRANCH" exit 1 @@ -89,7 +90,7 @@ fi # Step 4: Commit and open PR echo "==> Committing and opening PR..." -git add flake.nix +git add "$PACKAGE_NIX" COMMIT_MSG="Update nix flake vendorHash" PR_TITLE="Update nix flake vendorHash"