NixOS: Erstellen eines neuen Pakets¶
Dieser Artikel entstand, weil ein Bekannter mich bat, ihm zu zeigen, wie man eine Software
für Nix paketiert und in github.com/nixos/nixpkgs integriert.
Konkret ging es um das Paket alertmanager-gotify-bridge, das eine Brücke zwischen dem Prometheus
Alertmanager und Gotify bildet. Ziel war es, nicht nur das Paket zu erstellen, sondern auch den
gesamten Prozess zu verstehen, um es später selbstständig in das offizielle nixpkgs-Repository
einzubringen. Um diesen Ablauf für andere nachvollziehbar zu machen, entschied ich mich, ihn
umfassend zu dokumentieren.
-
Vorarbeiten
-
Contributing Guide lesen
-
GitHub Account anlegen
-
Fork von
erstellen -
Fork klonen und offizielles Repository als "upstream" hinzufügen (für späteres rebasen):
git remote add upstream [email protected]:nixos/nixpkgs.git
-
-
Neuen Feature-Branch in Fork erstellen: Da die NixOS-Maintainer den master-Branch aufgrund von GitHub-Schutzmechanismen nicht bearbeiten können - insbesondere, weil GitHub Action Workflows dort direkt ausgeführt würden - ist es sinnvoll, einen neuen Feature-Branch zu erstellen.
Dies hilft auch dabei, mögliche Merge-Konflikte zu lösen, besonders wenn man noch nicht viel Erfahrung im Umgang mit Git hat.
git checkout -b alertmanager-gotify-bridge -
Sofern dies die erste Contribution zu
nixpkgsist, sollte anschließend ein Eintrag in der Dateimaintainers/maintainers-list.nixangelegt werden.Anschließend werden die Änderungen hinzugefügt:<handle> = { # Required name = "Your name"; # Optional, but at least one of email, matrix or githubId must be given email = "[email protected]"; matrix = "@user:example.org"; github = "<github-name>"; githubId = your-github-id; # see profile -> profile picture -> url keys = [{ fingerprint = "AAAA BBBB CCCC DDDD EEEE FFFF 0000 1111 2222 3333"; }]; };git add maintainers/maintainers-list.nix git commit -m "maintainers: add <handle>" -
Software analysieren: Programmiersprache und Lizenz bestimmen: Nix bietet eine Vielzahl von Modulen zur Unterstützung unterschiedlicher Programmiersprachen. Daher ist der erste Schritt, die Programmiersprache der Software zu identifizieren. Sobald die Sprache bestimmt ist, kann man sich im Language Framework der NixOS-Dokumentation weiter informieren, um das passende Build-Modul auszuwählen und zu verstehen, wie man es korrekt in das Paket integriert.
Die Lizenz wird im weiteren Verlauf für die Metainformationen des Pakets benötigt.
Im Fall der
alertmanager-gotify-bridgehandelt es sich um eine Go-Anwendung, die unter der Apache-2.0 Lizenz steht. Zum Paketieren von Go-Anwendungen bietet Nix das ModulbuildGoModule. Die Lizenz kann mitlib.licenses.asl20definiert werden (siehe lib/licenses.nix). -
Unter Verwendung des Beispielaufrufes von
buildGoModuleund der Informationen aus dem GitHub Repositories der Anwendung kann die Derrivation definiert werden:Nachdem diese unter dem Pfad{ lib, buildGoModule, fetchFromGitHub, }: buildGoModule rec { pname = "alertmanager-gotify-bridge"; # name of the package version = "2.3.1"; # version of last release (on github) src = fetchFromGitHub { owner = "DRuggeri"; # github owner repo = "alertmanager_gotify_bridge"; # github repository name tag = "v${version}"; # releases use semver schema for versioning hash = lib.fakeHash; # we don't know the hash yet, so let's use a fake one }; vendorHash = lib.fakeHash; meta = { description = "Bridge between Prometheus AlertManager and a Gotify server"; homepage = "https://github.com/DRuggeri/alertmanager_gotify_bridge"; changelog = "https://github.com/DRuggeri/alertmanager_gotify_bridge/releases/tag/v${version}"; license = lib.licenses.asl20; maintainers = with lib.maintainers; [ <handle> ]; }; }pkgs/by-name/al/alertmanager-gotify-bridge/package.nixgespeichert wurde, kann das Programm mithilfe des Befehlsnix build -f . alertmanager-gotify-bridgegebaut werden.Beim ersten Ausführen wurde der Build jedoch abgebrochen, da Nix einen Fehler im Zusammenhang mit dem
src.hash-Attribut erkennt:error: hash mismatch in fixed-output derivation '/nix/store/9v7c1qjzibbq3r4v579h684zgkbg0nkz-source.drv': specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= got: sha256-yXPOrpkhQUNPg5YNBxsgGijT1utRcUZ1k38T7wmkbgg= error: 1 dependencies of derivation '/nix/store/zafjqknp6vq3lrh1lf4y9h1npim3vzz6-alertmanager-gotify-bridge-2.3.1.drv' failed to buildAuch nachdem der korrekte Hash in
src.hasheingetragen und der Build erneut gestartet wurde, bricht Nix den Build-Prozess ab, da dervendorHashebenfalls falsch ist:error: hash mismatch in fixed-output derivation '/nix/store/gx9qq67fn953xyzfgznz4ygh9p1rirbc-alertmanager-gotify-bridge-2.3.1-go-modules.drv': specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= got: sha256-YDSKSSMTdjROyBaiOO2tZtu9QPKSUqwAd8VWf3ZOvDI= error: 1 dependencies of derivation '/nix/store/pgrywjs655jqkn2p11hg8hg7nh835m1f-alertmanager-gotify-bridge-2.3.1.drv' failed to buildNachdem auch dieser korrigiert ist schlug der Build mit folgender Fehlermeldung fehl:
error: builder for '/nix/store/q8751wvq5fnrlr8d0h1dlpdihn2jclcv-alertmanager-gotify-bridge-2.3.1.drv' failed with exit code 1; last 25 log lines: > vendor/golang.org/x/exp/constraints/constraints.go:49:2: embedding interface element Integer | Float | ~string requires go1.18 or later (-lang was set to go1.16; check go.mod) > # go.opentelemetry.io/otel/internal/attribute > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:26:17: type parameter requires go1.18 or later (-lang was set to go1.16; check go.mod) > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:26:19: embedding interface element bool | int64 | float64 | string requires go1.18 or later (-lang was set to go1.16; check go.mod) > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:26:59: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod) > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:34:14: type parameter requires go1.18 or later (-lang was set to go1.16; check go.mod) > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:34:16: embedding interface element bool | int64 | float64 | string requires go1.18 or later (-lang was set to go1.16; check go.mod) > vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go:34:51: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod) <... SNIP ...> For full logs, run 'nix log /nix/store/q8751wvq5fnrlr8d0h1dlpdihn2jclcv-alertmanager-gotify-bridge-2.3.1.drv'.Um diesen Fehler zu beheben, musste die in der
go.moddefinierten Go-Version aktualisiert werden. Dazu wurdezunächst geforked und geklont. Nachdem die Version in der go.modauf 1.18 gesetzt wurde, kann der Befehlgo mod tidyausgeführt werden, um die indirekten Abhängigkeiten ingo.mod, und die dazugehörigen Hashes in dergo.sum, hinzuzufügen.Danach wurde mithilfe von
git diffein Patch für die beiden Dateien angelegt, der in der Derrivation hinzugefügt werden kann:patches = [ ./go.sum.patch ./go.mod.patch ];Nachdem das Programm erneut gebaut wurde und der
vendorHashaktualisiert wurde, ist der Build erfolgreich.{ lib, buildGoModule, fetchFromGitHub, }: buildGoModule rec { pname = "alertmanager-gotify-bridge"; version = "2.3.1"; src = fetchFromGitHub { owner = "DRuggeri"; repo = "alertmanager_gotify_bridge"; tag = "v${version}"; hash = "sha256-yXPOrpkhQUNPg5YNBxsgGijT1utRcUZ1k38T7wmkbgg="; }; patches = [ ./go.sum.patch ./go.mod.patch ]; vendorHash = "sha256-APFoNLCrSiAoeuVIzlnmtUthyqFDcG0cjoJf/jGbrTg="; meta = { description = "A bridge between Prometheus AlertManager and a Gotify server"; homepage = "https://github.com/DRuggeri/alertmanager_gotify_bridge"; changelog = "https://github.com/DRuggeri/alertmanager_gotify_bridge/releases/tag/v${version}"; license = lib.licenses.asl20; maintainers = with lib.maintainers; [ <handle> ]; }; } -
Testen und erstellen des Pull Requests Die resultierende
alertmanager_gotify_brudgeBinary ist im Verzeichnisresultzu finden.Nun kann die
package.nixsowie die beiden Patchesgo.{mod,sum}zur Staging Umgebung hinzugefügt, commited und gepushed werden.git add pkgs/by-name/al/alertmanager-gotify-bridge/ git commit -m "alertmanager-gotify-bridge: init at 2.3.1" git push -u origin alertmanager-gotify-bridgeZuletzt wird der Pull Request erstellt (siehe Nachricht von
git push) und geprüft, ob die Pakete alle kompilieren:nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD --print-result"