jreleaser / jreleaser

:rocket: Release projects quickly and easily with JReleaser
https://jreleaser.org
Apache License 2.0
959 stars 112 forks source link

[packagers] Support Nix as packager #1032

Open aalmiray opened 2 years ago

aalmiray commented 2 years ago

https://nixos.org/

aalmiray commented 2 years ago

kcctl🐻 setup https://github.com/NixOS/nixpkgs/pull/199609/commits/ab160d7d424190e7104b5191823d0b42875e92d8

aalmiray commented 7 months ago

https://github.com/NixOS/nixpkgs/issues/303400

https://github.com/NixOS/nixpkgs/pull/271127/

From @msgilligan

msgilligan commented 7 months ago

Make sure to 👍 https://github.com/NixOS/nixpkgs/issues/303400 ! Maybe with enough 👍 some open source elves will do it while we sleep! 🤣

I-Al-Istannen commented 3 weeks ago

It's been packaged by me for ~3 months now, though it is only in unstable until the next release.

aalmiray commented 3 weeks ago

@I-Al-Istannen it would be great to know the steps required to get a Java package published just like you did. In this way, JReleaser could ad nix as a package target like every other package manager currently supported https://jreleaser.org/guide/latest/integrations.html#_package_publish

I-Al-Istannen commented 3 weeks ago

I am not sure what exactly that means. Do you want jreleaser to build a nix package as an artifact? I.e. do you want this workflow?

  1. I write a java project with a cli/that is runnable
  2. I use jreleaser to publish this to Github and maven central
  3. I also use jreleaser to create a nix package other people can consume

If so, that sounds a bit weird. A nix derivation/flake does not embed any binary and there is no central store to push to either. Your generated derivation could, however, pull the jar file from a GitHub release or maven central.

Ideally it would build the jar file from scratch though, inside the derivation. For this you either need a deterministic build or a build that does not require any internet connection (a first phase for downloading dependencies is fine, as long as it is deterministic).
Nix knows two types of derivations: Fixed-output where the resulting hash is known in advance (hardcoded), those can access the internet. Or normal derivations which are sandboxed and have no network, but do not need to be deterministic. Most builds are therefore split in two phases: The first one downloads dependencies and its output is already known exactly through build-tool lockfiles and a second phase without internet that produces the final artifact.

aalmiray commented 3 weeks ago

Yes, I want steps 1 through 3.

Building a Java project usually requires downloading dependencies from Maven Central or another remote server thus one can not guarantee that network access is not required. Also, a small percentage of Java projects adhere to the rules proposed by reproducible builds, thus building from source is also not going to work for the vast majority.

Grabbing an JAR or a binary distribution (ZIP, tarball) from a GH release would be my recommendation, as those artifacts can be signed, checksumed, attestated (SLSA and/or GH attestation).

Is there no central place to obtain derivations from other than core Nix?

Are binary derivations frowned upon?

AFAIR GoReleaser also builds and publishes Nix derivations for Go projects and I believe they do it in binary form, just the same as they do for AUR.

I-Al-Istannen commented 3 weeks ago

Also, a small percentage of Java projects adhere to the rules proposed by reproducible builds, thus building from source is also not going to work for the vast majority.

Nix does not require your build to be deterministic, if it can be run sandboxed without internet. The main problem with Java code is downloading all dependencies before the build to then build offline. The maven dependency plugin (using e.g. go-offline) does not handle plugins correctly, for example.

Grabbing an JAR or a binary distribution (ZIP, tarball) from a GH release would be my recommendation, as those artifacts can be signed, checksumed, attestated (SLSA and/or GH attestation).

That is relatively simple to package then and virtually identical to my jreleaser package.

Is there no central place to obtain derivations from other than core Nix?

There are two things: The derivation source code and the actual evaluated derivation, potentially including artifacts it produced. The latter is stored in nix binary caches, with Hydra being the most common one. You can host your own though, if you want. Currently the amount of trust you need to place in your binary cache is extremely high though (afaik), as the output build result is not verified with a hash for normal derivations. The binary cache could therefore serve you malware. There is ongoing work to change that, but I am not sure how far along that is.

The central place for derivations is nixpkgs (which is a separate repository from Nix itself). There is also the (not sure how maintained) nix user repository. Using nix flakes though, you can obtain flakes from wherever (even from github using nix run github:user/repo), so decentralization is a lot easier there. There is also https://flakehub.com/flakes as a commercial offering, which offers some integration with GitHub actions.

AFAIR GoReleaser also builds and publishes Nix derivations for Go projects and I believe they do it in binary form, just the same as they do for AUR.

Judging by the template it fetches the binary from an URL. I do not know where the URL comes from though. It sounds (to me) like you need to configure an upload somewhere and then that URL is referenced (seems like it).

Personally I would just publish a flake.nix in my repository and maybe update it in the release commit (if it points to a GitHub release and does not build from source). Then users can just reference your repository by git tag and only need to trust your own repository. Nixpkgs is a bit easier for users still, but getting stuff merged there is a lot more work. If you do not want a flake.nix in your repository you will probably have to publish to NUR (using your own github repository) or go through the whole process with nixpkgs (and then updates take a hot minute, if you get it merged in the first place).

aalmiray commented 3 weeks ago

I see. It seems to me that publishing your own flake.nix to a repository under your control is similar to what homebrew offers with local taps. Publishing core homebrew formulas requires more work, and building for source is most times the preferred, if not the only, way to do so.

Havibg the option to publish your own tap gives the producer more leeway but users will have to trust their packages. This is why JReleaser encourages and supports SLSA, SBOMs, signatures, and other (redundant) ways to verify provenance and authenticity.

I-Al-Istannen commented 3 weeks ago

The flake.nix normally lives inside your own repository, the one it refers to (e.g. here or here) and can also specify a development environment.

Publishing core homebrew formulas requires more work, and building for source is most times the preferred, if not the only, way to do so.

Yea, that sounds about right :)

Havibg the option to publish your own tap gives the producer more leeway but users will have to trust their packages. This is why JReleaser encourages and supports SLSA, SBOMs, signatures, and other (redundant) ways to verify provenance and authenticity.

When the flake.nix is inside your software's repository (and ideally also builds from source), you do not have to really trust them more. You are already running their software, if their own GitHub repository has malware inside I wouldn't want to run their software either. And once that is corrupted, their release tarballs probably are too. If the flake downloads a binary jar file from GitHub releases you are at the mercy of git tags playing nice and being stable.


For jreleaser you probably want to generate a flake.nix and flake.lock on release, which downloads the tarball from GitHub releases (or somewhere else). This flake can then directly be committed to the repository as part of the release (so you have one commit that includes the flake.nix referring to a release asset) or you just give it to the user to place wherever they want.

You can also additionally generate an old-school derivation the user can use in conjunction with the Nix User Repository.