···11+#!/bin/sh
22+#
33+# Buildkite pre-command hook: install Determinate Nix on the agent
44+# before each command step runs. We rely on Nix (with flakes) for our
55+# build environment, so every fresh agent needs it bootstrapped.
66+#
77+# Determinate's installer enables flakes and `nix-command` by default
88+# and is more reliable in CI than the upstream installer, so we don't
99+# need to stage a custom nix.conf.
1010+1111+set -eu
1212+1313+# Install Nix without touching the agent's init system. The `?ci=buildkite`
1414+# query param is informational; it lets Determinate tag installer telemetry.
1515+curl --proto '=https' --tlsv1.2 -sSf -L \
1616+ "https://install.determinate.systems/nix?ci=buildkite" \
1717+ | sh -s -- install linux --no-confirm --init none
1818+1919+# Start the Determinate daemon ourselves since we passed `--init none`.
2020+# Point the Nix client at the daemon for the rest of this shell.
2121+nohup /usr/local/bin/determinate-nixd daemon &
2222+export NIX_REMOTE=daemon
2323+2424+# Wait for the daemon to become responsive before handing control back
2525+# to the command step.
2626+while ! determinate-nixd status >/dev/null 2>&1; do
2727+ sleep 0.1
2828+done
2929+3030+# Put `nix` on PATH for the command step. Buildkite sources hooks, so
3131+# this export propagates. With `--init none` we never edited any shell
3232+# profile, so we have to do it ourselves. The default profile holds the
3333+# `nix` binary; the per-user profile holds anything `nix profile install`
3434+# adds later.
3535+export PATH="/nix/var/nix/profiles/default/bin:$HOME/.nix-profile/bin:$PATH"
+33
.buildkite/pipeline.yml
···11+# In-repo Buildkite pipeline. The Buildkite-side pipeline only needs
22+# one step that does `buildkite-agent pipeline upload`; everything
33+# real lives here.
44+55+steps:
66+ - label: ":nix: format check"
77+ # `nix fmt` dispatches to the flake's `formatter` output (alejandra).
88+ # `--` forwards `--check` to alejandra, which exits non-zero on any
99+ # file that would be reformatted so the build fails instead of
1010+ # silently rewriting files.
1111+ command: nix fmt -- --check .
1212+1313+ - label: ":go: test"
1414+ # Run the full Go test suite inside the flake's dev shell so the
1515+ # toolchain (go, cgo deps for mattn/go-sqlite3) matches what the
1616+ # package build uses. `nix develop -c` runs the given command in the
1717+ # default devShell without dropping into an interactive shell.
1818+ command: nix develop -c go test ./...
1919+2020+ - label: ":nix: package build & smoke"
2121+ # Build the `tack` flake package and smoke-test the resulting
2222+ # binary. This catches regressions that `go test` won't, such as a
2323+ # stale `vendorHash`, broken cgo wiring for mattn/go-sqlite3, or a
2424+ # linker failure inside the Nix sandbox.
2525+ #
2626+ # `tack -h` is the cheapest possible "did the binary load?" check:
2727+ # `flag.Parse()` runs before any required env-var validation, prints
2828+ # usage, and exits 0 — proving the binary was produced, links, and
2929+ # can execute Go init without spinning up the HTTP server, store,
3030+ # or jetstream consumer.
3131+ command: |
3232+ nix build .#tack
3333+ ./result/bin/tack -h
···1212 flake-utils,
1313 ...
1414 }:
1515- # Per-system outputs (packages, apps, devShells). nixosModules is
1616- # system-independent and is merged in below.
1515+ # Per-system outputs (packages, apps, devShells). nixosModules is
1616+ # system-independent and is merged in below.
1717 flake-utils.lib.eachDefaultSystem (
1818 system: let
1919 pkgs = nixpkgs.legacyPackages.${system};
···3939 env.CGO_ENABLED = "1";
4040 };
4141 in {
4242+ # `nix fmt` formats the tree with alejandra. CI pins this same
4343+ # binary via `nix run nixpkgs#alejandra` for the format check.
4444+ formatter = pkgs.alejandra;
4545+4246 devShells.default = pkgs.mkShell {
4347 packages = [
4448 pkgs.go