diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command new file mode 100755 index 0000000..ed314ea --- /dev/null +++ b/.buildkite/hooks/pre-command @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Buildkite pre-command hook: install Determinate Nix on the agent +# before each command step runs. We rely on Nix (with flakes) for our +# build environment, so every fresh agent needs it bootstrapped. +# +# Determinate's installer enables flakes and `nix-command` by default +# and is more reliable in CI than the upstream installer, so we don't +# need to stage a custom nix.conf. + +set -eu + +# Install Nix without touching the agent's init system. The `?ci=buildkite` +# query param is informational; it lets Determinate tag installer telemetry. +curl --proto '=https' --tlsv1.2 -sSf -L \ + "https://install.determinate.systems/nix?ci=buildkite" \ + | sh -s -- install linux --no-confirm --init none + +# Start the Determinate daemon ourselves since we passed `--init none`. +# Point the Nix client at the daemon for the rest of this shell. +nohup /usr/local/bin/determinate-nixd daemon & +export NIX_REMOTE=daemon + +# Wait for the daemon to become responsive before handing control back +# to the command step. +while ! determinate-nixd status >/dev/null 2>&1; do + sleep 0.1 +done + +# Put `nix` on PATH for the command step. Buildkite sources hooks, so +# this export propagates. With `--init none` we never edited any shell +# profile, so we have to do it ourselves. The default profile holds the +# `nix` binary; the per-user profile holds anything `nix profile install` +# adds later. +export PATH="/nix/var/nix/profiles/default/bin:$HOME/.nix-profile/bin:$PATH" diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 0000000..7245941 --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,33 @@ +# In-repo Buildkite pipeline. The Buildkite-side pipeline only needs +# one step that does `buildkite-agent pipeline upload`; everything +# real lives here. + +steps: + - label: ":nix: format check" + # `nix fmt` dispatches to the flake's `formatter` output (alejandra). + # `--` forwards `--check` to alejandra, which exits non-zero on any + # file that would be reformatted so the build fails instead of + # silently rewriting files. + command: nix fmt -- --check . + + - label: ":go: test" + # Run the full Go test suite inside the flake's dev shell so the + # toolchain (go, cgo deps for mattn/go-sqlite3) matches what the + # package build uses. `nix develop -c` runs the given command in the + # default devShell without dropping into an interactive shell. + command: nix develop -c go test ./... + + - label: ":nix: package build & smoke" + # Build the `tack` flake package and smoke-test the resulting + # binary. This catches regressions that `go test` won't, such as a + # stale `vendorHash`, broken cgo wiring for mattn/go-sqlite3, or a + # linker failure inside the Nix sandbox. + # + # `tack -h` is the cheapest possible "did the binary load?" check: + # `flag.Parse()` runs before any required env-var validation, prints + # usage, and exits 0 — proving the binary was produced, links, and + # can execute Go init without spinning up the HTTP server, store, + # or jetstream consumer. + command: | + nix build .#tack + ./result/bin/tack -h diff --git a/.tangled/workflows/test.yml b/.tangled/workflows/test.yml new file mode 100644 index 0000000..c0fdb86 --- /dev/null +++ b/.tangled/workflows/test.yml @@ -0,0 +1,12 @@ +when: + - event: ["push"] + branch: ["main"] + - event: ["pull_request"] + branch: ["main"] + +engine: nixery + +tack: + buildkite: + org: mitchellh + pipeline: tack diff --git a/flake.nix b/flake.nix index 895ca91..4f0f8e7 100644 --- a/flake.nix +++ b/flake.nix @@ -12,8 +12,8 @@ flake-utils, ... }: - # Per-system outputs (packages, apps, devShells). nixosModules is - # system-independent and is merged in below. + # Per-system outputs (packages, apps, devShells). nixosModules is + # system-independent and is merged in below. flake-utils.lib.eachDefaultSystem ( system: let pkgs = nixpkgs.legacyPackages.${system}; @@ -39,6 +39,10 @@ env.CGO_ENABLED = "1"; }; in { + # `nix fmt` formats the tree with alejandra. CI pins this same + # binary via `nix run nixpkgs#alejandra` for the format check. + formatter = pkgs.alejandra; + devShells.default = pkgs.mkShell { packages = [ pkgs.go diff --git a/nix/modules/tack.nix b/nix/modules/tack.nix index 11f3a11..8b5baea 100644 --- a/nix/modules/tack.nix +++ b/nix/modules/tack.nix @@ -1,4 +1,4 @@ -# NixOS module for the tack spindle. +# NixOS module for the tack spindle. { config, lib, @@ -127,7 +127,7 @@ in ] ++ optional cfg.dev "TACK_DEV=1" ++ optional (cfg.buildkite.org != null) - "TACK_BUILDKITE_ORG=${cfg.buildkite.org}"; + "TACK_BUILDKITE_ORG=${cfg.buildkite.org}"; ExecStart = "${cfg.package}/bin/tack -addr ${cfg.listenAddr}"; Restart = "always";