Commit c3b9774f4bd0499d1f3d629c4b9bd110e4106b66

Authored by Riyad Preukschas
1 parent 71266ad2

Update and add checks

lib/tasks/gitlab/check.rake
1 1 namespace :gitlab do
2 2 desc "GITLAB | Check the configuration of GitLab and its environment"
3 3 task check: %w{gitlab:env:check
4   - gitlab:app:check
5 4 gitlab:gitolite:check
6   - gitlab:resque:check}
  5 + gitlab:resque:check
  6 + gitlab:app:check}
  7 +
  8 +
7 9  
8 10 namespace :app do
9 11 desc "GITLAB | Check the configuration of the GitLab Rails app"
10 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 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 141 return
18 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 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 182 return
26 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 242 end
28 243 end
29 244  
  245 +
  246 +
30 247 namespace :env do
31 248 desc "GITLAB | Check the configuration of the environment"
32 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 376 end
34 377 end
35 378  
  379 +
  380 +
36 381 namespace :gitolite do
37 382 desc "GITLAB | Check the configuration of Gitolite"
38 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 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 518 return
47 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 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 644 return
55 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 692 return
67 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 716 return
80   - ensure
81   - FileUtils.rm_rf("/tmp/gitolite_gitlab_test")
82 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 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 740 return
90 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 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 766 end
103 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 815 end
125 816 end
126 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 837 end
128 838  
  839 +
  840 +
129 841 namespace :resque do
130 842 desc "GITLAB | Check the configuration of Resque"
131 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 957 end
133 958 end
134 959 end
... ...
lib/tasks/gitlab/info.rake
... ... @@ -84,7 +84,13 @@ namespace :gitlab do
84 84  
85 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 94 def run_and_match(command, regexp)
89 95 run(command).try(:match, regexp)
90 96 end
... ... @@ -93,6 +99,8 @@ namespace :gitlab do
93 99 #
94 100 # Returns nil if the command was not found
95 101 # Returns the output of the command otherwise
  102 + #
  103 + # see also #run_and_match
96 104 def run(command)
97 105 unless `#{command} 2>/dev/null`.blank?
98 106 `#{command}`
... ...