1{
2 pkgs ? import (import ./.npins).nixpkgs { },
3 version ? builtins.null,
4 debug ? false,
5}:
6let
7 # releaseTargets is a list of platforms (in the nix double format) to platforms
8 # in the `go tool dist list` format (that GOOS and GOOARCH expect). this is
9 # used to generate a list of release targets, and to include/exclude tests
10 # when building cross-platform and native binaries.
11 releaseTargets = {
12 aarch64-embedded = "linux/arm64";
13 aarch64-multiplatform = "linux/arm64";
14 aarch64-windows = "windows/arm64";
15 riscv64 = "linux/riscv64";
16 riscv64-embedded = "linux/riscv64";
17 x86_64-linux = "linux/amd64";
18 x86_64-windows = "windows/amd64";
19 x86_64-darwin = "darwin/amd64";
20 aarch64-darwin = "darwin/arm64";
21 };
22
23 inherit (pkgs) lib;
24
25 buildTarget =
26 {
27 platform ? pkgs.stdenv.hostPlatform.system,
28 version ? builtins.null,
29 release ? false,
30 }:
31 let
32 parts = lib.strings.splitString "/" releaseTargets."${platform}";
33 suffix = lib.strings.concatStringsSep "-" parts;
34 goos = builtins.elemAt parts 0;
35 goarch = builtins.elemAt parts 1;
36
37 isNative = platform == pkgs.stdenv.hostPlatform.system;
38 in
39 # git-bug does not currently have any direct or transitive C dependencies.
40 # as such, we do not need to use pkgsCross, which would introduce
41 # additional overhead, but does properly handle setting up different
42 # linkers and would be required if cgo is introduced.
43 pkgs.buildGoModule {
44 name = if isNative then "git-bug" else "git-bug-${suffix}";
45
46 src = lib.sources.cleanSourceWith {
47 filter =
48 name: type:
49 let
50 baseName = baseNameOf (toString name);
51 in
52 !(
53 (
54 type == "directory"
55 && lib.any (n: n == baseName) [
56 # keep-sorted start
57 ".direnv"
58 ".git"
59 ".githooks.d"
60 ".github"
61 ".npins"
62 "nix"
63 "webui/node_modules"
64 "webui/public"
65 "webui/src"
66 "webui/types"
67 # keep-sorted end
68 ]
69 )
70 || (lib.any (n: n == baseName) [
71 # keep-sorted start
72 ".codespellrc"
73 ".editorconfig"
74 ".envrc"
75 ".envrc.local"
76 ".git-blame-ignore-revs"
77 ".gitignore"
78 ".gitmessage"
79 ".mailmap"
80 ".pinact.yaml"
81 "Makefile"
82 "Maskfile.md"
83 "cliff.toml"
84 "default.nix"
85 "git-bug" # the binary built when using the go compiler directly
86 "shell-hook.bash"
87 "shell.nix"
88 # keep-sorted end
89 ])
90 # swap, backup, and temporary files
91 || lib.strings.hasSuffix "~" baseName
92 || lib.strings.match "^\\.sw[a-z]$" baseName != null
93 || lib.strings.match "^\\..*\\.sw[a-z]$" baseName != null
94 # nix-build result symlinks
95 || (type == "symlink" && lib.strings.hasPrefix "result" baseName)
96 # misc stuff (sockets and such that don't belong in the store)
97 || (type == "unknown")
98 );
99 src = ./.;
100 };
101
102 vendorHash = "sha256-F5E7Xu6t3f4rDaA8izqzR6ha8EHSdiQSHdj/LlVBAj0=";
103
104 excludedPackages = [
105 # keep-sorted start
106 "doc"
107 "misc"
108 "tests"
109 # keep-sorted end
110 ];
111
112 ldflags =
113 lib.optionals (!debug || release) [
114 # keep-sorted start
115 "-s" # omit the symbol table
116 "-w" # omit DWARF debug info
117 # keep-sorted end
118 ]
119 ++ lib.optionals (version != builtins.null) [ "-X main.version=${version}" ];
120
121 # normally, pack the web ui for builds, but for debug builds, fetch it
122 # from the filesystem (this is what this build tag controls)
123 tags = lib.optionals (debug && !release) [ "debug" ];
124
125 flags = lib.optionals (debug && !release) [
126 # enable debugger-friendly compiler options for non-release builds
127 "-gcflags=all='-N -l'"
128 ];
129
130 env = {
131 CGO_ENABLED = 0; # disable cgo to enable static builds
132 };
133
134 preBuild = lib.strings.concatLines (
135 lib.optionals (!debug) [
136 # TODO: embed //webui
137 ]
138 ++ [
139 # keep-sorted start
140 "export GOARCH=${goarch}"
141 "export GOOS=${goos}"
142 # keep-sorted end
143 ]
144 );
145
146 postInstall =
147 let
148 extension = lib.optionalString (goos == "windows") ".exe";
149 in
150 lib.optionalString release ''
151 if test -d $out/bin/${goos}_${goarch}; then
152 mv \
153 $out/bin/${goos}_${goarch}/git-bug* \
154 $out/bin/git-bug-${suffix}${extension}
155 rmdir $out/bin/${goos}_${goarch}
156 fi
157
158 # the host-native binary when built on linux or macos
159 if test -x $out/bin/git-bug; then
160 mv $out/bin/git-bug $out/bin/git-bug-${suffix}
161 fi
162 '';
163
164 nativeCheckInputs = with pkgs; [ gitMinimal ];
165
166 doCheck = isNative && !debug;
167
168 # skip tests that require the network
169 checkFlags =
170 let
171 e2eTests = [
172 "TestValidateUsername/existing_organisation"
173 "TestValidateUsername/existing_organisation_with_bad_case"
174 "TestValidateUsername/existing_username"
175 "TestValidateUsername/existing_username_with_bad_case"
176 "TestValidateUsername/non_existing_username"
177 "TestValidateProject/public_project"
178 ];
179 in
180 [ "-skip=^${lib.concatStringsSep "$|^" e2eTests}$" ];
181
182 meta = {
183 description = "Distributed bug tracker embedded in Git";
184 homepage = "https://github.com/git-bug/git-bug";
185 license = lib.licenses.gpl3Plus;
186 };
187 };
188in
189{
190 # build target for the current system
191 default = buildTarget { inherit version; };
192
193 # this drv builds release binaries for every platform. the output directory
194 # contains all of the binaries uniquely named with their platform, suitable
195 # for uploading as release artifacts.
196 release = pkgs.symlinkJoin {
197 name = "git-bug-release-binaries";
198 paths = map (
199 platform:
200 buildTarget {
201 inherit platform version;
202 release = true;
203 }
204 ) (builtins.attrNames releaseTargets);
205 };
206}