Skip to content

Conversation

doprz
Copy link

@doprz doprz commented Aug 15, 2025

PR Description

This PR adds Nix flake support to provide a reproducible development environment and build process for lazygit contributors, devs, and users.

Features:

  • Nix Flake Configuration: Complete flake setup supporting multiple architectures
  • Development Shell: Pre-configured environment with Go toolchain, linting tools, and development utilities
  • Multiple Entry Points: Support for nix develop, nix run, and nix build

Closes #3474.

Please check if the PR fulfills these requirements

n/a as this PR doesn't modify go files.

  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalised (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc

@doprz doprz changed the title feat(nix): add nix flake with dev shell feat(nix): add comprehensive Nix flake Aug 15, 2025
@stefanhaller
Copy link
Collaborator

I know next to nothing about Nix, and in particular I don't know what Nix flakes are. I don't really want to spend time on learning more about that, either. However, I would have to understand things a little better in order to judge if the PR is good and can be merged. So what can we do?

I see that our current README.md already says something about flakes (here), but I don't understand what it means. Would this have to be changed with your PR?

Any people reading here who are more familiar with Nix and can help review this?

@doprz
Copy link
Author

doprz commented Aug 19, 2025

It seems that someone has already uploaded lazygit to nixpkgs which is what your current README.md references.
https://search.nixos.org/packages?channel=25.05&show=lazygit&query=lazygit

I will update the README.md to include information about the local nix flake. In summary this will allow people that use nix to run your project in an ephemeral shell, install it, and even have a fully setup dev env with go and other dependencies managed by nix.

This will be an official flake that is fully featured while the one on nixpkgs is maintained by others and will either follow the 20.05 or unstable channel.

Copy link

@Eveeifyeve Eveeifyeve left a comment

Choose a reason for hiding this comment

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

I like what you are doing, but a lot of changes needed.

@doprz
Copy link
Author

doprz commented Aug 28, 2025

@Eveeifyeve thank you for the feedback!

@stefanhaller
Copy link
Collaborator

I really wonder if this thing should be maintained in our repo at all. It sounds similar to an rpm spec file, a deb file, or a homebrew formula, and we don't maintain those here either; we let people who are packaging experts do it wherever it makes sense to them. I'd feel better about this if we took the same approach for this flake thing too. (Happy to link to it from the readme though, of course.)

Or am I missing something about why it conceptionally makes sense to maintain this here, unlike those other ones?

@doprz
Copy link
Author

doprz commented Aug 28, 2025

The main difference is that this will let developers load up a dev environment provided by nix which includes all the necessary dependencies, env vars, and build tools/checks setup. I've also added the ability to build from source using nix while the unofficial one on nixpkgs is currently pinned at v0.53.0. The nix configuration doesn't require constant maintenance and will only be updated when NixOS reaches a next major version as the packages follow that or lazygit undergoes a major refactor dependent on the go version, build/dev tools, etc... I would be happy to update the nix configuration for lazygit as needed.

@doprz doprz requested a review from Eveeifyeve August 28, 2025 22:55
Copy link

@Eveeifyeve Eveeifyeve left a comment

Choose a reason for hiding this comment

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

Looking good now, but one change needed

@doprz doprz requested a review from Eveeifyeve August 29, 2025 17:33
Copy link

@Eveeifyeve Eveeifyeve left a comment

Choose a reason for hiding this comment

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

Only two more changes needed. Before I consider this LGTM.

@doprz doprz requested a review from Eveeifyeve August 30, 2025 18:07
@doprz doprz requested a review from Eveeifyeve August 30, 2025 22:53
@doprz
Copy link
Author

doprz commented Aug 30, 2025

Thank you for your feedback @Eveeifyeve on this PR! It's been very helpful to learn best practices.

Copy link

@Eveeifyeve Eveeifyeve left a comment

Choose a reason for hiding this comment

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

A few nit picks, real issue is the with pkgs.lib else it's LGTM.

@doprz
Copy link
Author

doprz commented Aug 31, 2025

Thank you @Eveeifyeve!
cc: @stefanhaller This PR is now complete.

Copy link

@Eveeifyeve Eveeifyeve left a comment

Choose a reason for hiding this comment

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

@doprz
Copy link
Author

doprz commented Sep 4, 2025

@stefanhaller bump

Copy link
Collaborator

@stefanhaller stefanhaller left a comment

Choose a reason for hiding this comment

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

A few things.

  • The branch is totally unreviewable with all the merges from master, and all the fine-grained commits that change things back and forth. I rebased onto master to get rid of the merge commits and force-pushed, this makes it a little bit reviewable at least. In the end I suppose all commits need to be squashed into one. We don't do this by default here, it's the contributor's job to provide a commit sequence that makes sense. In the future, please look into working with fixup! commits, and never merge master into your branch; always rebase onto master instead.
  • As for maintaining it here vs. elsewhere: your explanation above still didn't make it very clear to me what the benefit is of maintaining the flake in this repo vs. somewhere else. I now saw that we have an issue for this (#3474), this explains it a little bit better. But still, there are also things like flakehub, would it be an option to use that instead?

The reason why I'm still hesitant to host the flake here is that this PR has shown that it needs expertise to get this right. @Eveeifyeve seems to have done a great job at helping with this, but if they are not around next time we need to make a change to this, who else will be able to do that? I won't, because I totally lack the expertise, and I don't intend to acquire it. @Eveeifyeve What's your take on this?

flake.nix Outdated

buildInputs = with pkgs; [
# Go toolchain
go_1_24
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't know the nix language at all, so not sure this makes sense, but is there some way to not hard-code the version here, but extract it from go.mod somehow? It would be nice to have fewer places that need to be touched when we bump our go minimum version; I'm worried that we will forget to update it here.

Choose a reason for hiding this comment

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

I would say base it on the latest go version.

Here is a suggestion to fix this:

Suggested change
go_1_24
go

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this is appropriate for guaranteeing a stable environment, which I understand is the whole point here.

While go promises not to break the build with language updates, it might still break tests. It looks like this happened in #4844, so currently developing lazygit works with 1.24 but not with 1.25. (I actually haven't investigated those test failures yet, so I don't even know if these only affect running the tests or also introduce regressions in the production code.)

Copy link

@Eveeifyeve Eveeifyeve Sep 5, 2025

Choose a reason for hiding this comment

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

Well it's impossible of getting the version from the go mod unless you do a script with sed and some magic like make it a package in list which requires huge amounts of nix code to make it work and out of my reach.

I would have to research how packages with the list in pkgs.mkShell work and create a function for it to work.
Many go projects add a defaulted go version in a nix flake to use and call it a day.

If you want to try go right ahead, but for now we should stick to the latest go package since we can't read the go mod file.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@doprz Please don't mark things as resolved when they aren't.

@Eveeifyeve In that case we should go back to specifying the version explicitly and accept the redundancy. We do the same in the Dockerfile and in .github/workflows/ci.yml and other places. It is important to be on the same version everywhere to guarantee predictable results.

The problem is that those other places can easily be found by a global search, but the one in the flake can't because it uses a different format. To mitigate this, we should probably add a comment such as:

diff --git i/go.mod w/go.mod
index 324be6d7e..f48ce401b 100644
--- i/go.mod
+++ w/go.mod
@@ -1,5 +1,7 @@
 module github.com/jesseduffield/lazygit
 
+// If you change this, be sure to also update flake.nix and other files that
+// mention the go version (search for it)
 go 1.24.0
 
 require (

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Eveeifyeve Good point, I guess the regex could be a bit stricter, maybe something like "^go\\s+(\\d+\\.\\d+)\\.\\d+$". We don't need to be lenient against the version having either two or three components; we know it will always be three.

@doprz Did you actually test your version? I think you need to double the \ in the pattern to escape it properly.

Can we add some error checking to make sure the whole thing errors out when it doesn't find a match?

Finally, I'd consider matching the first two components of the version separately so that you don't need to replace dots by underscores afterwards.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, I'm able to add some error correction. Note that in nixpkgs, go has the following options hence why I'm only matching the first two parts of the version:
image

Copy link
Author

Choose a reason for hiding this comment

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

Yeah that could work, but only problem isn't this searching all go's in the file which could cause a problem right?

True but then this becomes into an issue of making sure that all go version instances are matching. I would suppose that the maintainers make sure that their go version throughout the repo matches and if that's the case, then the go version that the nix flake pulls will be consistent, however we could add a section to the makefile that checks all instances of go versions as a check.

Copy link
Author

Choose a reason for hiding this comment

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

A stricter regex that still works while ignoring the patch part of the go version would be:

^go\s(\d+\.\d+)\.\d+$

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah that could work, but only problem isn't this searching all go's in the file which could cause a problem right?

True but then this becomes into an issue of making sure that all go version instances are matching. I would suppose that the maintainers make sure that their go version throughout the repo matches and if that's the case, then the go version that the nix flake pulls will be consistent, however we could add a section to the makefile that checks all instances of go versions as a check.

Not really sure what you are talking about here. I wouldn't worry about any other go versions in other files (e.g. ci.yml) as part of this PR. We already need to make sure that these all agree when we bump the go version, and it's easy enough to find them all with a search.

For this PR, the only concern was that the regex is too loose and might match multiple hits in go.mod, and using a stricter regex solves that.

A stricter regex that still works while ignoring the patch part of the go version would be:

^go\s(\d+\.\d+)\.\d+$

Yes, this is almost the same as the one I was suggesting above (except for the + after the \s, which I don't care too much about as long as we have error checking). Still think you need to double the backslashes to escape them in a nix string literal.

Sounds like we agree on the approach and you can go ahead with this.

@Eveeifyeve
Copy link

Eveeifyeve commented Sep 5, 2025

A few things.

* The branch is totally unreviewable with all the merges from master, and all the fine-grained commits that change things back and forth. I rebased onto master to get rid of the merge commits and force-pushed, this makes it a little bit reviewable at least. In the end I suppose all commits need to be squashed into one. We don't do this by default here, it's the contributor's job to provide a commit sequence that makes sense. In the future, please look into working with `fixup!` commits, and never merge master into your branch; always rebase onto master instead.

* As for maintaining it here vs. elsewhere: your explanation above still didn't make it very clear to me what the benefit is of maintaining the flake in this repo vs. somewhere else. I now saw that we have an issue for this (#3474), this explains it a little bit better. But still, there are also things like flakehub, would it be an option to use that instead?

The reason why I'm still hesitant to host the flake here is that this PR has shown that it needs expertise to get this right. @Eveeifyeve seems to have done a great job at helping with this, but if they are not around next time we need to make a change to this, who else will be able to do that? I won't, because I totally lack the expertise, and I don't intend to acquire it. @Eveeifyeve What's your take on this?

I agree to most of this this pr is at the point where you need to squash the commits. Second Maintaining the flake should be left up to the nix contributors and not the main program maintainers it should be in the official repo because packages take a few days before they reach unstable but have a way of getting the package early before unstable releases/updates.

@stefanhaller
Copy link
Collaborator

it should be in the official repo because packages take a few days before they reach unstable

That alone is not a reason to host them here though, is it? The same can be said about any distribution or package manager. Look at this table, where most table cells need a few days to become green after a new release. We are not going to start hosting deb files, rpm spec files, or homebrew formula files in this repo to avoid that.

@Eveeifyeve
Copy link

Eveeifyeve commented Sep 5, 2025

it should be in the official repo because packages take a few days before they reach unstable

That alone is not a reason to host them here though, is it? The same can be said about any distribution or package manager. Look at this table, where most table cells need a few days to become green after a new release. We are not going to start hosting deb files, rpm spec files, or homebrew formula files in this repo to avoid that.

Homebrew it's instant after pr release idk about others probably the same, but nixpkgs you have something called channels (stable and unstable) and channels get merged every couple of days so you have the time of the pr created till merged + time for channels which can equate to about two weeks. Which for many people you don't want to be waiting for the channel to have the change so many people upstream flakes to get the change instantly while also providing a development shell for those who use nix and want to develop they can.

@doprz doprz force-pushed the feature/nix-flake branch from 2f2e918 to 293b5a7 Compare September 5, 2025 15:49
@doprz
Copy link
Author

doprz commented Sep 5, 2025

This configuration is at the point where it should not require any major changes or foreseeable maintenance to it. The main purpose of this PR was to allow nix users to have a development shell with all of the required deps and tools to start developing and using lazygit. I've also added the ability to build with nix as a nice bonus. I've also squashed the commits + updated the docs as requested.

The original commit I made worked albeit not using best practices as I wasn't aware of things such as flake-compat to offer backwards compatibility to non-flake users. A good example of a project offering nix configuration with a dev environment is ghostty. I'm easily able to clone the repository and have a working zig environment that is reproducible.

image

The PR is not about replacing the "unofficial" nix flake or adding distribution/package management files to the lazygit repo. It's about allowing nix users to have a declarative and reproducible dev environment to allow them to contribute to lazygit. All they have to do is cd into the repo and load up the dev shell or build lazygit via nix or with make. It's a quality of life PR at it's core.

feat(nix): add nix run and build support

chore: move vendor/ -> vendor_lg/

fix: revert vendor_lg -> vendor

fix: fix vendor

chore: set vendorHash to null

docs: add local nix flake installation and contributing

refactor(nix): use flake-parts, nix-systems, and flake-compat

docs: remove nix profile installation section

fix(nix): remove apps and hydraJobs

fix: version info to match main

chore: remove shellHook

feat(nix): add treefmt-nix

feat(nix): add gofmt to treefmt

chore(nix): move version and gitCommit

Apply suggestion from @Eveeifyeve

Co-authored-by: Eveeifyeve <[email protected]>

Apply suggestion from @Eveeifyeve

Co-authored-by: Eveeifyeve <[email protected]>

Apply suggestion from @Eveeifyeve

Co-authored-by: Eveeifyeve <[email protected]>

Apply suggestion from @Eveeifyeve

Co-authored-by: Eveeifyeve <[email protected]>

Update CONTRIBUTING.md

Co-authored-by: Eveeifyeve <[email protected]>

Update flake.nix

Co-authored-by: Eveeifyeve <[email protected]>

chore: change version to dev
@doprz doprz force-pushed the feature/nix-flake branch from 293b5a7 to 516faea Compare September 5, 2025 17:08
# Go toolchain
go
gotools
golangci-lint
Copy link
Collaborator

Choose a reason for hiding this comment

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

For golangci-lint it is even more important than for go itself to be on the right version. Which checks are enabled by default tends to change between versions, so you are likely to get spurious linter warnings when using the latest version.

We already have a mechanism in place to mitigate this by using a shim that runs golangci-lint with the right version (see make lint in the Makefile), so I wonder if we should remove this entirely rather than add an explicit version.

Copy link
Author

Choose a reason for hiding this comment

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

Got it. Yes, then we can remove this from the nix file as I'm including gnumake. Will wait for unresolved comments to be updated before pushing a chore commit and rebasing.

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.

Add a flake.nix
3 participants