1{ stdenv, lib, fetchFromGitLab, bundlerEnv
2, ruby_3_1, tzdata, git, nettools, nixosTests, nodejs, openssl
3, defaultGemConfig, buildRubyGem
4, gitlabEnterprise ? false, callPackage, yarn
5, fixup-yarn-lock, replace, file, cacert, fetchYarnDeps, makeWrapper, pkg-config
6, cargo, rustc, rustPlatform
7}:
8
9let
10 data = lib.importJSON ./data.json;
11
12 version = data.version;
13 src = fetchFromGitLab {
14 owner = data.owner;
15 repo = data.repo;
16 rev = data.rev;
17 sha256 = data.repo_hash;
18 };
19
20 rubyEnv = bundlerEnv rec {
21 name = "gitlab-env-${version}";
22 ruby = ruby_3_1;
23 gemdir = ./rubyEnv;
24 gemset = import (gemdir + "/gemset.nix") src;
25 gemConfig = defaultGemConfig // {
26 gpgme = attrs: {
27 nativeBuildInputs = [ pkg-config ];
28 };
29 # the openssl needs the openssl include files
30 openssl = attrs: {
31 buildInputs = [ openssl ];
32 };
33 ruby-magic = attrs: {
34 buildInputs = [ file ];
35 buildFlags = [ "--enable-system-libraries" ];
36 };
37 gitlab-glfm-markdown = attrs: {
38 cargoDeps = rustPlatform.fetchCargoTarball {
39 src = stdenv.mkDerivation {
40 inherit (buildRubyGem { inherit (attrs) gemName version source; })
41 name
42 src
43 unpackPhase
44 nativeBuildInputs
45 ;
46 dontBuilt = true;
47 installPhase = ''
48 cp -R ext/glfm_markdown $out
49 cp Cargo.lock $out
50 '';
51 };
52 hash = "sha256-7q2xWAsFkXHxkYNzIjPwJRy72xMXF278cpVzqGLt/9Y=";
53 };
54
55 dontBuild = false;
56
57 nativeBuildInputs = [
58 cargo
59 rustc
60 rustPlatform.cargoSetupHook
61 rustPlatform.bindgenHook
62 ];
63
64 disallowedReferences = [
65 rustc.unwrapped
66 ];
67
68 preInstall = ''
69 export CARGO_HOME="$PWD/../.cargo/"
70 '';
71
72 postInstall = ''
73 mv -v $GEM_HOME/gems/${attrs.gemName}-${attrs.version}/lib/{glfm_markdown/glfm_markdown.so,}
74 find $out -type f -name .rustc_info.json -delete
75 '';
76 };
77 };
78 groups = [
79 "default" "unicorn" "ed25519" "metrics" "development" "puma" "test" "kerberos"
80 ];
81 # N.B. omniauth_oauth2_generic and apollo_upload_server both provide a
82 # `console` executable.
83 ignoreCollisions = true;
84
85 extraConfigPaths = [ "${src}/vendor" "${src}/gems" ];
86 };
87
88 assets = stdenv.mkDerivation {
89 pname = "gitlab-assets";
90 inherit version src;
91
92 yarnOfflineCache = fetchYarnDeps {
93 yarnLock = src + "/yarn.lock";
94 sha256 = data.yarn_hash;
95 };
96
97 nativeBuildInputs = [ rubyEnv.wrappedRuby rubyEnv.bundler nodejs yarn git cacert fixup-yarn-lock ];
98
99 patches = [
100 # Since version 12.6.0, the rake tasks need the location of git,
101 # so we have to apply the location patches here too.
102 ./remove-hardcoded-locations.patch
103
104 # Gitlab edited the default database config since [1] and the
105 # installer now complains about valid keywords only being "main", "ci" and "embedded".
106 #
107 # [1]: https://gitlab.com/gitlab-org/gitlab/-/commit/99c0fac52b10cd9df62bbe785db799352a2d9028
108 ./Remove-unsupported-database-names.patch
109 ];
110 # One of the patches uses this variable - if it's unset, execution
111 # of rake tasks fails.
112 GITLAB_LOG_PATH = "log";
113 FOSS_ONLY = !gitlabEnterprise;
114
115 SKIP_YARN_INSTALL = 1;
116
117 configurePhase = ''
118 runHook preConfigure
119
120 # Some rake tasks try to run yarn automatically, which won't work
121 rm lib/tasks/yarn.rake
122
123 # The rake tasks won't run without a basic configuration in place
124 mv config/database.yml.postgresql config/database.yml
125 mv config/gitlab.yml.example config/gitlab.yml
126
127 # Yarn and bundler wants a real home directory to write cache, config, etc to
128 export HOME=$NIX_BUILD_TOP/fake_home
129
130 # Make yarn install packages from our offline cache, not the registry
131 yarn config --offline set yarn-offline-mirror $yarnOfflineCache
132
133 # Fixup "resolved"-entries in yarn.lock to match our offline cache
134 fixup-yarn-lock yarn.lock
135
136 yarn install --offline --frozen-lockfile --ignore-scripts --no-progress --non-interactive
137
138 patchShebangs node_modules/
139 patchShebangs scripts/frontend/
140
141 runHook postConfigure
142 '';
143
144 buildPhase = ''
145 runHook preBuild
146
147 bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production SKIP_YARN_INSTALL=true
148
149 runHook postBuild
150 '';
151
152 installPhase = ''
153 runHook preInstall
154
155 mv public/assets $out
156
157 runHook postInstall
158 '';
159 };
160in
161stdenv.mkDerivation {
162 name = "gitlab${lib.optionalString gitlabEnterprise "-ee"}-${version}";
163
164 inherit src;
165
166 nativeBuildInputs = [ makeWrapper ];
167 buildInputs = [
168 rubyEnv rubyEnv.wrappedRuby rubyEnv.bundler tzdata git nettools
169 ];
170
171 patches = [
172 # Change hardcoded paths to the NixOS equivalent
173 ./remove-hardcoded-locations.patch
174 ];
175
176 postPatch = ''
177 ${lib.optionalString (!gitlabEnterprise) ''
178 # Remove all proprietary components
179 rm -rf ee
180 sed -i 's/-ee//' ./VERSION
181 ''}
182
183 # For reasons I don't understand "bundle exec" ignores the
184 # RAILS_ENV causing tests to be executed that fail because we're
185 # not installing development and test gems above. Deleting the
186 # tests works though.
187 rm lib/tasks/test.rake
188
189 rm config/initializers/gitlab_shell_secret_token.rb
190
191 sed -i '/ask_to_continue/d' lib/tasks/gitlab/two_factor.rake
192 sed -ri -e '/log_level/a config.logger = Logger.new(STDERR)' config/environments/production.rb
193
194 mv config/puma.rb.example config/puma.rb
195 # Always require lib-files and application.rb through their store
196 # path, not their relative state directory path. This gets rid of
197 # warnings and means we don't have to link back to lib from the
198 # state directory.
199 ${replace}/bin/replace-literal -f -r -e '../../lib' "$out/share/gitlab/lib" config
200 ${replace}/bin/replace-literal -f -r -e '../lib' "$out/share/gitlab/lib" config
201 ${replace}/bin/replace-literal -f -r -e "require_relative 'application'" "require_relative '$out/share/gitlab/config/application'" config
202 ${replace}/bin/replace-literal -f -r -e 'require_relative "/home/git/gitlab/lib/gitlab/puma/error_handler"' "require_relative '$out/share/gitlab/lib/gitlab/puma/error_handler'" config
203 '';
204
205 buildPhase = ''
206 rm -f config/secrets.yml
207 mv config config.dist
208 rm -r tmp
209 '';
210
211 installPhase = ''
212 mkdir -p $out/share
213 cp -r . $out/share/gitlab
214 ln -sf ${assets} $out/share/gitlab/public/assets
215 rm -rf $out/share/gitlab/log
216 ln -sf /run/gitlab/log $out/share/gitlab/log
217 ln -sf /run/gitlab/uploads $out/share/gitlab/public/uploads
218 ln -sf /run/gitlab/config $out/share/gitlab/config
219 ln -sf /run/gitlab/tmp $out/share/gitlab/tmp
220
221 # rake tasks to mitigate CVE-2017-0882
222 # see https://about.gitlab.com/2017/03/20/gitlab-8-dot-17-dot-4-security-release/
223 cp ${./reset_token.rake} $out/share/gitlab/lib/tasks/reset_token.rake
224
225 # manually patch the shebang line in generate-loose-foreign-key
226 wrapProgram $out/share/gitlab/scripts/decomposition/generate-loose-foreign-key --set ENABLE_SPRING 0 --add-flags 'runner -e test'
227 '';
228
229 passthru = {
230 inherit rubyEnv assets;
231 ruby = rubyEnv.wrappedRuby;
232 GITALY_SERVER_VERSION = data.passthru.GITALY_SERVER_VERSION;
233 GITLAB_PAGES_VERSION = data.passthru.GITLAB_PAGES_VERSION;
234 GITLAB_SHELL_VERSION = data.passthru.GITLAB_SHELL_VERSION;
235 GITLAB_WORKHORSE_VERSION = data.passthru.GITLAB_WORKHORSE_VERSION;
236 gitlabEnv.FOSS_ONLY = lib.boolToString (!gitlabEnterprise);
237 tests = {
238 nixos-test-passes = nixosTests.gitlab;
239 };
240 };
241
242 meta = with lib; {
243 homepage = "http://www.gitlab.com/";
244 platforms = platforms.linux;
245 maintainers = teams.gitlab.members;
246 } // (if gitlabEnterprise then
247 {
248 license = licenses.unfreeRedistributable; # https://gitlab.com/gitlab-org/gitlab-ee/raw/master/LICENSE
249 description = "GitLab Enterprise Edition";
250 }
251 else
252 {
253 license = licenses.mit;
254 description = "GitLab Community Edition";
255 longDescription = "GitLab Community Edition (CE) is an open source end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more. Self-host GitLab CE on your own servers, in a container, or on a cloud provider.";
256 });
257}