Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,26 @@ concurrency:

jobs:
build:
name: Build
runs-on: ubuntu-latest
name: Build (${{ matrix.system }})
strategy:
fail-fast: false
matrix:
include:
- system: x86_64-linux
runner: depot-ubuntu-24.04-8
- system: aarch64-linux
runner: depot-ubuntu-22.04-arm-8
- system: aarch64-darwin
runner: depot-macos-14
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v14
- uses: cachix/cachix-action@v17
with:
name: moonrepo
authToken: ${{ github.event_name != 'pull_request' && secrets.CACHIX_AUTH_TOKEN || '' }}
- name: Check flake
run: nix flake check --no-build --no-write-lock-file
run: nix flake check --no-build --no-write-lock-file --accept-flake-config
- name: Build package
run: nix build .#default -L
run: nix build .#packages.${{ matrix.system }}.default -L --accept-flake-config
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ dockerManifest.json
# AI / agents
.claude/settings.local.json
.claude/worktrees

# Nix
result
result-*
.direnv/
32 changes: 22 additions & 10 deletions docs/NIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ gives contributors on NixOS a dev shell with the right toolchain. It is independ
[nixpkgs `moon` package](https://search.nixos.org/packages?query=moon), which is maintained by
nixpkgs contributors on their own schedule.

Outputs, for `x86_64-linux` and `aarch64-linux`:
Outputs, for `x86_64-linux`, `aarch64-linux`, and `aarch64-darwin`:

- `packages.default` builds the `moon` and `moonx` binaries with shell completions.
- `packages.default` and `packages.moon` build the `moon` and `moonx` binaries with shell
completions.
- `packages.moon-deps` exposes the compiled Cargo dependencies for cache warming.
- `apps.default` runs the `moon` binary.
- `devShells.default` provides the Rust toolchain, `just`, and `cargo-nextest`.

## Releases
Expand All @@ -17,7 +20,7 @@ package and the `meta.changelog` link without touching `flake.nix`.

## Updating inputs

The flake pins nixpkgs, flake-utils, and rust-overlay in `flake.lock`. To move them forward:
The flake pins nixpkgs, flake-utils, rust-overlay, and Crane in `flake.lock`. To move them forward:

```shell
nix flake update
Expand All @@ -42,21 +45,30 @@ gigabytes to the closure.
time. `openssl` plus `OPENSSL_NO_VENDOR` make reqwest link against the system library rather than
compiling a vendored copy, which the `native-tls-vendored` feature would otherwise do.

Cargo dependencies are vendored from `Cargo.lock` through `cargoLock.lockFile`. If moon ever takes a
dependency from a git source, that will need a `cargoLock.outputHashes` entry for it.
Crane vendors Cargo dependencies from `Cargo.lock`. If moon ever takes a dependency from a git
source, Crane will vendor it from the locked revision.

Crane compiles dependencies separately from the final package so application changes can reuse them.
The package source is restricted to Cargo sources and compile-time assets, preventing unrelated files
and version control metadata from invalidating the build.

Tests run with `doCheck = false`. They download Node.js, Bun, Deno, and other toolchains at runtime,
which the Nix sandbox blocks.

## CI

`.github/workflows/nix.yml` runs `nix flake check` and `nix build .#default` when `flake.nix`,
`flake.lock`, `Cargo.toml`, `Cargo.lock`, `rust-toolchain.toml`, or anything under `crates/`
changes. There is no binary cache wired up, so the job compiles moon from source every time.
`.github/workflows/nix.yml` runs `nix flake check` and builds the package for every supported Linux
and macOS system when `flake.nix`, `flake.lock`, `Cargo.toml`, `Cargo.lock`, `rust-toolchain.toml`, or
anything under `crates/` changes. All jobs pull from the public `moonrepo` Cachix cache. Trusted push
and manual runs publish new paths when the repository has a `CACHIX_AUTH_TOKEN` secret; pull requests
remain read-only.

The flake advertises the cache through `nixConfig`. Pass `--accept-flake-config` when running Nix
non-interactively, or configure the cache with `cachix use moonrepo`.

Before pushing a change to the flake, run the same two commands locally:

```shell
nix flake check
nix build .#default
nix flake check --accept-flake-config
nix build .#default --accept-flake-config
```
16 changes: 16 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

229 changes: 154 additions & 75 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,95 +1,174 @@
{
description = "A monorepo build system and task runner for the web ecosystem";

nixConfig = {
extra-substituters = [ "https://moonrepo.cachix.org" ];
extra-trusted-public-keys = [
"moonrepo.cachix.org-1:n4zm4mkV1Eoqck4mQvAhJM28EQwFLU7kW4dEbtAXbD8="
];
};

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
crane.url = "github:ipetkov/crane";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = { self, nixpkgs, flake-utils, rust-overlay }:
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ rust-overlay.overlays.default ];
};

rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;

devRustToolchain = rustToolchain.override {
extensions = [ "rust-src" ];
};

moonVersion = (builtins.fromTOML
(builtins.readFile ./crates/cli/Cargo.toml)).package.version;

nativeDeps = with pkgs; [ pkg-config protobuf ];
buildDeps = with pkgs; [ openssl ];
in
{
packages.default = (pkgs.makeRustPlatform {
cargo = rustToolchain;
rustc = rustToolchain;
}).buildRustPackage {
pname = "moon";
version = moonVersion;
src = ./.;

cargoLock.lockFile = ./Cargo.lock;

nativeBuildInputs = nativeDeps ++ (with pkgs; [
installShellFiles
writableTmpDirAsHomeHook
]);
buildInputs = buildDeps;

env = {
RUSTFLAGS = "-C strip=symbols";
OPENSSL_NO_VENDOR = "1";
outputs =
{
self,
nixpkgs,
flake-utils,
crane,
rust-overlay,
}:
flake-utils.lib.eachSystem
[
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
]
(
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ rust-overlay.overlays.default ];
};

postInstall = pkgs.lib.optionalString
(pkgs.stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages)
(
let emulator = pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages;
in ''
installShellCompletion --cmd moon \
--bash <(${emulator} $out/bin/moon completions --shell bash) \
--fish <(${emulator} $out/bin/moon completions --shell fish) \
--zsh <(${emulator} $out/bin/moon completions --shell zsh)
''
);

doCheck = false;

meta = with pkgs.lib; {
description = "A monorepo build system and task runner for the web ecosystem";
mainProgram = "moon";
homepage = "https://github.com/moonrepo/moon";
changelog = "https://github.com/moonrepo/moon/releases/tag/v${moonVersion}";
license = licenses.mit;
maintainers = [ ];
platforms = platforms.linux;
rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;

devRustToolchain = rustToolchain.override {
extensions = [ "rust-src" ];
};
};

devShells.default = pkgs.mkShell {
nativeBuildInputs = nativeDeps ++ [
devRustToolchain
pkgs.just
pkgs.cargo-nextest
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;

moonVersion = (builtins.fromTOML (builtins.readFile ./crates/cli/Cargo.toml)).package.version;

nativeDeps = with pkgs; [
pkg-config
protobuf
];
buildDeps = with pkgs; [ openssl ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ libiconv ];

cargoFiles = pkgs.lib.fileset.unions [
./Cargo.toml
./Cargo.lock
./.cargo/config.toml
(craneLib.fileset.commonCargoSources ./crates)
];
Comment on lines +59 to 64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional. craneLib.buildDepsOnly internally uses mkDummySrc, which replaces workspace sources and build scripts while compiling external dependencies. The real workspace crates and their compile-time assets are rebuilt by buildPackage using the broader source fileset.

Keeping these assets out of cargoSource prevents template, protobuf, grammar, or embedded WASM changes from unnecessarily invalidating the dependency artifact.

This has been verified with successful full moon-deps builds on Linux and Darwin, followed by a successful full aarch64-darwin package build.

buildInputs = buildDeps;

env = {
OPENSSL_NO_VENDOR = "1";
RUST_SRC_PATH = "${devRustToolchain}/lib/rustlib/src/rust/library";
cargoSource = pkgs.lib.fileset.toSource {
root = ./.;
fileset = cargoFiles;
};

source = pkgs.lib.fileset.toSource {
root = ./.;
fileset = pkgs.lib.fileset.unions [
cargoFiles
./crates/daemon-proto/proto
./crates/config-loader/res
./crates/docker/templates/Dockerfile.tera
./crates/app/src/commands/graph/html.tera
./crates/query/src/mql.pest
];
};

commonArgs = {
pname = "moon";
version = moonVersion;
src = source;

cargoExtraArgs = "--locked --package moon_cli --bins";
strictDeps = true;
doCheck = false;

nativeBuildInputs = nativeDeps;
buildInputs = buildDeps;

env = {
RUSTFLAGS = "-C strip=symbols";
OPENSSL_NO_VENDOR = "1";
};
};

cargoArtifacts = craneLib.buildDepsOnly (
commonArgs
// {
src = cargoSource;
buildPhaseCargoCommand = "cargo build --release --locked --package moon_cli --bins";
}
);

moon = craneLib.buildPackage (
commonArgs
// {
inherit cargoArtifacts;

nativeBuildInputs =
nativeDeps
++ (with pkgs; [
installShellFiles
writableTmpDirAsHomeHook
]);

postInstall =
pkgs.lib.optionalString (pkgs.stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages)
(
let
emulator = pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages;
in
''
installShellCompletion --cmd moon \
--bash <(${emulator} $out/bin/moon completions --shell bash) \
--fish <(${emulator} $out/bin/moon completions --shell fish) \
--zsh <(${emulator} $out/bin/moon completions --shell zsh)
''
);

meta = with pkgs.lib; {
description = "A monorepo build system and task runner for the web ecosystem";
mainProgram = "moon";
homepage = "https://github.com/moonrepo/moon";
changelog = "https://github.com/moonrepo/moon/releases/tag/v${moonVersion}";
license = licenses.mit;
maintainers = [ ];
platforms = platforms.linux ++ [ "aarch64-darwin" ];
};
}
);
in
{
packages = {
inherit moon;
moon-deps = cargoArtifacts;
default = moon;
};

apps.default = {
type = "app";
program = "${moon}/bin/moon";
};

devShells.default = pkgs.mkShell {
nativeBuildInputs = nativeDeps ++ [
devRustToolchain
pkgs.just
pkgs.cargo-nextest
];
buildInputs = buildDeps;

env = {
OPENSSL_NO_VENDOR = "1";
RUST_SRC_PATH = "${devRustToolchain}/lib/rustlib/src/rust/library";
};
};
};
}
);
}
);
}
Loading