Commit c3b9774f4bd0499d1f3d629c4b9bd110e4106b66
1 parent
71266ad2
Exists in
master
and in
4 other branches
Update and add checks
Showing
2 changed files
with
903 additions
and
70 deletions
Show diff stats
lib/tasks/gitlab/check.rake
1 | namespace :gitlab do | 1 | namespace :gitlab do |
2 | desc "GITLAB | Check the configuration of GitLab and its environment" | 2 | desc "GITLAB | Check the configuration of GitLab and its environment" |
3 | task check: %w{gitlab:env:check | 3 | task check: %w{gitlab:env:check |
4 | - gitlab:app:check | ||
5 | gitlab:gitolite:check | 4 | gitlab:gitolite:check |
6 | - gitlab:resque:check} | 5 | + gitlab:resque:check |
6 | + gitlab:app:check} | ||
7 | + | ||
8 | + | ||
7 | 9 | ||
8 | namespace :app do | 10 | namespace :app do |
9 | desc "GITLAB | Check the configuration of the GitLab Rails app" | 11 | desc "GITLAB | Check the configuration of the GitLab Rails app" |
10 | task check: :environment do | 12 | task check: :environment do |
13 | + warn_user_is_not_gitlab | ||
14 | + start_checking "GitLab" | ||
15 | + | ||
16 | + check_database_config_exists | ||
17 | + check_database_is_not_sqlite | ||
18 | + check_migrations_are_up | ||
19 | + check_gitlab_config_exists | ||
20 | + check_gitlab_config_not_outdated | ||
21 | + check_log_writable | ||
22 | + check_tmp_writable | ||
23 | + check_init_script_exists | ||
24 | + check_init_script_up_to_date | ||
25 | + check_satellites_exist | ||
26 | + | ||
27 | + finished_checking "GitLab" | ||
28 | + end | ||
29 | + | ||
30 | + | ||
31 | + # Checks | ||
32 | + ######################## | ||
33 | + | ||
34 | + def check_database_config_exists | ||
35 | + print "Database config exists? ... " | ||
36 | + | ||
37 | + database_config_file = Rails.root.join("config", "database.yml") | ||
38 | + | ||
39 | + if File.exists?(database_config_file) | ||
40 | + puts "yes".green | ||
41 | + else | ||
42 | + puts "no".red | ||
43 | + try_fixing_it( | ||
44 | + "Copy config/database.yml.<your db> to config/database.yml", | ||
45 | + "Check that the information in config/database.yml is correct" | ||
46 | + ) | ||
47 | + for_more_information( | ||
48 | + see_database_guide, | ||
49 | + "http://guides.rubyonrails.org/getting_started.html#configuring-a-database" | ||
50 | + ) | ||
51 | + check_failed | ||
52 | + end | ||
53 | + end | ||
54 | + | ||
55 | + def check_database_is_not_sqlite | ||
56 | + print "Database is not SQLite ... " | ||
57 | + | ||
58 | + database_config_file = Rails.root.join("config", "database.yml") | ||
59 | + | ||
60 | + unless File.read(database_config_file) =~ /sqlite/ | ||
61 | + puts "yes".green | ||
62 | + else | ||
63 | + puts "no".red | ||
64 | + for_more_information( | ||
65 | + "https://github.com/gitlabhq/gitlabhq/wiki/Migrate-from-SQLite-to-MySQL", | ||
66 | + see_database_guide | ||
67 | + ) | ||
68 | + check_failed | ||
69 | + end | ||
70 | + end | ||
71 | + | ||
72 | + def check_gitlab_config_exists | ||
73 | + print "GitLab config exists? ... " | ||
74 | + | ||
75 | + gitlab_config_file = Rails.root.join("config", "gitlab.yml") | ||
76 | + | ||
77 | + if File.exists?(gitlab_config_file) | ||
78 | + puts "yes".green | ||
79 | + else | ||
80 | + puts "no".red | ||
81 | + try_fixing_it( | ||
82 | + "Copy config/gitlab.yml.example to config/gitlab.yml", | ||
83 | + "Update config/gitlab.yml to match your setup" | ||
84 | + ) | ||
85 | + for_more_information( | ||
86 | + see_installation_guide_section "GitLab" | ||
87 | + ) | ||
88 | + check_failed | ||
89 | + end | ||
90 | + end | ||
91 | + | ||
92 | + def check_gitlab_config_not_outdated | ||
93 | + print "GitLab config not outdated? ... " | ||
94 | + | ||
95 | + gitlab_config_file = Rails.root.join("config", "gitlab.yml") | ||
96 | + unless File.exists?(gitlab_config_file) | ||
97 | + puts "can't check because of previous errors".magenta | ||
98 | + end | ||
99 | + | ||
100 | + # omniauth or ldap could have been deleted from the file | ||
101 | + if File.read(gitlab_config_file) =~ /^web:/ | ||
102 | + puts "yes".green | ||
103 | + else | ||
104 | + puts "no".red | ||
105 | + try_fixing_it( | ||
106 | + "Copy config/gitlab.yml.example to config/gitlab.yml", | ||
107 | + "Update config/gitlab.yml to match your setup" | ||
108 | + ) | ||
109 | + for_more_information( | ||
110 | + see_installation_guide_section "GitLab" | ||
111 | + ) | ||
112 | + check_failed | ||
113 | + end | ||
114 | + end | ||
11 | 115 | ||
12 | - print "config/database.yml............" | ||
13 | - if File.exists?(Rails.root.join "config", "database.yml") | ||
14 | - puts "exists".green | 116 | + def check_init_script_exists |
117 | + print "Init script exists? ... " | ||
118 | + | ||
119 | + script_path = "/etc/init.d/gitlab" | ||
120 | + | ||
121 | + if File.exists?(script_path) | ||
122 | + puts "yes".green | ||
15 | else | 123 | else |
16 | - puts "missing".red | 124 | + puts "no".red |
125 | + try_fixing_it( | ||
126 | + "Install the init script" | ||
127 | + ) | ||
128 | + for_more_information( | ||
129 | + see_installation_guide_section "Install Init Script" | ||
130 | + ) | ||
131 | + check_failed | ||
132 | + end | ||
133 | + end | ||
134 | + | ||
135 | + def check_init_script_up_to_date | ||
136 | + print "Init script up-to-date? ... " | ||
137 | + | ||
138 | + script_path = "/etc/init.d/gitlab" | ||
139 | + unless File.exists?(script_path) | ||
140 | + puts "can't check because of previous errors".magenta | ||
17 | return | 141 | return |
18 | end | 142 | end |
19 | 143 | ||
20 | - print "config/gitlab.yml............" | ||
21 | - if File.exists?(Rails.root.join "config", "gitlab.yml") | ||
22 | - puts "exists".green | 144 | + recipe_content = `curl https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab 2>/dev/null` |
145 | + script_content = File.read(script_path) | ||
146 | + | ||
147 | + if recipe_content == script_content | ||
148 | + puts "yes".green | ||
149 | + else | ||
150 | + puts "no".red | ||
151 | + try_fixing_it( | ||
152 | + "Redownload the init script" | ||
153 | + ) | ||
154 | + for_more_information( | ||
155 | + see_installation_guide_section "Install Init Script" | ||
156 | + ) | ||
157 | + check_failed | ||
158 | + end | ||
159 | + end | ||
160 | + | ||
161 | + def check_migrations_are_up | ||
162 | + print "All migrations up? ... " | ||
163 | + | ||
164 | + migration_status = `bundle exec rake db:migrate:status` | ||
165 | + | ||
166 | + unless migration_status =~ /down\s+\d{14}/ | ||
167 | + puts "yes".green | ||
23 | else | 168 | else |
24 | - puts "missing".red | 169 | + puts "no".red |
170 | + try_fixing_it( | ||
171 | + "sudo -u gitlab -H bundle exec rake db:migrate" | ||
172 | + ) | ||
173 | + check_failed | ||
174 | + end | ||
175 | + end | ||
176 | + | ||
177 | + def check_satellites_exist | ||
178 | + print "Projects have satellites? ... " | ||
179 | + | ||
180 | + unless Project.count > 0 | ||
181 | + puts "can't check, you have no projects".magenta | ||
25 | return | 182 | return |
26 | end | 183 | end |
184 | + puts "" | ||
185 | + | ||
186 | + Project.find_each(batch_size: 100) do |project| | ||
187 | + print "#{project.name.yellow} ... " | ||
188 | + | ||
189 | + if project.satellite.exists? | ||
190 | + puts "yes".green | ||
191 | + else | ||
192 | + puts "no".red | ||
193 | + try_fixing_it( | ||
194 | + "sudo -u gitlab -H bundle exec rake gitlab:app:enable_automerge" | ||
195 | + ) | ||
196 | + for_more_information( | ||
197 | + "doc/raketasks/maintenance.md " | ||
198 | + ) | ||
199 | + check_failed | ||
200 | + end | ||
201 | + end | ||
202 | + end | ||
203 | + | ||
204 | + def check_log_writable | ||
205 | + print "Log directory writable? ... " | ||
206 | + | ||
207 | + log_path = Rails.root.join("log") | ||
208 | + | ||
209 | + if File.writable?(log_path) | ||
210 | + puts "yes".green | ||
211 | + else | ||
212 | + puts "no".red | ||
213 | + try_fixing_it( | ||
214 | + "sudo chown -R gitlab #{log_path}", | ||
215 | + "sudo chmod -R rwX #{log_path}" | ||
216 | + ) | ||
217 | + for_more_information( | ||
218 | + see_installation_guide_section "GitLab" | ||
219 | + ) | ||
220 | + check_failed | ||
221 | + end | ||
222 | + end | ||
223 | + | ||
224 | + def check_tmp_writable | ||
225 | + print "Tmp directory writable? ... " | ||
226 | + | ||
227 | + tmp_path = Rails.root.join("tmp") | ||
228 | + | ||
229 | + if File.writable?(tmp_path) | ||
230 | + puts "yes".green | ||
231 | + else | ||
232 | + puts "no".red | ||
233 | + try_fixing_it( | ||
234 | + "sudo chown -R gitlab #{tmp_path}", | ||
235 | + "sudo chmod -R rwX #{tmp_path}" | ||
236 | + ) | ||
237 | + for_more_information( | ||
238 | + see_installation_guide_section "GitLab" | ||
239 | + ) | ||
240 | + check_failed | ||
241 | + end | ||
27 | end | 242 | end |
28 | end | 243 | end |
29 | 244 | ||
245 | + | ||
246 | + | ||
30 | namespace :env do | 247 | namespace :env do |
31 | desc "GITLAB | Check the configuration of the environment" | 248 | desc "GITLAB | Check the configuration of the environment" |
32 | task check: :environment do | 249 | task check: :environment do |
250 | + warn_user_is_not_gitlab | ||
251 | + start_checking "Environment" | ||
252 | + | ||
253 | + check_gitlab_in_git_group | ||
254 | + check_issue_1056_shell_profile_error | ||
255 | + check_gitlab_git_config | ||
256 | + check_python2_exists | ||
257 | + check_python2_version | ||
258 | + | ||
259 | + finished_checking "Environment" | ||
260 | + end | ||
261 | + | ||
262 | + | ||
263 | + # Checks | ||
264 | + ######################## | ||
265 | + | ||
266 | + def check_gitlab_git_config | ||
267 | + print "Git configured for gitlab user? ... " | ||
268 | + | ||
269 | + options = { | ||
270 | + "user.name" => "GitLab", | ||
271 | + "user.email" => Gitlab.config.email_from | ||
272 | + } | ||
273 | + correct_options = options.map do |name, value| | ||
274 | + run("git config --global --get #{name}").try(:squish) == value | ||
275 | + end | ||
276 | + | ||
277 | + if correct_options.all? | ||
278 | + puts "yes".green | ||
279 | + else | ||
280 | + puts "no".red | ||
281 | + try_fixing_it( | ||
282 | + "sudo -u gitlab -H git config --global user.name \"#{options["user.name"]}\"", | ||
283 | + "sudo -u gitlab -H git config --global user.email \"#{options["user.email"]}\"" | ||
284 | + ) | ||
285 | + for_more_information( | ||
286 | + see_installation_guide_section "GitLab" | ||
287 | + ) | ||
288 | + check_failed | ||
289 | + end | ||
290 | + end | ||
291 | + | ||
292 | + def check_gitlab_in_git_group | ||
293 | + print "gitlab user is in git group? ... " | ||
294 | + | ||
295 | + if run_and_match("id -rnG", /\Wgit\W/) | ||
296 | + puts "yes".green | ||
297 | + else | ||
298 | + puts "no".red | ||
299 | + try_fixing_it( | ||
300 | + "sudo usermod -a -G git gitlab" | ||
301 | + ) | ||
302 | + for_more_information( | ||
303 | + see_installation_guide_section "System Users" | ||
304 | + ) | ||
305 | + check_failed | ||
306 | + end | ||
307 | + end | ||
308 | + | ||
309 | + # see https://github.com/gitlabhq/gitlabhq/issues/1059 | ||
310 | + def check_issue_1056_shell_profile_error | ||
311 | + print "Has no \"-e\" in ~git/.profile ... " | ||
312 | + | ||
313 | + profile_file = File.expand_path("~#{Gitlab.config.ssh_user}/.profile") | ||
314 | + | ||
315 | + unless File.read(profile_file) =~ /^-e PATH/ | ||
316 | + puts "yes".green | ||
317 | + else | ||
318 | + puts "no".red | ||
319 | + try_fixing_it( | ||
320 | + "Open #{profile_file}", | ||
321 | + "Find the line starting with \"-e PATH\"", | ||
322 | + "Remove \"-e \" so the line starts with PATH" | ||
323 | + ) | ||
324 | + for_more_information( | ||
325 | + see_installation_guide_section("Gitolite"), | ||
326 | + "https://github.com/gitlabhq/gitlabhq/issues/1059" | ||
327 | + ) | ||
328 | + check_failed | ||
329 | + end | ||
330 | + end | ||
331 | + | ||
332 | + def check_python2_exists | ||
333 | + print "Has python2? ... " | ||
334 | + | ||
335 | + # Python prints its version to STDERR | ||
336 | + # so we can't just use run("python2 --version") | ||
337 | + if run_and_match("which python2", /python2$/) | ||
338 | + puts "yes".green | ||
339 | + else | ||
340 | + puts "no".red | ||
341 | + try_fixing_it( | ||
342 | + "Make sure you have Python 2.5+ installed", | ||
343 | + "Link it to python2" | ||
344 | + ) | ||
345 | + for_more_information( | ||
346 | + see_installation_guide_section "Packages / Dependencies" | ||
347 | + ) | ||
348 | + check_failed | ||
349 | + end | ||
350 | + end | ||
351 | + | ||
352 | + def check_python2_version | ||
353 | + print "python2 is supported version? ... " | ||
354 | + | ||
355 | + # Python prints its version to STDERR | ||
356 | + # so we can't just use run("python2 --version") | ||
357 | + | ||
358 | + unless run_and_match("which python2", /python2$/) | ||
359 | + puts "can't check because of previous errors".magenta | ||
360 | + return | ||
361 | + end | ||
362 | + | ||
363 | + if `python2 --version 2>&1` =~ /2\.[567]\.\d/ | ||
364 | + puts "yes".green | ||
365 | + else | ||
366 | + puts "no".red | ||
367 | + try_fixing_it( | ||
368 | + "Make sure you have Python 2.5+ installed", | ||
369 | + "Link it to python2" | ||
370 | + ) | ||
371 | + for_more_information( | ||
372 | + see_installation_guide_section "Packages / Dependencies" | ||
373 | + ) | ||
374 | + check_failed | ||
375 | + end | ||
33 | end | 376 | end |
34 | end | 377 | end |
35 | 378 | ||
379 | + | ||
380 | + | ||
36 | namespace :gitolite do | 381 | namespace :gitolite do |
37 | desc "GITLAB | Check the configuration of Gitolite" | 382 | desc "GITLAB | Check the configuration of Gitolite" |
38 | task check: :environment do | 383 | task check: :environment do |
39 | - git_base_path = Gitlab.config.git_base_path | 384 | + warn_user_is_not_gitlab |
385 | + start_checking "Gitolite" | ||
386 | + | ||
387 | + check_gitolite_is_up_to_date | ||
388 | + check_gitoliterc_repo_umask | ||
389 | + check_gitoliterc_git_config_keys | ||
390 | + check_dot_gitolite_exists | ||
391 | + check_dot_gitolite_user_and_group | ||
392 | + check_dot_gitolite_permissions | ||
393 | + check_repo_base_exists | ||
394 | + check_repo_base_user_and_group | ||
395 | + check_repo_base_permissions | ||
396 | + check_can_clone_gitolite_admin | ||
397 | + check_can_commit_to_gitolite_admin | ||
398 | + check_post_receive_hook_exists | ||
399 | + check_post_receive_hook_is_up_to_date | ||
400 | + check_repos_post_receive_hooks_is_link | ||
401 | + check_repos_git_config | ||
402 | + | ||
403 | + finished_checking "Gitolite" | ||
404 | + end | ||
405 | + | ||
406 | + | ||
407 | + # Checks | ||
408 | + ######################## | ||
409 | + | ||
410 | + def check_can_clone_gitolite_admin | ||
411 | + print "Can clone gitolite-admin? ... " | ||
412 | + | ||
413 | + test_path = "/tmp/gitlab_gitolite_admin_test" | ||
414 | + FileUtils.rm_rf(test_path) | ||
415 | + `git clone -q #{Gitlab.config.gitolite_admin_uri} #{test_path}` | ||
416 | + raise unless $?.success? | ||
417 | + | ||
418 | + puts "yes".green | ||
419 | + rescue | ||
420 | + puts "no".red | ||
421 | + try_fixing_it( | ||
422 | + "Make sure the \"admin_uri\" is set correctly in config/gitlab.yml", | ||
423 | + "Try cloning it yourself with:", | ||
424 | + " git clone -q #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite-admin", | ||
425 | + "Make sure Gitolite is installed correctly." | ||
426 | + ) | ||
427 | + for_more_information( | ||
428 | + see_installation_guide_section "Gitolite" | ||
429 | + ) | ||
430 | + check_failed | ||
431 | + end | ||
432 | + | ||
433 | + # assumes #check_can_clone_gitolite_admin has been run before | ||
434 | + def check_can_commit_to_gitolite_admin | ||
435 | + print "Can commit to gitolite-admin? ... " | ||
436 | + | ||
437 | + test_path = "/tmp/gitlab_gitolite_admin_test" | ||
438 | + unless File.exists?(test_path) | ||
439 | + puts "can't check because of previous errors".magenta | ||
440 | + return | ||
441 | + end | ||
442 | + | ||
443 | + Dir.chdir(test_path) do | ||
444 | + `touch foo && git add foo && git commit -qm foo` | ||
445 | + raise unless $?.success? | ||
446 | + end | ||
447 | + | ||
448 | + puts "yes".green | ||
449 | + rescue | ||
450 | + puts "no".red | ||
451 | + try_fixing_it( | ||
452 | + "Try committing to it yourself with:", | ||
453 | + " git clone -q #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite-admin", | ||
454 | + " touch foo", | ||
455 | + " git add foo", | ||
456 | + " git commit -m \"foo\"", | ||
457 | + "Make sure Gitolite is installed correctly." | ||
458 | + ) | ||
459 | + for_more_information( | ||
460 | + see_installation_guide_section "Gitolite" | ||
461 | + ) | ||
462 | + check_failed | ||
463 | + ensure | ||
464 | + FileUtils.rm_rf("/tmp/gitolite_gitlab_test") | ||
465 | + end | ||
466 | + | ||
467 | + def check_dot_gitolite_exists | ||
468 | + print "Config directory exists? ... " | ||
469 | + | ||
470 | + gitolite_config_path = File.expand_path("~#{Gitlab.config.ssh_user}/.gitolite") | ||
471 | + | ||
472 | + if File.directory?(gitolite_config_path) | ||
473 | + puts "yes".green | ||
474 | + else | ||
475 | + puts "no".red | ||
476 | + puts "#{gitolite_config_path} is missing".red | ||
477 | + try_fixing_it( | ||
478 | + "This should have been created when setting up Gitolite.", | ||
479 | + "Make sure Gitolite is installed correctly." | ||
480 | + ) | ||
481 | + for_more_information( | ||
482 | + see_installation_guide_section "Gitolite" | ||
483 | + ) | ||
484 | + check_failed | ||
485 | + end | ||
486 | + end | ||
487 | + | ||
488 | + def check_dot_gitolite_permissions | ||
489 | + print "Config directory access is drwxr-x---? ... " | ||
40 | 490 | ||
41 | - print "#{git_base_path}............" | ||
42 | - if File.exists?(git_base_path) | ||
43 | - puts "exists".green | 491 | + gitolite_config_path = File.expand_path("~#{Gitlab.config.ssh_user}/.gitolite") |
492 | + unless File.exists?(gitolite_config_path) | ||
493 | + puts "can't check because of previous errors".magenta | ||
494 | + return | ||
495 | + end | ||
496 | + | ||
497 | + if `stat --printf %a #{gitolite_config_path}` == "750" | ||
498 | + puts "yes".green | ||
44 | else | 499 | else |
45 | - puts "missing".red | 500 | + puts "no".red |
501 | + puts "#{gitolite_config_path} is not writable".red | ||
502 | + try_fixing_it( | ||
503 | + "sudo chmod 750 #{gitolite_config_path}" | ||
504 | + ) | ||
505 | + for_more_information( | ||
506 | + see_installation_guide_section "Gitolite" | ||
507 | + ) | ||
508 | + check_failed | ||
509 | + end | ||
510 | + end | ||
511 | + | ||
512 | + def check_dot_gitolite_user_and_group | ||
513 | + print "Config directory owned by git:git? ... " | ||
514 | + | ||
515 | + gitolite_config_path = File.expand_path("~#{Gitlab.config.ssh_user}/.gitolite") | ||
516 | + unless File.exists?(gitolite_config_path) | ||
517 | + puts "can't check because of previous errors".magenta | ||
46 | return | 518 | return |
47 | end | 519 | end |
48 | 520 | ||
49 | - print "#{git_base_path} is writable?............" | ||
50 | - if File.stat(git_base_path).writable? | ||
51 | - puts "YES".green | 521 | + if `stat --printf %U #{gitolite_config_path}` == "git" && # user |
522 | + `stat --printf %G #{gitolite_config_path}` == "git" #group | ||
523 | + puts "yes".green | ||
524 | + else | ||
525 | + puts "no".red | ||
526 | + puts "#{gitolite_config_path} is not owned by git".red | ||
527 | + try_fixing_it( | ||
528 | + "sudo chown -R git:git #{gitolite_config_path}" | ||
529 | + ) | ||
530 | + for_more_information( | ||
531 | + see_installation_guide_section "Gitolite" | ||
532 | + ) | ||
533 | + check_failed | ||
534 | + end | ||
535 | + end | ||
536 | + | ||
537 | + def check_gitolite_is_up_to_date | ||
538 | + print "Using recommended version ... " | ||
539 | + if gitolite_version.try(:start_with?, "v3.04") | ||
540 | + puts "yes".green | ||
541 | + else | ||
542 | + puts "no".red | ||
543 | + try_fixing_it( | ||
544 | + "We strongly recommend using the version pointed out in the installation guide." | ||
545 | + ) | ||
546 | + for_more_information( | ||
547 | + see_installation_guide_section "Gitolite" | ||
548 | + ) | ||
549 | + # this is not a "hard" failure | ||
550 | + end | ||
551 | + end | ||
552 | + | ||
553 | + def check_gitoliterc_git_config_keys | ||
554 | + gitoliterc_path = File.join(gitolite_home, ".gitolite.rc") | ||
555 | + | ||
556 | + print "Allow all Git config keys in .gitolite.rc ... " | ||
557 | + option_name = if has_gitolite3? | ||
558 | + # see https://github.com/sitaramc/gitolite/blob/v3.04/src/lib/Gitolite/Rc.pm#L329 | ||
559 | + "GIT_CONFIG_KEYS" | ||
560 | + else | ||
561 | + # assume older version | ||
562 | + # see https://github.com/sitaramc/gitolite/blob/v2.3/conf/example.gitolite.rc#L49 | ||
563 | + "$GL_GITCONFIG_KEYS" | ||
564 | + end | ||
565 | + option_value = ".*" | ||
566 | + if open(gitoliterc_path).grep(/#{option_name}\s*=[>]?\s*["']#{option_value}["']/).any? | ||
567 | + puts "yes".green | ||
568 | + else | ||
569 | + puts "no".red | ||
570 | + try_fixing_it( | ||
571 | + "Open #{gitoliterc_path}", | ||
572 | + "Find the \"#{option_name}\" option", | ||
573 | + "Change its value to \".*\"" | ||
574 | + ) | ||
575 | + for_more_information( | ||
576 | + see_installation_guide_section "Gitolite" | ||
577 | + ) | ||
578 | + check_failed | ||
579 | + end | ||
580 | + end | ||
581 | + | ||
582 | + def check_gitoliterc_repo_umask | ||
583 | + gitoliterc_path = File.join(gitolite_home, ".gitolite.rc") | ||
584 | + | ||
585 | + print "Repo umask is 0007 in .gitolite.rc? ... " | ||
586 | + option_name = if has_gitolite3? | ||
587 | + # see https://github.com/sitaramc/gitolite/blob/v3.04/src/lib/Gitolite/Rc.pm#L328 | ||
588 | + "UMASK" | ||
589 | + else | ||
590 | + # assume older version | ||
591 | + # see https://github.com/sitaramc/gitolite/blob/v2.3/conf/example.gitolite.rc#L32 | ||
592 | + "$REPO_UMASK" | ||
593 | + end | ||
594 | + option_value = "0007" | ||
595 | + if open(gitoliterc_path).grep(/#{option_name}\s*=[>]?\s*#{option_value}/).any? | ||
596 | + puts "yes".green | ||
597 | + else | ||
598 | + puts "no".red | ||
599 | + try_fixing_it( | ||
600 | + "Open #{gitoliterc_path}", | ||
601 | + "Find the \"#{option_name}\" option", | ||
602 | + "Change its value to \"0007\"" | ||
603 | + ) | ||
604 | + for_more_information( | ||
605 | + see_installation_guide_section "Gitolite" | ||
606 | + ) | ||
607 | + check_failed | ||
608 | + end | ||
609 | + end | ||
610 | + | ||
611 | + def check_post_receive_hook_exists | ||
612 | + print "post-receive hook exists? ... " | ||
613 | + | ||
614 | + hook_file = "post-receive" | ||
615 | + gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common") | ||
616 | + gitolite_hook_file = File.join(gitolite_hooks_path, hook_file) | ||
617 | + | ||
618 | + gitlab_hook_file = Rails.root.join.join("lib", "hooks", hook_file) | ||
619 | + | ||
620 | + if File.exists?(gitolite_hook_file) | ||
621 | + puts "yes".green | ||
52 | else | 622 | else |
53 | - puts "NO".red | 623 | + puts "no".red |
624 | + try_fixing_it( | ||
625 | + "sudo -u git cp #{gitlab_hook_file} #{gitolite_hook_file}" | ||
626 | + ) | ||
627 | + for_more_information( | ||
628 | + see_installation_guide_section "Setup GitLab Hooks" | ||
629 | + ) | ||
630 | + check_failed | ||
631 | + end | ||
632 | + end | ||
633 | + | ||
634 | + def check_post_receive_hook_is_up_to_date | ||
635 | + print "post-receive hook up-to-date? ... " | ||
636 | + | ||
637 | + hook_file = "post-receive" | ||
638 | + gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common") | ||
639 | + gitolite_hook_file = File.join(gitolite_hooks_path, hook_file) | ||
640 | + gitolite_hook_content = File.read(gitolite_hook_file) | ||
641 | + | ||
642 | + unless File.exists?(gitolite_hook_file) | ||
643 | + puts "can't check because of previous errors".magenta | ||
54 | return | 644 | return |
55 | end | 645 | end |
56 | 646 | ||
57 | - FileUtils.rm_rf("/tmp/gitolite_gitlab_test") | ||
58 | - begin | ||
59 | - `git clone -q #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite_gitlab_test` | ||
60 | - raise unless $?.success? | ||
61 | - print "Can clone gitolite-admin?............" | ||
62 | - puts "YES".green | ||
63 | - rescue | ||
64 | - print "Can clone gitolite-admin?............" | ||
65 | - puts "NO".red | 647 | + gitlab_hook_file = Rails.root.join.join("lib", "hooks", hook_file) |
648 | + gitlab_hook_content = File.read(gitlab_hook_file) | ||
649 | + | ||
650 | + if gitolite_hook_content == gitlab_hook_content | ||
651 | + puts "yes".green | ||
652 | + else | ||
653 | + puts "no".red | ||
654 | + try_fixing_it( | ||
655 | + "sudo -u git cp #{gitlab_hook_file} #{gitolite_hook_file}" | ||
656 | + ) | ||
657 | + for_more_information( | ||
658 | + see_installation_guide_section "Setup GitLab Hooks" | ||
659 | + ) | ||
660 | + check_failed | ||
661 | + end | ||
662 | + end | ||
663 | + | ||
664 | + def check_repo_base_exists | ||
665 | + print "Repo base directory exists? ... " | ||
666 | + | ||
667 | + repo_base_path = Gitlab.config.git_base_path | ||
668 | + | ||
669 | + if File.exists?(repo_base_path) | ||
670 | + puts "yes".green | ||
671 | + else | ||
672 | + puts "no".red | ||
673 | + puts "#{repo_base_path} is missing".red | ||
674 | + try_fixing_it( | ||
675 | + "This should have been created when setting up Gitolite.", | ||
676 | + "Make sure it's set correctly in config/gitlab.yml", | ||
677 | + "Make sure Gitolite is installed correctly." | ||
678 | + ) | ||
679 | + for_more_information( | ||
680 | + see_installation_guide_section "Gitolite" | ||
681 | + ) | ||
682 | + check_failed | ||
683 | + end | ||
684 | + end | ||
685 | + | ||
686 | + def check_repo_base_permissions | ||
687 | + print "Repo base access is drwsrws---? ... " | ||
688 | + | ||
689 | + repo_base_path = Gitlab.config.git_base_path | ||
690 | + unless File.exists?(repo_base_path) | ||
691 | + puts "can't check because of previous errors".magenta | ||
66 | return | 692 | return |
67 | end | 693 | end |
68 | 694 | ||
69 | - begin | ||
70 | - Dir.chdir("/tmp/gitolite_gitlab_test") do | ||
71 | - `touch blah && git add blah && git commit -qm blah -- blah` | ||
72 | - raise unless $?.success? | ||
73 | - end | ||
74 | - print "Can git commit?............" | ||
75 | - puts "YES".green | ||
76 | - rescue | ||
77 | - print "Can git commit?............" | ||
78 | - puts "NO".red | 695 | + if `stat --printf %a #{repo_base_path}` == "6770" |
696 | + puts "yes".green | ||
697 | + else | ||
698 | + puts "no".red | ||
699 | + puts "#{repo_base_path} is not writable".red | ||
700 | + try_fixing_it( | ||
701 | + "sudo chmod -R ug+rwXs,o-rwx #{repo_base_path}" | ||
702 | + ) | ||
703 | + for_more_information( | ||
704 | + see_installation_guide_section "Gitolite" | ||
705 | + ) | ||
706 | + check_failed | ||
707 | + end | ||
708 | + end | ||
709 | + | ||
710 | + def check_repo_base_user_and_group | ||
711 | + print "Repo base owned by git:git? ... " | ||
712 | + | ||
713 | + repo_base_path = Gitlab.config.git_base_path | ||
714 | + unless File.exists?(repo_base_path) | ||
715 | + puts "can't check because of previous errors".magenta | ||
79 | return | 716 | return |
80 | - ensure | ||
81 | - FileUtils.rm_rf("/tmp/gitolite_gitlab_test") | ||
82 | end | 717 | end |
83 | 718 | ||
84 | - print "UMASK for .gitolite.rc is 0007? ............" | ||
85 | - if open(File.absolute_path("#{git_base_path}/../.gitolite.rc")).grep(/UMASK([ \t]*)=([ \t>]*)0007/).any? | ||
86 | - puts "YES".green | 719 | + if `stat --printf %U #{repo_base_path}` == "git" && # user |
720 | + `stat --printf %G #{repo_base_path}` == "git" #group | ||
721 | + puts "yes".green | ||
87 | else | 722 | else |
88 | - puts "NO".red | 723 | + puts "no".red |
724 | + puts "#{repo_base_path} is not owned by git".red | ||
725 | + try_fixing_it( | ||
726 | + "sudo chown -R git:git #{repo_base_path}" | ||
727 | + ) | ||
728 | + for_more_information( | ||
729 | + see_installation_guide_section "Gitolite" | ||
730 | + ) | ||
731 | + check_failed | ||
732 | + end | ||
733 | + end | ||
734 | + | ||
735 | + def check_repos_git_config | ||
736 | + print "Git config in repos: ... " | ||
737 | + | ||
738 | + unless Project.count > 0 | ||
739 | + puts "can't check, you have no projects".magenta | ||
89 | return | 740 | return |
90 | end | 741 | end |
742 | + puts "" | ||
91 | 743 | ||
92 | - gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common") | ||
93 | - gitlab_hook_files = ['post-receive'] | ||
94 | - gitlab_hook_files.each do |file_name| | ||
95 | - dest = File.join(gitolite_hooks_path, file_name) | ||
96 | - print "#{dest} exists? ............" | ||
97 | - if File.exists?(dest) | ||
98 | - puts "YES".green | 744 | + options = { |
745 | + "core.sharedRepository" => "0660", | ||
746 | + } | ||
747 | + | ||
748 | + Project.find_each(batch_size: 100) do |project| | ||
749 | + print "#{project.name.yellow} ... " | ||
750 | + | ||
751 | + correct_options = options.map do |name, value| | ||
752 | + run("git --git-dir=\"#{project.path_to_repo}\" config --get #{name}").try(:chomp) == value | ||
753 | + end | ||
754 | + | ||
755 | + if correct_options.all? | ||
756 | + puts "ok".green | ||
99 | else | 757 | else |
100 | - puts "NO".red | ||
101 | - return | 758 | + puts "wrong or missing".red |
759 | + try_fixing_it( | ||
760 | + "sudo -u gitlab -H bundle exec rake gitlab:gitolite:update_repos" | ||
761 | + ) | ||
762 | + for_more_information( | ||
763 | + "doc/raketasks/maintenance.md" | ||
764 | + ) | ||
765 | + check_failed | ||
102 | end | 766 | end |
103 | end | 767 | end |
768 | + end | ||
769 | + | ||
770 | + def check_repos_post_receive_hooks_is_link | ||
771 | + print "post-receive hooks in repos are links: ... " | ||
772 | + | ||
773 | + hook_file = "post-receive" | ||
774 | + gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common") | ||
775 | + gitolite_hook_file = File.join(gitolite_hooks_path, hook_file) | ||
776 | + | ||
777 | + unless File.exists?(gitolite_hook_file) | ||
778 | + puts "can't check because of previous errors".magenta | ||
779 | + return | ||
780 | + end | ||
104 | 781 | ||
105 | - if Project.count > 0 | ||
106 | - puts "\nValidating projects repositories:".yellow | ||
107 | - Project.find_each(:batch_size => 100) do |project| | ||
108 | - print "* #{project.name}....." | ||
109 | - hook_file = File.join(project.path_to_repo, 'hooks', 'post-receive') | 782 | + unless Project.count > 0 |
783 | + puts "can't check, you have no projects".magenta | ||
784 | + return | ||
785 | + end | ||
786 | + puts "" | ||
110 | 787 | ||
111 | - unless File.exists?(hook_file) | ||
112 | - puts "post-receive file missing".red | ||
113 | - next | ||
114 | - end | 788 | + Project.find_each(batch_size: 100) do |project| |
789 | + print "#{project.name.yellow} ... " | ||
790 | + project_hook_file = File.join(project.path_to_repo, "hooks", hook_file) | ||
115 | 791 | ||
116 | - original_content = File.read(Rails.root.join('lib', 'hooks', 'post-receive')) | ||
117 | - new_content = File.read(hook_file) | 792 | + unless File.exists?(project_hook_file) |
793 | + puts "missing".red | ||
794 | + try_fixing_it( | ||
795 | + "sudo -u git ln -sf #{gitolite_hook_file} #{project_hook_file}" | ||
796 | + ) | ||
797 | + for_more_information( | ||
798 | + "lib/support/rewrite-hooks.sh" | ||
799 | + ) | ||
800 | + check_failed | ||
801 | + next | ||
802 | + end | ||
118 | 803 | ||
119 | - if original_content == new_content | ||
120 | - puts "post-receive file ok".green | ||
121 | - else | ||
122 | - puts "post-receive file content does not match".red | ||
123 | - end | 804 | + if run_and_match("stat --format %N #{project_hook_file}", /#{hook_file}.+->.+#{gitolite_hook_file}/) |
805 | + puts "ok".green | ||
806 | + else | ||
807 | + puts "not a link to Gitolite's hook".red | ||
808 | + try_fixing_it( | ||
809 | + "sudo -u git ln -sf #{gitolite_hook_file} #{project_hook_file}" | ||
810 | + ) | ||
811 | + for_more_information( | ||
812 | + "lib/support/rewrite-hooks.sh" | ||
813 | + ) | ||
814 | + check_failed | ||
124 | end | 815 | end |
125 | end | 816 | end |
126 | end | 817 | end |
818 | + | ||
819 | + | ||
820 | + # Helper methods | ||
821 | + ######################## | ||
822 | + | ||
823 | + def gitolite_home | ||
824 | + File.expand_path("~#{Gitlab.config.ssh_user}") | ||
825 | + end | ||
826 | + | ||
827 | + def gitolite_version | ||
828 | + gitolite_version_file = "#{gitolite_home}/gitolite/src/VERSION" | ||
829 | + if File.readable?(gitolite_version_file) | ||
830 | + File.read(gitolite_version_file) | ||
831 | + end | ||
832 | + end | ||
833 | + | ||
834 | + def has_gitolite3? | ||
835 | + gitolite_version.try(:start_with?, "v3.") | ||
836 | + end | ||
127 | end | 837 | end |
128 | 838 | ||
839 | + | ||
840 | + | ||
129 | namespace :resque do | 841 | namespace :resque do |
130 | desc "GITLAB | Check the configuration of Resque" | 842 | desc "GITLAB | Check the configuration of Resque" |
131 | task check: :environment do | 843 | task check: :environment do |
844 | + warn_user_is_not_gitlab | ||
845 | + start_checking "Resque" | ||
846 | + | ||
847 | + check_resque_running | ||
848 | + | ||
849 | + finished_checking "Resque" | ||
850 | + end | ||
851 | + | ||
852 | + | ||
853 | + # Checks | ||
854 | + ######################## | ||
855 | + | ||
856 | + def check_resque_running | ||
857 | + print "Running? ... " | ||
858 | + | ||
859 | + if run_and_match("ps aux | grep -i resque", /resque-[\d\.]+:.+$/) | ||
860 | + puts "yes".green | ||
861 | + else | ||
862 | + puts "no".red | ||
863 | + puts "#{repo_base_path} is not owned by git".red | ||
864 | + try_fixing_it( | ||
865 | + "sudo service gitlab restart", | ||
866 | + "or", | ||
867 | + "sudo /etc/init.d/gitlab restart" | ||
868 | + ) | ||
869 | + for_more_information( | ||
870 | + see_installation_guide_section("Install Init Script"), | ||
871 | + "see log/resque.log for possible errors" | ||
872 | + ) | ||
873 | + check_failed | ||
874 | + end | ||
875 | + end | ||
876 | + end | ||
877 | + | ||
878 | + | ||
879 | + # Helper methods | ||
880 | + ########################## | ||
881 | + | ||
882 | + def check_failed | ||
883 | + puts " Please #{"fix the error above"} and rerun the checks.".red | ||
884 | + end | ||
885 | + | ||
886 | + def for_more_information(*sources) | ||
887 | + sources = sources.shift if sources.first.is_a?(Array) | ||
888 | + | ||
889 | + puts " For more information see:".blue | ||
890 | + sources.each do |source| | ||
891 | + puts " #{source}" | ||
892 | + end | ||
893 | + end | ||
894 | + | ||
895 | + def finished_checking(component) | ||
896 | + puts "" | ||
897 | + puts "Checking #{component.yellow} ... #{"Finished".green}" | ||
898 | + puts "" | ||
899 | + end | ||
900 | + | ||
901 | + # Runs the given command | ||
902 | + # | ||
903 | + # Returns nil if the command was not found | ||
904 | + # Returns the output of the command otherwise | ||
905 | + # | ||
906 | + # see also #run_and_match | ||
907 | + def run(command) | ||
908 | + unless `#{command} 2>/dev/null`.blank? | ||
909 | + `#{command}` | ||
910 | + end | ||
911 | + end | ||
912 | + | ||
913 | + # Runs the given command and matches the output agains the given pattern | ||
914 | + # | ||
915 | + # Returns nil if nothing matched | ||
916 | + # Retunrs the MatchData if the pattern matched | ||
917 | + # | ||
918 | + # see also #run | ||
919 | + # see also String#match | ||
920 | + def run_and_match(command, pattern) | ||
921 | + run(command).try(:match, pattern) | ||
922 | + end | ||
923 | + | ||
924 | + def see_database_guide | ||
925 | + "doc/install/databases.md" | ||
926 | + end | ||
927 | + | ||
928 | + def see_installation_guide_section(section) | ||
929 | + "doc/install/installation.md in section \"#{section}\"" | ||
930 | + end | ||
931 | + | ||
932 | + def start_checking(component) | ||
933 | + puts "Checking #{component.yellow} ..." | ||
934 | + puts "" | ||
935 | + end | ||
936 | + | ||
937 | + def try_fixing_it(*steps) | ||
938 | + steps = steps.shift if steps.first.is_a?(Array) | ||
939 | + | ||
940 | + puts " Try fixing it:".blue | ||
941 | + steps.each do |step| | ||
942 | + puts " #{step}" | ||
943 | + end | ||
944 | + end | ||
945 | + | ||
946 | + def warn_user_is_not_gitlab | ||
947 | + unless @warned_user_not_gitlab | ||
948 | + current_user = run("whoami").chomp | ||
949 | + unless current_user == "gitlab" | ||
950 | + puts "#{Colored.color(:black)+Colored.color(:on_yellow)} Warning #{Colored.extra(:clear)}" | ||
951 | + puts " You are running as user #{current_user.magenta}, we hope you know what you are doing." | ||
952 | + puts " Some tests may pass\/fail for the wrong reason." | ||
953 | + puts " For meaningful results you should run this as user #{"gitlab".magenta}." | ||
954 | + puts "" | ||
955 | + end | ||
956 | + @warned_user_not_gitlab = true | ||
132 | end | 957 | end |
133 | end | 958 | end |
134 | end | 959 | end |
lib/tasks/gitlab/info.rake
@@ -84,7 +84,13 @@ namespace :gitlab do | @@ -84,7 +84,13 @@ namespace :gitlab do | ||
84 | 84 | ||
85 | # Helper methods | 85 | # Helper methods |
86 | 86 | ||
87 | - # Runs the given command and matches the output agains the given RegExp | 87 | + # Runs the given command and matches the output agains the given pattern |
88 | + # | ||
89 | + # Returns nil if nothing matched | ||
90 | + # Retunrs the MatchData if the pattern matched | ||
91 | + # | ||
92 | + # see also #run | ||
93 | + # see also String#match | ||
88 | def run_and_match(command, regexp) | 94 | def run_and_match(command, regexp) |
89 | run(command).try(:match, regexp) | 95 | run(command).try(:match, regexp) |
90 | end | 96 | end |
@@ -93,6 +99,8 @@ namespace :gitlab do | @@ -93,6 +99,8 @@ namespace :gitlab do | ||
93 | # | 99 | # |
94 | # Returns nil if the command was not found | 100 | # Returns nil if the command was not found |
95 | # Returns the output of the command otherwise | 101 | # Returns the output of the command otherwise |
102 | + # | ||
103 | + # see also #run_and_match | ||
96 | def run(command) | 104 | def run(command) |
97 | unless `#{command} 2>/dev/null`.blank? | 105 | unless `#{command} 2>/dev/null`.blank? |
98 | `#{command}` | 106 | `#{command}` |