Skip to content

chore(nix): add development shell and CI#2128

Open
lloeki wants to merge 15 commits into
mainfrom
lloeki/nix
Open

chore(nix): add development shell and CI#2128
lloeki wants to merge 15 commits into
mainfrom
lloeki/nix

Conversation

@lloeki

@lloeki lloeki commented Jun 16, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Adds a Nix flake development shell to the repository, with a CI workflow that exercises it.

  • flake.nix / flake.lock: a devshell providing the Rust toolchain (rustc, cargo, rustfmt, clippy), cbindgen, cmake and autotools. The Rust toolchain is pinned via the oxalica/rust-overlay input reading the existing rust-toolchain.toml, so the devshell tracks the same channel as CI and rustup.
  • .github/workflows/nix.yml: enters the devshell and builds the workspace on Linux (x86_64, aarch64) and macOS (arm64), mirroring the Nix CI already present in dd-trace-rb and libdatadog-rb.
  • CODEOWNERS: co-owns the Nix files and workflow with the Nix guild.

Motivation

Contributors using Nix previously kept these files locally and unshared, with the Rust version floating with the nixpkgs channel (currently 1.91.1) rather than matching the toolchain libdatadog is built with. Committing a pinned devshell gives a reproducible, low-setup environment, and the CI guard keeps it from bit-rotting.

Additional Notes

The pin derives from rust-toolchain.toml (single source of truth), so a future MSRV bump updates the devshell automatically.

AI was used to accelerate implementation; all code was reviewed and understood.

How to test the change?

nix develop --command cargo build --workspace --exclude builder, and confirm nix develop --command rustc --version reports the channel from rust-toolchain.toml. CI runs the same build across the three platforms.

