Skip to content

feat: provide a flake.nix to build with Nix - #104

Draft
vincentbernat wants to merge 2 commits into
tattoy-org:mainfrom
vincentbernat:feature/nix-flake
Draft

feat: provide a flake.nix to build with Nix#104
vincentbernat wants to merge 2 commits into
tattoy-org:mainfrom
vincentbernat:feature/nix-flake

Conversation

@vincentbernat

@vincentbernat vincentbernat commented Jun 14, 2025

Copy link
Copy Markdown

One can use nix build ..

Unfortunately, it does not work as one of the dependency is referencing a file from another workspace and I lack any experience with Rust or Nix packaging for Rust, so I don't know how to fix that.

Also, I made it Linux-only, but it would be possible to add support for MacOS.

This would help for #100.

@tombh

tombh commented Jun 14, 2025

Copy link
Copy Markdown
Collaborator

Thank you. I guess the files in another workspace you're referring to are one of or both the termwiz and wezterm-term dependencies? If so then this would be related to #94.

So once this is ready, would we add it on the downloads page? https://tattoy.sh/download

@vincentbernat

Copy link
Copy Markdown
Author

Yes, you'll get another way to run tattoy, notably nix run github:tattoy-org/tattoy. It would also be possible to integrate it into nixpkgs.

@vincentbernat

Copy link
Copy Markdown
Author

Note that the error I get is:

       >    Compiling wezterm-term v0.1.0 (https://github.com/tombh/wezterm.git?rev=ec9005d59f6ab92d9b76d3b9947c8582259cf76e#ec9005d5)
       > error: couldn't read `/build/cargo-vendor-dir/wezterm-term-0.1.0/src/terminalstate/../../../termwiz/data/wezterm`: No such file or directory (os error 2)
       >   --> /build/cargo-vendor-dir/wezterm-term-0.1.0/src/terminalstate/mod.rs:40:20
       >    |
       > 40 |         let data = include_bytes!("../../../termwiz/data/wezterm");
       >    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       >    |
       >    = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
       >
       > error: could not compile `wezterm-term` (lib) due to 1 previous error

@tombh

tombh commented Jul 2, 2025

Copy link
Copy Markdown
Collaborator

Is there a convenient command to try this out? I think it should be fixed now if running from latest main.

@vincentbernat

Copy link
Copy Markdown
Author

If you have Nix, you can just run nix build. If you didn't enable flakes, this is nix --extra-experimental-features "nix-command flakes" build.

I have rebased to make it work, but some tests are failing:

       > nfig-dir /build/.tmp31ydd3 --log-path ./tests.log
       > ^[[201~
       > bash: $'\E[200~unset': command not found
       > bash-5.2$
       >
       >
       > thread 'e2e::resizing' panicked at crates/tests/e2e_tests.rs:139:61:
       > called `Result::unwrap()` on an `Err` value: Whatever { message: "'▀' not found after 1000 milliseconds.", source: None }
       >
       >
       > failures:
       >     e2e::auto_text_contrast
       >     e2e::background_command
       >     e2e::bad_plugin
       >     e2e::basic_interactivity
       >     e2e::keybind_toggle_renderer
       >     e2e::minimap
       >     e2e::palette_to_true_colour
       >     e2e::plugins
       >     e2e::resizing
       >     e2e::scrolling
       >
       > test result: FAILED. 0 passed; 10 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.63s

Maybe we could just not run e2e tests if they require a working terminal?

@tombh

tombh commented Jul 3, 2025

Copy link
Copy Markdown
Collaborator

I got it to build and saw the same error as you! Okay so that error is simply because the unset command is missing and I fixed that by adding bash to the nativeBuildInputs array.

Now I see a new error when it runs the tests. Some of the tests require the debug build of Tattoy, as they're end to end tests that test the CLI application itself. Do you know if its possible to run cargo build --all before the tests are run?

@tombh

tombh commented Jul 3, 2025

Copy link
Copy Markdown
Collaborator

Oh BTW the end to end tests don't need a working terminal, they're all run in memory.

@vincentbernat

Copy link
Copy Markdown
Author

I have tried checkType = "debug"; but that's not enough (the binary is not built). So, I have just addded cargo build --all as a preCheck hook. I have pushed a few other fixes but I still get some errors in the e2e tests.

@tombh

tombh commented Jul 7, 2025

Copy link
Copy Markdown
Collaborator

Ok step by step! I see those errors too:

last 25 log lines:
       >
       >
       > thread 'e2e::bad_plugin' panicked at crates/tests/e2e_tests.rs:421:14:
       > called `Result::unwrap()` on an `Err` value: Whatever { message: "'Something went wrong' not found after 500 milliseconds.", source: None }
       >
       > ---- e2e::basic_interactivity stdout ----
       >
       > thread 'e2e::basic_interactivity' panicked at crates/tests/e2e_tests.rs:143:13:
       > Random walker didn't move in a 1000 iterations.
       >
       >
       > failures:
       >     e2e::auto_text_contrast
       >     e2e::background_command
       >     e2e::bad_plugin
       >     e2e::basic_interactivity
       >     e2e::minimap
       >     e2e::palette_to_true_colour
       >     e2e::plugins
       >     e2e::resizing
       >     e2e::scrolling
       >
       > test result: FAILED. 1 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.32s

It looks like basically all the e2e tests are failing, so it's probably something simple but underlying. I tried nix shell as well to see if I could interactively investigate, but it still runs the tests, and fails. So I added doCheck = false and then it does compile but I don't seem to be in the same environment that built the binary. Do you know if there's a way to do that?

@vincentbernat

Copy link
Copy Markdown
Author

You should have a nix log command to see more logs.

Use nix develop, not nix shell. The first one give you a shell with the development environment while the second one is giving you a shell where the package is installed.

@tombh

tombh commented Jul 8, 2025

Copy link
Copy Markdown
Collaborator

Thanks for that. I've discovered something interesting: the tests pass with cargo nextest run but fail with cargo test. It's the same outside of Nix too. In theory they should be the same, but clearly they're not, so it'd probably be useful for me to know why anyway. So we could either change the Nix test command, or even just ignore them altogether seeing as they're a requirement for PRs and releasing.

So thanks to those commands I was also able to run tattoy. And I see it mostly works, but there's some unexpected bash output: "bash: shopt: progcomp: invalid shell option name".

Comment thread flake.nix Outdated
@tombh

tombh commented Jul 27, 2025

Copy link
Copy Markdown
Collaborator

There's actually a proper nixpkg in the works now! NixOS/nixpkgs#428828

Will that replace this flake here or be based on it? Or are there other good reasons to have both?

@vincentbernat

Copy link
Copy Markdown
Author

We can keep both. The one here is useful for people wanting the latest version. The one in nixpkgs will be used by most users.

@vincentbernat

Copy link
Copy Markdown
Author

I have pushed an update for you to tweak. I don't know exactly how cargo nextest should work.

@tombh

tombh commented Jul 27, 2025

Copy link
Copy Markdown
Collaborator

Great, thanks. It needs nextest to be installed now. Which can be done with cargo install cargo-nextest --locked, but I'm not sure that's idiomatic Nix? There are other installation options here https://nexte.st/docs/installation/from-source

@vincentbernat

Copy link
Copy Markdown
Author

Yes, we cannot do that this way. It needs to be "locked". You cannot access internet while building.

Comment thread flake.nix Outdated
Comment thread flake.nix Outdated
Comment thread flake.nix Outdated
Comment on lines +42 to +47
checkPhase = ''
runHook preCheck
cargo build --all
cargo nextest run
runHook postCheck
'';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I wonder if there's a way to encode this without adding a custom checkPhase. I tried

          cargoTestFlags = [ "--workspace" ];
          checkType = "debug";
          useNextest = true;

but this fails more of the e2e tests (12 instead of 10). I'm not really sure why.

@vincentbernat vincentbernat Jul 29, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

From my understanding, the end to end tests are using the generated binary, which is not rebuilt when using just these flags. But we can move cargo build --all to the precheck hook.

tombh added a commit to tattoy-org/shadow-terminal that referenced this pull request Jul 28, 2025
The old `send_command` now just sends all the characters of the command
individually. And so there's a new command,
`send_command_with_osc_paste()` that retains the old behaviour.

This should fix a lot of the tests failing inside Nix.

Relates to tattoy-org/tattoy#104.
tombh added a commit to tattoy-org/shadow-terminal that referenced this pull request Jul 28, 2025
The old `send_command` now just sends all the characters of the command
individually. And so there's a new command,
`send_command_with_osc_paste()` that retains the old behaviour.

This should fix a lot of the tests failing inside Nix.

Relates to tattoy-org/tattoy#104.
tombh added a commit that referenced this pull request Jul 28, 2025
tombh added a commit that referenced this pull request Jul 28, 2025
tombh added a commit that referenced this pull request Jul 28, 2025
tombh added a commit that referenced this pull request Jul 28, 2025
@tombh

tombh commented Jul 28, 2025

Copy link
Copy Markdown
Collaborator

I've pushed a fix to main branch that gets most of the e2e tests back. It was a very curious issue, for some reason Tattoy's PTY process that gets started under Nix doesn't parse out OSC paste codes (which are used to paste the end to end test commands). I never even knew that PTY processes cared about ANSI codes, I thought that was all handled by the terminal emulator.

So that just leaves the gpu tests now. For them to pass they either need access to a real GPU or a software GPU like LLVMPipe https://docs.mesa3d.org/drivers/llvmpipe.html How important is it that a Nix package runs all the end to end tests?

@vincentbernat

Copy link
Copy Markdown
Author

We could try with mesa.llvmpipeHook in the check inputs.

One can use `nix build .`.

On NixOS, there is only `/bin/sh` and `/usr/bin/env` outside the `/nix`
directory, so some invocations of bash and env were updated for that.

This would help for tattoy-org#100.
@vincentbernat

Copy link
Copy Markdown
Author

I have pushed an updated version, but I wasn't able to fully build from my laptop due to space constraint. I have added mesa.llvmpipeHook for the tests requiring a GPU.

@tombh

tombh commented Jul 29, 2025

Copy link
Copy Markdown
Collaborator

So I can now get all the tests to pass in nix develop, but not from nix build, just the e2e tests fail. The GPU tests actually seem to pass. And nix build recompiles everything every time, which makes debugging difficult. What I can see from nix log is that it can't actually find nano and watch. Ah but we're not installing watch in the checkInputs, but
nano we are, so maybe paths aren't being passed into tattoy binary under test. Theres actually a separate log file that the test logs are telling me is at /build/.local/state/tattoy/tattoy.log, but I'm not sure how to get at that. I suppose it could be printed out after the test logs, but that starts to make nix log` very verbose.

I just thought as well, we should add the flake build as a member of the test matrix in Github Actions. Do you have any experience of that?

@DieracDelta

DieracDelta commented Jul 30, 2025

Copy link
Copy Markdown

checking out head of this branch, I get:

nix build .
tattoy>      Summary [   4.546s] 46 tests run: 36 passed, 10 failed, 0 skipped
tattoy>         FAIL [   3.377s] tests::e2e e2e::auto_text_contrast
tattoy>         FAIL [   3.413s] tests::e2e e2e::background_command
tattoy>         FAIL [   3.388s] tests::e2e e2e::bad_plugin
tattoy>         FAIL [   3.367s] tests::e2e e2e::minimap
tattoy>         FAIL [   3.376s] tests::e2e e2e::palette_to_true_colour
tattoy>         FAIL [   4.539s] tests::e2e e2e::plugins
tattoy>         FAIL [   3.393s] tests::e2e e2e::resizing
tattoy>         FAIL [   3.563s] tests::e2e e2e::scrolling
tattoy>         FAIL [   4.443s] tests::e2e gpu::animated_cursor
tattoy>         FAIL [   4.427s] tests::e2e gpu::shaders

When I run outside the sandbox:

nix develop .#packages.x86_64-linux.tattoy --ignore-env
$configurePhase
$buildPhase
$installPhase
$checkPhase

I get two failing tests:

────────────
     Summary [   4.641s] 46 tests run: 44 passed, 2 failed, 0 skipped
        FAIL [   4.634s] tests::e2e gpu::animated_cursor
        FAIL [   4.624s] tests::e2e gpu::shaders

Any chance you ran into these @tombh ?

Theres actually a separate log file that the test logs are telling me is at /build/.local/state/tattoy/tattoy.log, but I'm not sure how to get at that

I think if you add breakpointHook (or breakpointHookCntr) to checkInputs, then run nix build . -L, then you should be able to inspect the output of running the tests. You can even run $checkPhase from the shell you're dropped into and it should generate the log. That being said, I don't see any log being generated, which is a bit strange. I wonder if there's a permissions error when writing to the file or something 🤔

@tombh

tombh commented Aug 2, 2025

Copy link
Copy Markdown
Collaborator

Yes, that's exactly what I run into. So I'm assuming that the GPU tests fail just because they can't connect to the GPU device and that the e2e tests fail because of the way nix build affects the PTY process that gets created for each test. I'm wondering if it's to do with the /dev/tty that nix build makes available. I must admit I never understood how /dev/tty knows what the current terminal emulator is, maybe through ENV vars?? Either way I'm going to learn something important fixing this! 🤓

@vincentbernat

Copy link
Copy Markdown
Author

So I can now get all the tests to pass in nix develop, but not from nix build, just the e2e tests fail. The GPU tests actually seem to pass. And nix build recompiles everything every time, which makes debugging difficult. What I can see from nix log is that it can't actually find nano and watch. Ah but we're not installing watch in the checkInputs, but nano we are, so maybe paths aren't being passed into tattoy binary under test. Theres actually a separate log file that the test logs are telling me is at /build/.local/state/tattoy/tattoy.log, but I'm not sure how to get at that. I suppose it could be printed out after the test logs, but that starts to make nix log` very verbose.

You can keep the build directory with nix build --keep-failed.

I just thought as well, we should add the flake build as a member of the test matrix in Github Actions. Do you have any experience of that?

I can do that.

@vincentbernat

Copy link
Copy Markdown
Author

I have added a commit to build on GitHub CI.

@DieracDelta

Copy link
Copy Markdown

Maybe we could disable the failing tests for now and add that as a separate issue? Would love to see this merged!

@tombh

tombh commented Sep 3, 2025

Copy link
Copy Markdown
Collaborator

We could certainly do that! But the reason I haven't is that we've already disabled the tests on the Nix package: https://search.nixos.org/packages?channel=unstable&show=tattoy&query=tattoy I'd assumed that gave us the time to really dig into the underlying reason for the test failures. You see I think Nix is revealing a very interesting side of TTYs that I haven't understood yet, so I'm keen to learn from the failures.

Or put another way: if there's already a Nix way to install Tattoy, then the urgency to merge this PR is lower. I could be totally be misunderstanding something though, please let me know.

BTW I've not been working on Tattoy recently, it's not just this PR. But I have big plans, so I'll be back soon!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants