Remove buck2 and make the flake the single build entry point
buck2 was a one-target wrapper: a genrule that shelled out to scripts/build-image.sh, which in turn ran `nix build .#image`. The whole prelude/toolchain/cell setup existed to describe a build that Nix already described. Delete BUCK, .buckconfig, .buckroot and toolchains/, and let the flake own it directly. The flake now covers every system it can (x86_64/aarch64 linux, aarch64 darwin -- nixpkgs unstable has dropped x86_64-darwin), and gains a devShell with the CGO include flags the Makefile computes, apps for `nix run .#glean` / `nix run .#image`, checks that build the binary and frontend and run the Go tests, and a committed flake.lock. The image output stays Linux-only, since dockerTools is. build-image.sh is no longer fed a buck2 symlink farm: it resolves the repo from its own location, builds locally when `nix` is present, and only falls back to the remote $GLEAN_NIX_VM builder otherwise. The Makefile's docker-build/docker-push targets pointed at a Dockerfile that no longer exists; image/image-load/image-push replace them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d76710b parent: e861f3e deleted
.buckconfig +0 -29 | deleted file mode 100644 | ||
| @@ -1,29 +0,0 @@ | ||
| 1 | -[cells] | |
| 2 | - root = . | |
| 3 | - prelude = prelude | |
| 4 | - toolchains = toolchains | |
| 5 | - none = none | |
| 6 | - | |
| 7 | -[cell_aliases] | |
| 8 | - config = prelude | |
| 9 | - ovr_config = prelude | |
| 10 | - fbcode = none | |
| 11 | - fbsource = none | |
| 12 | - fbcode_macros = none | |
| 13 | - buck = none | |
| 14 | - | |
| 15 | -# Uses a copy of the prelude bundled with the buck2 binary. You can alternatively delete this | |
| 16 | -# section and vendor a copy of the prelude to the `prelude` directory of your project. | |
| 17 | -[external_cells] | |
| 18 | - prelude = bundled | |
| 19 | - | |
| 20 | -[parser] | |
| 21 | - target_platform_detector_spec = target:root//...->prelude//platforms:default \ | |
| 22 | - target:prelude//...->prelude//platforms:default \ | |
| 23 | - target:toolchains//...->prelude//platforms:default | |
| 24 | - | |
| 25 | -[build] | |
| 26 | - execution_platforms = prelude//platforms:default | |
| 27 | - | |
| 28 | -[project] | |
| 29 | - ignore = .git, web/node_modules, web/.svelte-kit, web/build | |
| deleted file mode 100644 | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | -[cells] | ||
| 2 | - root = . | ||
| 3 | - prelude = prelude | ||
| 4 | - toolchains = toolchains | ||
| 5 | - none = none | ||
| 6 | - | ||
| 7 | -[cell_aliases] | ||
| 8 | - config = prelude | ||
| 9 | - ovr_config = prelude | ||
| 10 | - fbcode = none | ||
| 11 | - fbsource = none | ||
| 12 | - fbcode_macros = none | ||
| 13 | - buck = none | ||
| 14 | - | ||
| 15 | -# Uses a copy of the prelude bundled with the buck2 binary. You can alternatively delete this | ||
| 16 | -# section and vendor a copy of the prelude to the `prelude` directory of your project. | ||
| 17 | -[external_cells] | ||
| 18 | - prelude = bundled | ||
| 19 | - | ||
| 20 | -[parser] | ||
| 21 | - target_platform_detector_spec = target:root//...->prelude//platforms:default \ | ||
| 22 | - target:prelude//...->prelude//platforms:default \ | ||
| 23 | - target:toolchains//...->prelude//platforms:default | ||
| 24 | - | ||
| 25 | -[build] | ||
| 26 | - execution_platforms = prelude//platforms:default | ||
| 27 | - | ||
| 28 | -[project] | ||
| 29 | - ignore = .git, web/node_modules, web/.svelte-kit, web/build | ||
deleted
.buckroot +0 -0 | deleted file mode 100644 |
| deleted file mode 100644 |
modified
.gitignore +2 -2 | @@ -31,8 +31,8 @@ web/node_modules/ | ||
| 31 | 31 | web/build/ |
| 32 | 32 | web/.svelte-kit/ |
| 33 | 33 | |
| 34 | -# buck2 | |
| 35 | -/buck-out | |
| 34 | +# container image tarball | |
| 35 | +/glean-image.tar | |
| 36 | 36 | |
| 37 | 37 | # todo |
| 38 | 38 | todo.md |
| @@ -31,8 +31,8 @@ web/node_modules/ | |||
| 31 | web/build/ | 31 | web/build/ |
| 32 | web/.svelte-kit/ | 32 | web/.svelte-kit/ |
| 33 | 33 | ||
| 34 | -# buck2 | 34 | +# container image tarball |
| 35 | -/buck-out | 35 | +/glean-image.tar |
| 36 | 36 | ||
| 37 | # todo | 37 | # todo |
| 38 | todo.md | 38 | todo.md |
modified
.tangled/workflows/ci.yml +3 -0 | @@ -11,6 +11,9 @@ clone: | ||
| 11 | 11 | skip: false |
| 12 | 12 | depth: 1 |
| 13 | 13 | |
| 14 | +# The repo is a nix flake (flake.nix): `nix build`/`nix develop` reproduce this | |
| 15 | +# environment exactly. The nixery engine has no `nix` of its own, so CI pulls | |
| 16 | +# the same toolchain the devShell declares and drives the Makefile directly. | |
| 14 | 17 | dependencies: |
| 15 | 18 | nixpkgs: |
| 16 | 19 | - go |
| @@ -11,6 +11,9 @@ clone: | |||
| 11 | skip: false | 11 | skip: false |
| 12 | depth: 1 | 12 | depth: 1 |
| 13 | 13 | ||
| 14 | +# The repo is a nix flake (flake.nix): `nix build`/`nix develop` reproduce this | ||
| 15 | +# environment exactly. The nixery engine has no `nix` of its own, so CI pulls | ||
| 16 | +# the same toolchain the devShell declares and drives the Makefile directly. | ||
| 14 | dependencies: | 17 | dependencies: |
| 15 | nixpkgs: | 18 | nixpkgs: |
| 16 | - go | 19 | - go |
deleted
BUCK +0 -30 | deleted file mode 100644 | ||
| @@ -1,30 +0,0 @@ | ||
| 1 | -# A list of available rules and their signatures can be found here: https://buck2.build/docs/prelude/globals/ | |
| 2 | - | |
| 3 | -export_file( | |
| 4 | - name = "build_image_sh", | |
| 5 | - src = "scripts/build-image.sh", | |
| 6 | -) | |
| 7 | - | |
| 8 | -# Builds the glean container image via Nix's dockerTools.streamLayeredImage | |
| 9 | -# (see flake.nix), executed on the remote `nix-vm` builder over SSH -- this | |
| 10 | -# machine has no `nix` installed. The genrule itself stays a thin, uninvolved | |
| 11 | -# wrapper; all the actual rsync/ssh side effects live in build-image.sh. | |
| 12 | -genrule( | |
| 13 | - name = "image", | |
| 14 | - out = "glean-image.tar", | |
| 15 | - # Populates $SRCDIR with a symlink farm mirroring the whole repo tree | |
| 16 | - # (minus buck-out/.git/node_modules) -- build-image.sh rsyncs it to the | |
| 17 | - # remote nix-vm builder, since it needs the full source, not just this | |
| 18 | - # target's declared deps. | |
| 19 | - srcs = glob( | |
| 20 | - ["**/*"], | |
| 21 | - exclude = [ | |
| 22 | - "buck-out/**", | |
| 23 | - ".git/**", | |
| 24 | - "web/node_modules/**", | |
| 25 | - "web/.svelte-kit/**", | |
| 26 | - "web/build/**", | |
| 27 | - ], | |
| 28 | - ), | |
| 29 | - cmd = "chmod +x $(location :build_image_sh) && $(location :build_image_sh) $SRCDIR $OUT", | |
| 30 | -) | |
| deleted file mode 100644 | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | -# A list of available rules and their signatures can be found here: https://buck2.build/docs/prelude/globals/ | ||
| 2 | - | ||
| 3 | -export_file( | ||
| 4 | - name = "build_image_sh", | ||
| 5 | - src = "scripts/build-image.sh", | ||
| 6 | -) | ||
| 7 | - | ||
| 8 | -# Builds the glean container image via Nix's dockerTools.streamLayeredImage | ||
| 9 | -# (see flake.nix), executed on the remote `nix-vm` builder over SSH -- this | ||
| 10 | -# machine has no `nix` installed. The genrule itself stays a thin, uninvolved | ||
| 11 | -# wrapper; all the actual rsync/ssh side effects live in build-image.sh. | ||
| 12 | -genrule( | ||
| 13 | - name = "image", | ||
| 14 | - out = "glean-image.tar", | ||
| 15 | - # Populates $SRCDIR with a symlink farm mirroring the whole repo tree | ||
| 16 | - # (minus buck-out/.git/node_modules) -- build-image.sh rsyncs it to the | ||
| 17 | - # remote nix-vm builder, since it needs the full source, not just this | ||
| 18 | - # target's declared deps. | ||
| 19 | - srcs = glob( | ||
| 20 | - ["**/*"], | ||
| 21 | - exclude = [ | ||
| 22 | - "buck-out/**", | ||
| 23 | - ".git/**", | ||
| 24 | - "web/node_modules/**", | ||
| 25 | - "web/.svelte-kit/**", | ||
| 26 | - "web/build/**", | ||
| 27 | - ], | ||
| 28 | - ), | ||
| 29 | - cmd = "chmod +x $(location :build_image_sh) && $(location :build_image_sh) $SRCDIR $OUT", | ||
| 30 | -) | ||
modified
Makefile +18 -7 | @@ -83,13 +83,24 @@ check: | ||
| 83 | 83 | |
| 84 | 84 | .PHONY: clean |
| 85 | 85 | clean: |
| 86 | - rm -f glean glean.db | |
| 86 | + rm -f glean glean.db $(IMAGE_TAR) | |
| 87 | 87 | rm -rf web/build web/.svelte-kit |
| 88 | 88 | |
| 89 | -.PHONY: docker-build | |
| 90 | -docker-build: | |
| 91 | - docker build -t glean:latest -t atcr.io/julien.rbrt.fr/glean:latest . | |
| 89 | +# Container image: built by Nix (flake.nix `image` output, dockerTools | |
| 90 | +# streamLayeredImage). scripts/build-image.sh builds locally when `nix` is | |
| 91 | +# present and otherwise on the remote builder in $GLEAN_NIX_VM. | |
| 92 | +IMAGE ?= atcr.io/julien.rbrt.fr/glean:latest | |
| 93 | +IMAGE_TAR ?= glean-image.tar | |
| 92 | 94 | |
| 93 | -.PHONY: docker-push | |
| 94 | -docker-push: | |
| 95 | - docker push atcr.io/julien.rbrt.fr/glean:latest | |
| 95 | +.PHONY: image | |
| 96 | +image: | |
| 97 | + scripts/build-image.sh $(IMAGE_TAR) | |
| 98 | + | |
| 99 | +.PHONY: image-load | |
| 100 | +image-load: image | |
| 101 | + docker load < $(IMAGE_TAR) | |
| 102 | + docker tag glean:latest $(IMAGE) | |
| 103 | + | |
| 104 | +.PHONY: image-push | |
| 105 | +image-push: image-load | |
| 106 | + docker push $(IMAGE) | |
| @@ -83,13 +83,24 @@ check: | |||
| 83 | 83 | ||
| 84 | .PHONY: clean | 84 | .PHONY: clean |
| 85 | clean: | 85 | clean: |
| 86 | - rm -f glean glean.db | 86 | + rm -f glean glean.db $(IMAGE_TAR) |
| 87 | rm -rf web/build web/.svelte-kit | 87 | rm -rf web/build web/.svelte-kit |
| 88 | 88 | ||
| 89 | -.PHONY: docker-build | 89 | +# Container image: built by Nix (flake.nix `image` output, dockerTools |
| 90 | -docker-build: | 90 | +# streamLayeredImage). scripts/build-image.sh builds locally when `nix` is |
| 91 | - docker build -t glean:latest -t atcr.io/julien.rbrt.fr/glean:latest . | 91 | +# present and otherwise on the remote builder in $GLEAN_NIX_VM. |
| 92 | +IMAGE ?= atcr.io/julien.rbrt.fr/glean:latest | ||
| 93 | +IMAGE_TAR ?= glean-image.tar | ||
| 92 | 94 | ||
| 93 | -.PHONY: docker-push | 95 | +.PHONY: image |
| 94 | -docker-push: | 96 | +image: |
| 95 | - docker push atcr.io/julien.rbrt.fr/glean:latest | 97 | + scripts/build-image.sh $(IMAGE_TAR) |
| 98 | + | ||
| 99 | +.PHONY: image-load | ||
| 100 | +image-load: image | ||
| 101 | + docker load < $(IMAGE_TAR) | ||
| 102 | + docker tag glean:latest $(IMAGE) | ||
| 103 | + | ||
| 104 | +.PHONY: image-push | ||
| 105 | +image-push: image-load | ||
| 106 | + docker push $(IMAGE) | ||
added
flake.lock +27 -0 | new file mode 100644 | ||
| @@ -0,0 +1,27 @@ | ||
| 1 | +{ | |
| 2 | + "nodes": { | |
| 3 | + "nixpkgs": { | |
| 4 | + "locked": { | |
| 5 | + "lastModified": 1788531059, | |
| 6 | + "narHash": "sha256-hLD4l3QOGBQhkVp3mQ2lJ/YbEi99qUgKapb40KovZ88=", | |
| 7 | + "owner": "NixOS", | |
| 8 | + "repo": "nixpkgs", | |
| 9 | + "rev": "801bef6abd86b91e51083066b83fb354a11fc640", | |
| 10 | + "type": "github" | |
| 11 | + }, | |
| 12 | + "original": { | |
| 13 | + "owner": "NixOS", | |
| 14 | + "ref": "nixos-unstable", | |
| 15 | + "repo": "nixpkgs", | |
| 16 | + "type": "github" | |
| 17 | + } | |
| 18 | + }, | |
| 19 | + "root": { | |
| 20 | + "inputs": { | |
| 21 | + "nixpkgs": "nixpkgs" | |
| 22 | + } | |
| 23 | + } | |
| 24 | + }, | |
| 25 | + "root": "root", | |
| 26 | + "version": 7 | |
| 27 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | +{ | ||
| 2 | + "nodes": { | ||
| 3 | + "nixpkgs": { | ||
| 4 | + "locked": { | ||
| 5 | + "lastModified": 1788531059, | ||
| 6 | + "narHash": "sha256-hLD4l3QOGBQhkVp3mQ2lJ/YbEi99qUgKapb40KovZ88=", | ||
| 7 | + "owner": "NixOS", | ||
| 8 | + "repo": "nixpkgs", | ||
| 9 | + "rev": "801bef6abd86b91e51083066b83fb354a11fc640", | ||
| 10 | + "type": "github" | ||
| 11 | + }, | ||
| 12 | + "original": { | ||
| 13 | + "owner": "NixOS", | ||
| 14 | + "ref": "nixos-unstable", | ||
| 15 | + "repo": "nixpkgs", | ||
| 16 | + "type": "github" | ||
| 17 | + } | ||
| 18 | + }, | ||
| 19 | + "root": { | ||
| 20 | + "inputs": { | ||
| 21 | + "nixpkgs": "nixpkgs" | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + "root": "root", | ||
| 26 | + "version": 7 | ||
| 27 | +} | ||
modified
flake.nix +93 -24 | @@ -7,17 +7,17 @@ | ||
| 7 | 7 | |
| 8 | 8 | outputs = { self, nixpkgs }: |
| 9 | 9 | let |
| 10 | - system = "x86_64-linux"; | |
| 11 | - pkgs = import nixpkgs { inherit system; }; | |
| 12 | - lib = pkgs.lib; | |
| 10 | + systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ]; | |
| 11 | + forEachSystem = f: nixpkgs.lib.genAttrs systems (system: | |
| 12 | + f (import nixpkgs { inherit system; })); | |
| 13 | 13 | |
| 14 | 14 | # --- Go API binary ----------------------------------------------------- |
| 15 | - # Mirrors the Dockerfile's CGO setup: mattn/go-sqlite3 vendors its own | |
| 16 | - # sqlite3 amalgamation, but sqlite-vec-go-bindings' cgo code expects a | |
| 17 | - # plain `sqlite3.h` on the include path. internal/db/include/sqlite3.h | |
| 18 | - # is that header; go-sqlite3's own module dir is added too so the | |
| 19 | - # u_intN_t compat defines line up with the same sqlite3 version. | |
| 20 | - glean = pkgs.buildGoModule { | |
| 15 | + # Mirrors the historical Dockerfile's CGO setup: mattn/go-sqlite3 vendors | |
| 16 | + # its own sqlite3 amalgamation, but sqlite-vec-go-bindings' cgo code | |
| 17 | + # expects a plain `sqlite3.h` on the include path. internal/db/include/ | |
| 18 | + # sqlite3.h is that header; go-sqlite3's own module dir is added too so | |
| 19 | + # the u_intN_t compat defines line up with the same sqlite3 version. | |
| 20 | + mkGlean = pkgs: pkgs.buildGoModule { | |
| 21 | 21 | pname = "glean"; |
| 22 | 22 | version = "0.0.1"; |
| 23 | 23 | src = ./.; |
| @@ -42,7 +42,7 @@ | ||
| 42 | 42 | # normal derivation -- split into a fixed-output "fetch deps" step |
| 43 | 43 | # (network allowed, output hash pinned) and a sandboxed "build" step |
| 44 | 44 | # that only ever sees the already-fetched node_modules. |
| 45 | - webDeps = pkgs.stdenvNoCC.mkDerivation { | |
| 45 | + mkWebDeps = pkgs: pkgs.stdenvNoCC.mkDerivation { | |
| 46 | 46 | pname = "glean-web-deps"; |
| 47 | 47 | version = "0.0.1"; |
| 48 | 48 | src = ./web; |
| @@ -63,7 +63,7 @@ | ||
| 63 | 63 | outputHash = "sha256-q/VJbH1rWCsxf3A3RYb22t2RrtjUm4xCCrCZkLkAFFY="; |
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | - frontend = pkgs.stdenvNoCC.mkDerivation { | |
| 66 | + mkFrontend = pkgs: webDeps: pkgs.stdenvNoCC.mkDerivation { | |
| 67 | 67 | pname = "glean-web"; |
| 68 | 68 | version = "0.0.1"; |
| 69 | 69 | src = ./web; |
| @@ -92,7 +92,7 @@ | ||
| 92 | 92 | # Runs both processes the same way the Dockerfile's CMD did: the Go API |
| 93 | 93 | # in the background on loopback:8080, the SvelteKit Node server in front |
| 94 | 94 | # on $PORT, proxying /api to it. |
| 95 | - entrypoint = pkgs.writeShellScriptBin "glean-entrypoint" '' | |
| 95 | + mkEntrypoint = pkgs: glean: frontend: pkgs.writeShellScriptBin "glean-entrypoint" '' | |
| 96 | 96 | set -euo pipefail |
| 97 | 97 | export GLEAN_ADDR="127.0.0.1:8080" |
| 98 | 98 | export GLEAN_API_URL="http://127.0.0.1:8080" |
| @@ -103,19 +103,88 @@ | ||
| 103 | 103 | ''; |
| 104 | 104 | in |
| 105 | 105 | { |
| 106 | - packages.${system} = { | |
| 107 | - inherit glean frontend webDeps; | |
| 108 | - | |
| 109 | - image = pkgs.dockerTools.streamLayeredImage { | |
| 110 | - name = "glean"; | |
| 111 | - tag = "latest"; | |
| 112 | - contents = [ pkgs.cacert pkgs.tzdata pkgs.dockerTools.fakeNss entrypoint ]; | |
| 113 | - config = { | |
| 114 | - Cmd = [ "${entrypoint}/bin/glean-entrypoint" ]; | |
| 115 | - Env = [ "PORT=3000" ]; | |
| 116 | - ExposedPorts = { "3000/tcp" = { }; }; | |
| 106 | + packages = forEachSystem (pkgs: | |
| 107 | + let | |
| 108 | + glean = mkGlean pkgs; | |
| 109 | + webDeps = mkWebDeps pkgs; | |
| 110 | + frontend = mkFrontend pkgs webDeps; | |
| 111 | + entrypoint = mkEntrypoint pkgs glean frontend; | |
| 112 | + in | |
| 113 | + { | |
| 114 | + inherit glean frontend webDeps; | |
| 115 | + default = glean; | |
| 116 | + } | |
| 117 | + # dockerTools images are Linux-only; on darwin the attribute is simply | |
| 118 | + # absent rather than a derivation that fails at build time. | |
| 119 | + // nixpkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { | |
| 120 | + image = pkgs.dockerTools.streamLayeredImage { | |
| 121 | + name = "glean"; | |
| 122 | + tag = "latest"; | |
| 123 | + contents = [ pkgs.cacert pkgs.tzdata pkgs.dockerTools.fakeNss entrypoint ]; | |
| 124 | + config = { | |
| 125 | + Cmd = [ "${entrypoint}/bin/glean-entrypoint" ]; | |
| 126 | + Env = [ "PORT=3000" ]; | |
| 127 | + ExposedPorts = { "3000/tcp" = { }; }; | |
| 128 | + }; | |
| 117 | 129 | }; |
| 130 | + }); | |
| 131 | + | |
| 132 | + # `nix run .#glean` runs the API; `nix run .#image > glean-image.tar` | |
| 133 | + # streams the docker-archive tarball to stdout. | |
| 134 | + apps = forEachSystem (pkgs: | |
| 135 | + let | |
| 136 | + system = pkgs.stdenv.hostPlatform.system; | |
| 137 | + pkgsFor = self.packages.${system}; | |
| 138 | + in | |
| 139 | + { | |
| 140 | + default = { type = "app"; program = "${pkgsFor.glean}/bin/glean"; }; | |
| 141 | + glean = { type = "app"; program = "${pkgsFor.glean}/bin/glean"; }; | |
| 142 | + } | |
| 143 | + // nixpkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { | |
| 144 | + # streamLayeredImage's output *is* the streaming script. | |
| 145 | + image = { type = "app"; program = "${pkgsFor.image}"; }; | |
| 146 | + }); | |
| 147 | + | |
| 148 | + # Everything the Makefile targets need: Go with cgo, bun/node for the | |
| 149 | + # frontend, and the image/lexicon tooling. | |
| 150 | + devShells = forEachSystem (pkgs: { | |
| 151 | + default = pkgs.mkShell { | |
| 152 | + packages = with pkgs; [ | |
| 153 | + go | |
| 154 | + gcc | |
| 155 | + gnumake | |
| 156 | + bun | |
| 157 | + nodejs_22 | |
| 158 | + sqlite | |
| 159 | + golangci-lint | |
| 160 | + rsync | |
| 161 | + openssh | |
| 162 | + ]; | |
| 163 | + | |
| 164 | + # Same include flags the Makefile computes, so `go build -tags fts5` | |
| 165 | + # works inside the shell without the module cache lookup. | |
| 166 | + shellHook = '' | |
| 167 | + export CGO_ENABLED=1 | |
| 168 | + export CGO_CFLAGS="-I$PWD/internal/db/include -I$(go env GOMODCACHE)/$(grep 'mattn/go-sqlite3' go.mod | awk '{print $1 "@" $2}')" | |
| 169 | + ''; | |
| 118 | 170 | }; |
| 119 | - }; | |
| 171 | + }); | |
| 172 | + | |
| 173 | + # `nix flake check` builds the binary and the frontend and runs the Go | |
| 174 | + # tests. | |
| 175 | + checks = forEachSystem (pkgs: | |
| 176 | + let | |
| 177 | + system = pkgs.stdenv.hostPlatform.system; | |
| 178 | + in | |
| 179 | + { | |
| 180 | + glean = self.packages.${system}.glean; | |
| 181 | + frontend = self.packages.${system}.frontend; | |
| 182 | + tests = (mkGlean pkgs).overrideAttrs (_: { | |
| 183 | + pname = "glean-tests"; | |
| 184 | + doCheck = true; | |
| 185 | + }); | |
| 186 | + }); | |
| 187 | + | |
| 188 | + formatter = forEachSystem (pkgs: pkgs.nixpkgs-fmt); | |
| 120 | 189 | }; |
| 121 | 190 | } |
| @@ -7,17 +7,17 @@ | |||
| 7 | 7 | ||
| 8 | outputs = { self, nixpkgs }: | 8 | outputs = { self, nixpkgs }: |
| 9 | let | 9 | let |
| 10 | - system = "x86_64-linux"; | 10 | + systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ]; |
| 11 | - pkgs = import nixpkgs { inherit system; }; | 11 | + forEachSystem = f: nixpkgs.lib.genAttrs systems (system: |
| 12 | - lib = pkgs.lib; | 12 | + f (import nixpkgs { inherit system; })); |
| 13 | 13 | ||
| 14 | # --- Go API binary ----------------------------------------------------- | 14 | # --- Go API binary ----------------------------------------------------- |
| 15 | - # Mirrors the Dockerfile's CGO setup: mattn/go-sqlite3 vendors its own | 15 | + # Mirrors the historical Dockerfile's CGO setup: mattn/go-sqlite3 vendors |
| 16 | - # sqlite3 amalgamation, but sqlite-vec-go-bindings' cgo code expects a | 16 | + # its own sqlite3 amalgamation, but sqlite-vec-go-bindings' cgo code |
| 17 | - # plain `sqlite3.h` on the include path. internal/db/include/sqlite3.h | 17 | + # expects a plain `sqlite3.h` on the include path. internal/db/include/ |
| 18 | - # is that header; go-sqlite3's own module dir is added too so the | 18 | + # sqlite3.h is that header; go-sqlite3's own module dir is added too so |
| 19 | - # u_intN_t compat defines line up with the same sqlite3 version. | 19 | + # the u_intN_t compat defines line up with the same sqlite3 version. |
| 20 | - glean = pkgs.buildGoModule { | 20 | + mkGlean = pkgs: pkgs.buildGoModule { |
| 21 | pname = "glean"; | 21 | pname = "glean"; |
| 22 | version = "0.0.1"; | 22 | version = "0.0.1"; |
| 23 | src = ./.; | 23 | src = ./.; |
| @@ -42,7 +42,7 @@ | |||
| 42 | # normal derivation -- split into a fixed-output "fetch deps" step | 42 | # normal derivation -- split into a fixed-output "fetch deps" step |
| 43 | # (network allowed, output hash pinned) and a sandboxed "build" step | 43 | # (network allowed, output hash pinned) and a sandboxed "build" step |
| 44 | # that only ever sees the already-fetched node_modules. | 44 | # that only ever sees the already-fetched node_modules. |
| 45 | - webDeps = pkgs.stdenvNoCC.mkDerivation { | 45 | + mkWebDeps = pkgs: pkgs.stdenvNoCC.mkDerivation { |
| 46 | pname = "glean-web-deps"; | 46 | pname = "glean-web-deps"; |
| 47 | version = "0.0.1"; | 47 | version = "0.0.1"; |
| 48 | src = ./web; | 48 | src = ./web; |
| @@ -63,7 +63,7 @@ | |||
| 63 | outputHash = "sha256-q/VJbH1rWCsxf3A3RYb22t2RrtjUm4xCCrCZkLkAFFY="; | 63 | outputHash = "sha256-q/VJbH1rWCsxf3A3RYb22t2RrtjUm4xCCrCZkLkAFFY="; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | - frontend = pkgs.stdenvNoCC.mkDerivation { | 66 | + mkFrontend = pkgs: webDeps: pkgs.stdenvNoCC.mkDerivation { |
| 67 | pname = "glean-web"; | 67 | pname = "glean-web"; |
| 68 | version = "0.0.1"; | 68 | version = "0.0.1"; |
| 69 | src = ./web; | 69 | src = ./web; |
| @@ -92,7 +92,7 @@ | |||
| 92 | # Runs both processes the same way the Dockerfile's CMD did: the Go API | 92 | # Runs both processes the same way the Dockerfile's CMD did: the Go API |
| 93 | # in the background on loopback:8080, the SvelteKit Node server in front | 93 | # in the background on loopback:8080, the SvelteKit Node server in front |
| 94 | # on $PORT, proxying /api to it. | 94 | # on $PORT, proxying /api to it. |
| 95 | - entrypoint = pkgs.writeShellScriptBin "glean-entrypoint" '' | 95 | + mkEntrypoint = pkgs: glean: frontend: pkgs.writeShellScriptBin "glean-entrypoint" '' |
| 96 | set -euo pipefail | 96 | set -euo pipefail |
| 97 | export GLEAN_ADDR="127.0.0.1:8080" | 97 | export GLEAN_ADDR="127.0.0.1:8080" |
| 98 | export GLEAN_API_URL="http://127.0.0.1:8080" | 98 | export GLEAN_API_URL="http://127.0.0.1:8080" |
| @@ -103,19 +103,88 @@ | |||
| 103 | ''; | 103 | ''; |
| 104 | in | 104 | in |
| 105 | { | 105 | { |
| 106 | - packages.${system} = { | 106 | + packages = forEachSystem (pkgs: |
| 107 | - inherit glean frontend webDeps; | 107 | + let |
| 108 | - | 108 | + glean = mkGlean pkgs; |
| 109 | - image = pkgs.dockerTools.streamLayeredImage { | 109 | + webDeps = mkWebDeps pkgs; |
| 110 | - name = "glean"; | 110 | + frontend = mkFrontend pkgs webDeps; |
| 111 | - tag = "latest"; | 111 | + entrypoint = mkEntrypoint pkgs glean frontend; |
| 112 | - contents = [ pkgs.cacert pkgs.tzdata pkgs.dockerTools.fakeNss entrypoint ]; | 112 | + in |
| 113 | - config = { | 113 | + { |
| 114 | - Cmd = [ "${entrypoint}/bin/glean-entrypoint" ]; | 114 | + inherit glean frontend webDeps; |
| 115 | - Env = [ "PORT=3000" ]; | 115 | + default = glean; |
| 116 | - ExposedPorts = { "3000/tcp" = { }; }; | 116 | + } |
| 117 | + # dockerTools images are Linux-only; on darwin the attribute is simply | ||
| 118 | + # absent rather than a derivation that fails at build time. | ||
| 119 | + // nixpkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { | ||
| 120 | + image = pkgs.dockerTools.streamLayeredImage { | ||
| 121 | + name = "glean"; | ||
| 122 | + tag = "latest"; | ||
| 123 | + contents = [ pkgs.cacert pkgs.tzdata pkgs.dockerTools.fakeNss entrypoint ]; | ||
| 124 | + config = { | ||
| 125 | + Cmd = [ "${entrypoint}/bin/glean-entrypoint" ]; | ||
| 126 | + Env = [ "PORT=3000" ]; | ||
| 127 | + ExposedPorts = { "3000/tcp" = { }; }; | ||
| 128 | + }; | ||
| 117 | }; | 129 | }; |
| 130 | + }); | ||
| 131 | + | ||
| 132 | + # `nix run .#glean` runs the API; `nix run .#image > glean-image.tar` | ||
| 133 | + # streams the docker-archive tarball to stdout. | ||
| 134 | + apps = forEachSystem (pkgs: | ||
| 135 | + let | ||
| 136 | + system = pkgs.stdenv.hostPlatform.system; | ||
| 137 | + pkgsFor = self.packages.${system}; | ||
| 138 | + in | ||
| 139 | + { | ||
| 140 | + default = { type = "app"; program = "${pkgsFor.glean}/bin/glean"; }; | ||
| 141 | + glean = { type = "app"; program = "${pkgsFor.glean}/bin/glean"; }; | ||
| 142 | + } | ||
| 143 | + // nixpkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { | ||
| 144 | + # streamLayeredImage's output *is* the streaming script. | ||
| 145 | + image = { type = "app"; program = "${pkgsFor.image}"; }; | ||
| 146 | + }); | ||
| 147 | + | ||
| 148 | + # Everything the Makefile targets need: Go with cgo, bun/node for the | ||
| 149 | + # frontend, and the image/lexicon tooling. | ||
| 150 | + devShells = forEachSystem (pkgs: { | ||
| 151 | + default = pkgs.mkShell { | ||
| 152 | + packages = with pkgs; [ | ||
| 153 | + go | ||
| 154 | + gcc | ||
| 155 | + gnumake | ||
| 156 | + bun | ||
| 157 | + nodejs_22 | ||
| 158 | + sqlite | ||
| 159 | + golangci-lint | ||
| 160 | + rsync | ||
| 161 | + openssh | ||
| 162 | + ]; | ||
| 163 | + | ||
| 164 | + # Same include flags the Makefile computes, so `go build -tags fts5` | ||
| 165 | + # works inside the shell without the module cache lookup. | ||
| 166 | + shellHook = '' | ||
| 167 | + export CGO_ENABLED=1 | ||
| 168 | + export CGO_CFLAGS="-I$PWD/internal/db/include -I$(go env GOMODCACHE)/$(grep 'mattn/go-sqlite3' go.mod | awk '{print $1 "@" $2}')" | ||
| 169 | + ''; | ||
| 118 | }; | 170 | }; |
| 119 | - }; | 171 | + }); |
| 172 | + | ||
| 173 | + # `nix flake check` builds the binary and the frontend and runs the Go | ||
| 174 | + # tests. | ||
| 175 | + checks = forEachSystem (pkgs: | ||
| 176 | + let | ||
| 177 | + system = pkgs.stdenv.hostPlatform.system; | ||
| 178 | + in | ||
| 179 | + { | ||
| 180 | + glean = self.packages.${system}.glean; | ||
| 181 | + frontend = self.packages.${system}.frontend; | ||
| 182 | + tests = (mkGlean pkgs).overrideAttrs (_: { | ||
| 183 | + pname = "glean-tests"; | ||
| 184 | + doCheck = true; | ||
| 185 | + }); | ||
| 186 | + }); | ||
| 187 | + | ||
| 188 | + formatter = forEachSystem (pkgs: pkgs.nixpkgs-fmt); | ||
| 120 | }; | 189 | }; |
| 121 | } | 190 | } |
modified
readme.md +20 -0 | @@ -39,12 +39,32 @@ The system improves over time: as you subscribe to feeds and like articles, Glea | ||
| 39 | 39 | docker run -p 3000:3000 -e GLEAN_SESSION_KEY=changeme -v glean-data:/data atcr.io/julien.rbrt.fr/glean:latest |
| 40 | 40 | ``` |
| 41 | 41 | |
| 42 | +The published image is built from this repo's flake — `nix build .#image` | |
| 43 | +produces a script that streams a docker-archive tarball: | |
| 44 | + | |
| 45 | +```bash | |
| 46 | +nix run .#image > glean-image.tar && docker load < glean-image.tar | |
| 47 | +``` | |
| 48 | + | |
| 49 | +`make image` wraps that, and falls back to building on a remote nix builder | |
| 50 | +(`$GLEAN_NIX_VM`, default `nix-vm`) when the local machine has no `nix`. | |
| 51 | + | |
| 42 | 52 | ### From source |
| 43 | 53 | |
| 44 | 54 | The frontend is a SvelteKit app in `web/`; the Go binary serves a JSON API. |
| 45 | 55 | SvelteKit runs the SSR server (port 3000) and proxies `/api` to the Go API |
| 46 | 56 | (port 8080). |
| 47 | 57 | |
| 58 | +Everything is packaged as a nix flake, so with nix installed: | |
| 59 | + | |
| 60 | +```bash | |
| 61 | +nix build .#glean # the Go binary | |
| 62 | +nix build .#frontend # the built SvelteKit app | |
| 63 | +nix develop # a shell with go, gcc, bun, node and the CGO flags set | |
| 64 | +``` | |
| 65 | + | |
| 66 | +Without nix, the Makefile does the same thing against your own toolchain: | |
| 67 | + | |
| 48 | 68 | ```bash |
| 49 | 69 | git clone https://github.com/anomalyco/glean.git |
| 50 | 70 | cd glean |
| @@ -39,12 +39,32 @@ The system improves over time: as you subscribe to feeds and like articles, Glea | |||
| 39 | docker run -p 3000:3000 -e GLEAN_SESSION_KEY=changeme -v glean-data:/data atcr.io/julien.rbrt.fr/glean:latest | 39 | docker run -p 3000:3000 -e GLEAN_SESSION_KEY=changeme -v glean-data:/data atcr.io/julien.rbrt.fr/glean:latest |
| 40 | ``` | 40 | ``` |
| 41 | 41 | ||
| 42 | +The published image is built from this repo's flake — `nix build .#image` | ||
| 43 | +produces a script that streams a docker-archive tarball: | ||
| 44 | + | ||
| 45 | +```bash | ||
| 46 | +nix run .#image > glean-image.tar && docker load < glean-image.tar | ||
| 47 | +``` | ||
| 48 | + | ||
| 49 | +`make image` wraps that, and falls back to building on a remote nix builder | ||
| 50 | +(`$GLEAN_NIX_VM`, default `nix-vm`) when the local machine has no `nix`. | ||
| 51 | + | ||
| 42 | ### From source | 52 | ### From source |
| 43 | 53 | ||
| 44 | The frontend is a SvelteKit app in `web/`; the Go binary serves a JSON API. | 54 | The frontend is a SvelteKit app in `web/`; the Go binary serves a JSON API. |
| 45 | SvelteKit runs the SSR server (port 3000) and proxies `/api` to the Go API | 55 | SvelteKit runs the SSR server (port 3000) and proxies `/api` to the Go API |
| 46 | (port 8080). | 56 | (port 8080). |
| 47 | 57 | ||
| 58 | +Everything is packaged as a nix flake, so with nix installed: | ||
| 59 | + | ||
| 60 | +```bash | ||
| 61 | +nix build .#glean # the Go binary | ||
| 62 | +nix build .#frontend # the built SvelteKit app | ||
| 63 | +nix develop # a shell with go, gcc, bun, node and the CGO flags set | ||
| 64 | +``` | ||
| 65 | + | ||
| 66 | +Without nix, the Makefile does the same thing against your own toolchain: | ||
| 67 | + | ||
| 48 | ```bash | 68 | ```bash |
| 49 | git clone https://github.com/anomalyco/glean.git | 69 | git clone https://github.com/anomalyco/glean.git |
| 50 | cd glean | 70 | cd glean |
modified
scripts/build-image.sh +20 -16 | @@ -1,29 +1,33 @@ | ||
| 1 | 1 | #!/bin/bash |
| 2 | 2 | # Builds the glean container image with Nix (pkgs.dockerTools.streamLayeredImage, |
| 3 | -# defined in flake.nix) on a remote builder over SSH -- this dev machine has no | |
| 4 | -# `nix` installed, so the actual build can't happen locally. Side-effecting (rsync | |
| 5 | -# + ssh) on purpose: buck2's genrule for :image just calls this script and stays | |
| 6 | -# pure/uninvolved in how the remote build actually happens. | |
| 3 | +# defined in flake.nix). If `nix` is available locally the build happens here; | |
| 4 | +# otherwise the repo is rsync'd to a remote builder over SSH and built there, | |
| 5 | +# with the resulting docker-archive tarball streamed back. | |
| 7 | 6 | # |
| 8 | -# Usage: scripts/build-image.sh <srcdir> <output-tar-path> | |
| 7 | +# Usage: scripts/build-image.sh [output-tar-path] (default: glean-image.tar) | |
| 9 | 8 | set -euo pipefail |
| 10 | -# $SRCDIR is populated by the genrule's `srcs = glob(...)` as a symlink farm | |
| 11 | -# mirroring the repo tree -- NOT this script's own location (which, after | |
| 12 | -# export_file, is a buck-out copy) and NOT $PWD (buck2 runs genrule cmds with | |
| 13 | -# cwd at a srcs scratch dir, not the project root). | |
| 14 | -DIR="$1" | |
| 15 | -OUT="$2" | |
| 9 | + | |
| 10 | +OUT="${1:-glean-image.tar}" | |
| 11 | +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| 12 | + | |
| 13 | +if command -v nix >/dev/null 2>&1; then | |
| 14 | + echo "==> building .#image locally" >&2 | |
| 15 | + nix build "$DIR#image" --print-out-paths --no-link -L | { | |
| 16 | + read -r store_path | |
| 17 | + echo "==> streaming image (docker-archive tar) to $OUT" >&2 | |
| 18 | + "$store_path" > "$OUT" | |
| 19 | + } | |
| 20 | + echo "==> wrote $OUT" >&2 | |
| 21 | + exit 0 | |
| 22 | +fi | |
| 16 | 23 | |
| 17 | 24 | NIX_VM="${GLEAN_NIX_VM:-nix-vm}" |
| 18 | 25 | REMOTE_DIR="${GLEAN_NIX_VM_DIR:-~/builds/glean}" |
| 19 | 26 | |
| 20 | -echo "==> syncing source to $NIX_VM:$REMOTE_DIR" >&2 | |
| 27 | +echo "==> no local nix; syncing source to $NIX_VM:$REMOTE_DIR" >&2 | |
| 21 | 28 | ssh "$NIX_VM" "mkdir -p $REMOTE_DIR" |
| 22 | -# -L dereferences $SRCDIR's symlinks (they point back at buck2's srcs farm, | |
| 23 | -# which doesn't exist on the remote host) so real file content gets copied. | |
| 24 | -rsync -aL --delete \ | |
| 29 | +rsync -a --delete \ | |
| 25 | 30 | --exclude .git \ |
| 26 | - --exclude buck-out \ | |
| 27 | 31 | --exclude web/node_modules \ |
| 28 | 32 | --exclude web/.svelte-kit \ |
| 29 | 33 | --exclude web/build \ |
| @@ -1,29 +1,33 @@ | |||
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | # Builds the glean container image with Nix (pkgs.dockerTools.streamLayeredImage, | 2 | # Builds the glean container image with Nix (pkgs.dockerTools.streamLayeredImage, |
| 3 | -# defined in flake.nix) on a remote builder over SSH -- this dev machine has no | 3 | +# defined in flake.nix). If `nix` is available locally the build happens here; |
| 4 | -# `nix` installed, so the actual build can't happen locally. Side-effecting (rsync | 4 | +# otherwise the repo is rsync'd to a remote builder over SSH and built there, |
| 5 | -# + ssh) on purpose: buck2's genrule for :image just calls this script and stays | 5 | +# with the resulting docker-archive tarball streamed back. |
| 6 | -# pure/uninvolved in how the remote build actually happens. | ||
| 7 | # | 6 | # |
| 8 | -# Usage: scripts/build-image.sh <srcdir> <output-tar-path> | 7 | +# Usage: scripts/build-image.sh [output-tar-path] (default: glean-image.tar) |
| 9 | set -euo pipefail | 8 | set -euo pipefail |
| 10 | -# $SRCDIR is populated by the genrule's `srcs = glob(...)` as a symlink farm | 9 | + |
| 11 | -# mirroring the repo tree -- NOT this script's own location (which, after | 10 | +OUT="${1:-glean-image.tar}" |
| 12 | -# export_file, is a buck-out copy) and NOT $PWD (buck2 runs genrule cmds with | 11 | +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 13 | -# cwd at a srcs scratch dir, not the project root). | 12 | + |
| 14 | -DIR="$1" | 13 | +if command -v nix >/dev/null 2>&1; then |
| 15 | -OUT="$2" | 14 | + echo "==> building .#image locally" >&2 |
| 15 | + nix build "$DIR#image" --print-out-paths --no-link -L | { | ||
| 16 | + read -r store_path | ||
| 17 | + echo "==> streaming image (docker-archive tar) to $OUT" >&2 | ||
| 18 | + "$store_path" > "$OUT" | ||
| 19 | + } | ||
| 20 | + echo "==> wrote $OUT" >&2 | ||
| 21 | + exit 0 | ||
| 22 | +fi | ||
| 16 | 23 | ||
| 17 | NIX_VM="${GLEAN_NIX_VM:-nix-vm}" | 24 | NIX_VM="${GLEAN_NIX_VM:-nix-vm}" |
| 18 | REMOTE_DIR="${GLEAN_NIX_VM_DIR:-~/builds/glean}" | 25 | REMOTE_DIR="${GLEAN_NIX_VM_DIR:-~/builds/glean}" |
| 19 | 26 | ||
| 20 | -echo "==> syncing source to $NIX_VM:$REMOTE_DIR" >&2 | 27 | +echo "==> no local nix; syncing source to $NIX_VM:$REMOTE_DIR" >&2 |
| 21 | ssh "$NIX_VM" "mkdir -p $REMOTE_DIR" | 28 | ssh "$NIX_VM" "mkdir -p $REMOTE_DIR" |
| 22 | -# -L dereferences $SRCDIR's symlinks (they point back at buck2's srcs farm, | 29 | +rsync -a --delete \ |
| 23 | -# which doesn't exist on the remote host) so real file content gets copied. | ||
| 24 | -rsync -aL --delete \ | ||
| 25 | --exclude .git \ | 30 | --exclude .git \ |
| 26 | - --exclude buck-out \ | ||
| 27 | --exclude web/node_modules \ | 31 | --exclude web/node_modules \ |
| 28 | --exclude web/.svelte-kit \ | 32 | --exclude web/.svelte-kit \ |
| 29 | --exclude web/build \ | 33 | --exclude web/build \ |
deleted
toolchains/BUCK +0 -5 | deleted file mode 100644 | ||
| @@ -1,5 +0,0 @@ | ||
| 1 | -load("@prelude//toolchains:demo.bzl", "system_demo_toolchains") | |
| 2 | - | |
| 3 | -# All the default toolchains, suitable for a quick demo or early prototyping. | |
| 4 | -# Most real projects should copy/paste the implementation to configure them. | |
| 5 | -system_demo_toolchains() | |
| deleted file mode 100644 | |||
| @@ -1,5 +0,0 @@ | |||
| 1 | -load("@prelude//toolchains:demo.bzl", "system_demo_toolchains") | ||
| 2 | - | ||
| 3 | -# All the default toolchains, suitable for a quick demo or early prototyping. | ||
| 4 | -# Most real projects should copy/paste the implementation to configure them. | ||
| 5 | -system_demo_toolchains() | ||