lloeki added 3 commits June 16, 2026 15:27
Provide a Nix flake devshell so contributors can get a reproducible
environment (rustc, cargo, rustfmt, clippy, cbindgen, cmake, autotools)
without manual setup. The Rust toolchain is read from the existing
rust-toolchain.toml via the rust-overlay input, so the devshell tracks
the same channel as CI and rustup.
Mirror the CODEOWNERS convention already used in dd-trace-rb and
libdatadog-rb so the Nix guild reviews changes to the development shell
alongside the existing tooling owners.
Add a GitHub Actions workflow that enters the Nix development shell and
builds the workspace on Linux (x86_64, aarch64) and macOS (arm64),
mirroring the Nix CI in dd-trace-rb and libdatadog-rb. This guards the
devshell against bit-rot so contributors relying on it keep a working,
toolchain-pinned environment. Co-own the workflow with the Nix guild.
@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jun 16, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 73.77% (+0.71%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: cfb9257 | Docs | Datadog PR Page | Give us feedback!

The stdenv cc-wrapper injects -D_FORTIFY_SOURCE, which glibc rejects when
compiling without optimization. spawn_worker's build script compiles its
trampoline.c at -O0 with -Werror, turning the fortify #warning into a
hard error and breaking a workspace build inside the devshell. Disable
fortify hardening so these C build steps succeed.
@lloeki

lloeki commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: efca305b12

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/nix.yml
@lloeki lloeki marked this pull request as ready for review June 16, 2026 14:19
@lloeki lloeki requested a review from a team as a code owner June 16, 2026 14:19
Comment thread flake.nix

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: efca305b12

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread flake.nix
@dd-octo-sts

dd-octo-sts Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 83.68 MB 83.68 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.70 MB 7.70 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.34 MB 10.34 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 94.78 MB 94.78 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 24.83 MB 24.83 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 180.88 MB 180.90 MB +0% (+16.00 KB) 👌
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 925.05 MB 925.05 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.09 MB 8.09 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 23.94 MB 23.94 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 47.78 MB 47.78 MB 0% (0 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.52 MB 21.52 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 184.88 MB 184.90 MB +0% (+16.00 KB) 👌
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 918.00 MB 918.00 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.24 MB 6.24 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.66 MB 25.66 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.41 MB 45.41 MB 0% (0 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 74.60 MB 74.60 MB 0% (0 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.58 MB 8.58 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 90.02 MB 90.02 MB 0% (0 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.44 MB 10.44 MB 0% (0 B) 👌

Comment thread .github/workflows/nix.yml Outdated
Comment thread .github/workflows/nix.yml
platform:
- os: darwin
cpu: arm64
base: macos-15 # always arm64-darwin

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is macos strictly needed? I ask because macos runners are scarce and ocuppying one for this might hurt us a bit in terms of merge times

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, it guarantees that it consistently works across OSes for any dev that uses Nix on a macOS machine

Should be mostly mitigated by conditional running mentioned above.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You could also use a concurrency group (example from our test workflow)and cancel in progress if you don't need commit level granularity.

Not necessarily a hill I want to die on, but I think using a concurrency group is a good compromise between getting signal that something broke and not potentially backing up the MergeQueue waiting for a macOS runner for a workflow that doesn't indicate an actual code issue.

lloeki added 3 commits June 17, 2026 15:04
The devshell is a rarely-changing safeguard, so gating every pull request
on it is unnecessary. Drop the blanket pull_request trigger and keep the
workflow on main and mq-working-branch-* pushes; devshell breakage will
still surface in the main pipeline.
Keep the devshell guard responsive to changes that actually affect it:
run on pull requests that modify the Nix files (paths mirror the Nix
CODEOWNERS entries), rust-toolchain.toml (read by the flake), or this
workflow.
Add a non-default `.#nightly` devshell built from ./nightly-toolchain.toml
(via rust-overlay's fromRustupToolchainFile), for the workflows that need
a nightly compiler. Factor the shared shell definition into mkDevShell so
default and nightly only differ by toolchain.
@lloeki lloeki requested a review from hoolioh June 17, 2026 13:11
Comment thread .github/CODEOWNERS
fuzz/ @DataDog/chaos-platform

# Nix
*.nix @DataDog/nix-guild @DataDog/apm-common-components-core

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TIL there's a Nix guild 😄

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's a small but growing group. Join us at #nix!

Comment thread flake.nix
hardeningDisable = [ "fortify" "fortify3" ];

buildInputs = [
rust # rustc + cargo + rustfmt + clippy, pinned via toolchain file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One slightly annoying thing here is that we need to cargo fmt with nightly. I wonder if we should provide a nightly toolchain pinned as well, or even maybe propose a "libdd-fmt" alias that uses the right nightly toolchain under the hood. It's a detail though, and could be worked out in a follow up PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Coincidentally I just added a nightly toolchain as .#nightly.

Maybe we can even work out something that would have a closure over the nightly toolchain as an internal dependency for a nightly-based cargo fmt - and only that - to be exposed. That's exactly the kind of thing Nix can solve.

Indeed probably for a later PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To clarify usage as of today:

  • nix develop .#nightly to enter a shell with the nightly toolchain
  • nix develop .#nightly -c cargo fmt to run its nightly cargo right away

Comment thread flake.nix
@yannham

yannham commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Do you know what are those Test Nix / test report jobs, or where they are coming from? They have no logs and a Windows one doesn't make sense

image

@lloeki

lloeki commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

Do you know what are those Test Nix / test report jobs, or where they are coming from? They have no logs and a Windows one doesn't make sense

image

Interesting. I'm not sure, let me look that up.

@ekump ekump left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Left a few nit comments, but I'm not a nix guy so not sure how relevant they are.

LGTM after we add a little bit of documentation and add a concurrency group for the workflow.

Comment thread flake.nix Outdated
# hardening in the shell so those builds succeed.
hardeningDisable = [ "fortify" "fortify3" ];

buildInputs = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Should this be nativeBuildInputs since they are build-time host tools?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

True-ish: it's only really relevant for cross-compilation so it doesn't really matter for devshells as they are always running on the host platform, although there's some subtlety like xdg paths and such.

I'll amend for the sake of good practice.

Comment thread flake.nix
flake-utils.url = "github:numtide/flake-utils";

# backwards compatibility with nix-build and nix-shell
flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Is this necessary? shell.nix or default.nix aren't included in this repo (maybe they will be in the future?).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ha, I forgot to add the shims, will add.

Comment thread .github/workflows/nix.yml
platform:
- os: darwin
cpu: arm64
base: macos-15 # always arm64-darwin

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You could also use a concurrency group (example from our test workflow)and cancel in progress if you don't need commit level granularity.

Not necessarily a hill I want to die on, but I think using a concurrency group is a good compromise between getting signal that something broke and not potentially backing up the MergeQueue waiting for a macOS runner for a workflow that doesn't indicate an actual code issue.

Comment thread .github/workflows/nix.yml Outdated

permissions:
contents: read
id-token: write

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this necessary? could you get away with contents: read?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think it would be fine without it indeed.

Comment thread .github/workflows/nix.yml
@@ -0,0 +1,69 @@
name: Test Nix

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we add documentation (maybe here and / or inline in this file) with instructions on what to do if there is a failure? I suspect it'll only come up on MSRV bumps.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not too sure what the expectation of the doc would be: some basic usage examples to onboard the Nix-unaware / a LLM agent maybe?

I did not want to be too invasive as a first PR but seems like you folks are quite on board with this so I feel like the doc you pointed to would be a good place. Will add.

@lloeki lloeki left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for the astute reviews! Will address.

Comment thread flake.nix
hardeningDisable = [ "fortify" "fortify3" ];

buildInputs = [
rust # rustc + cargo + rustfmt + clippy, pinned via toolchain file

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To clarify usage as of today:

  • nix develop .#nightly to enter a shell with the nightly toolchain
  • nix develop .#nightly -c cargo fmt to run its nightly cargo right away

Comment thread flake.nix Outdated
# hardening in the shell so those builds succeed.
hardeningDisable = [ "fortify" "fortify3" ];

buildInputs = [

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

True-ish: it's only really relevant for cross-compilation so it doesn't really matter for devshells as they are always running on the host platform, although there's some subtlety like xdg paths and such.

I'll amend for the sake of good practice.

Comment thread flake.nix
flake-utils.url = "github:numtide/flake-utils";

# backwards compatibility with nix-build and nix-shell
flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ha, I forgot to add the shims, will add.

Comment thread .github/workflows/nix.yml Outdated

permissions:
contents: read
id-token: write

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think it would be fine without it indeed.

Comment thread .github/workflows/nix.yml
Comment thread .github/workflows/nix.yml
@@ -0,0 +1,69 @@
name: Test Nix

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not too sure what the expectation of the doc would be: some basic usage examples to onboard the Nix-unaware / a LLM agent maybe?

I did not want to be too invasive as a first PR but seems like you folks are quite on board with this so I feel like the doc you pointed to would be a good place. Will add.

Comment thread .github/CODEOWNERS
fuzz/ @DataDog/chaos-platform

# Nix
*.nix @DataDog/nix-guild @DataDog/apm-common-components-core

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's a small but growing group. Join us at #nix!

@lloeki

lloeki commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

Ok so I looked up the test report ones:

  • they're not emitted by nix.yml
  • they apparently come from mikepenz/action-junit-report in test.yml (from check_name being [${{ matrix.platform }}:${{ steps.rust-version.outputs.version }}] test report + the matrix including windows)
  • why GitHub decided they should appear under Test Nix, that I couldn't figure out

Comment thread .github/workflows/nix.yml
Comment on lines +4 to +7
push:
branches:
- main
- mq-working-branch-*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
push:
branches:
- main
- mq-working-branch-*
# Nightly safeguard: catches devshell drift from changes that don't match the
# paths above (e.g. a dependency or build-script change that needs new native
# tooling). Scheduled runs only fire from the default branch, against its HEAD.
schedule:
- cron: "0 4 * * *" # daily at 04:00 UTC

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of triggering it in every PR I think it would be better to have a nightly schedule. That way we can save some capacity for the actual pipelines.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But wouldn't you want to check tings on PRs that change Nix files at least?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Definitely.

As is it's not going to trigger in every PR anyway, only those that change nix files or that have an impact on nix (the toolchain files).

The schedule can be nice though as a sanity check for when those don't change often.

@lloeki lloeki requested a review from a team as a code owner June 18, 2026 13:50
Comment thread flake.nix

{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/release-25.11";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the 26.05 channel is the latest stable, why not use it instead ?
And what about using unstable instead ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unstable is nice to have the very latest version, but I think you won't hit the binary cache, which might mean a lot of full local rebuilds from source. The latest stable makes sense though 👍

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does unstable really makes a difference with binary cache ? I never hit that issue personally.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unstable is actually cached, but it moves fast. I vaguely remember situations such as user A updates the flake.lock, 1 month passes, new user B checks the project out from scratch and inherits the same flake.lock, but stuff isn't in the unstable cache anymore. If you are the one updating you shouldn't have issues ofc, because when you check out the package, they are the most recent available and thus in cache. I think. I am not sure. Both latest stable and unstable are probably reasonable.

Another reason could be if you run NixOS, you usually target a specific release, and you probably don't want to duplicate many versions of core packages (the stable and the unstable one).

@Eldolfin

Copy link
Copy Markdown
Contributor

Hey I wanted to suggest many small changes (mostly styling/preferences), I created a stacked PR instead because it got too large

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants