Commit 57e210f6e585f126e6a0bb69f1cc2693be75d100

Authored by Dmitriy Zaporozhets
2 parents fa203e8b fe608f30

Merge pull request #2266 from riyad/improve-status-checks

Improve status checks
doc/install/installation.md
@@ -52,14 +52,14 @@ edited by hand. But, you can use any editor you like instead. @@ -52,14 +52,14 @@ edited by hand. But, you can use any editor you like instead.
52 52
53 Install the required packages: 53 Install the required packages:
54 54
55 - sudo apt-get install -y wget curl build-essential checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libreadline6-dev libc6-dev libssl-dev zlib1g-dev libicu-dev redis-server openssh-server git-core libyaml-dev postfix 55 + sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev wget curl git-core openssh-server redis-server postfix checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev
56 56
57 Make sure you have the right version of Python installed. 57 Make sure you have the right version of Python installed.
58 58
59 # Install Python 59 # Install Python
60 sudo apt-get install python 60 sudo apt-get install python
61 61
62 - # Make sure that Python is 2.x (3.x is not supported at the moment) 62 + # Make sure that Python is 2.5+ (3.x is not supported at the moment)
63 python --version 63 python --version
64 64
65 # If it's Python 3 you might need to install Python 2 separately 65 # If it's Python 3 you might need to install Python 2 separately
@@ -136,10 +136,10 @@ GitLab assumes *full and unshared* control over this Gitolite installation. @@ -136,10 +136,10 @@ GitLab assumes *full and unshared* control over this Gitolite installation.
136 # ... and use it as the admin key for the Gitolite setup 136 # ... and use it as the admin key for the Gitolite setup
137 sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub" 137 sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
138 138
139 -Fix the directory permissions for the repository: 139 +Fix the directory permissions for the repositories:
140 140
141 # Make sure the repositories dir is owned by git and it stays that way 141 # Make sure the repositories dir is owned by git and it stays that way
142 - sudo chmod -R ug+rwXs /home/git/repositories/ 142 + sudo chmod -R ug+rwXs,o-rwx /home/git/repositories/
143 sudo chown -R git:git /home/git/repositories/ 143 sudo chown -R git:git /home/git/repositories/
144 144
145 ## Test if everything works so far 145 ## Test if everything works so far
@@ -187,6 +187,12 @@ do so with caution! @@ -187,6 +187,12 @@ do so with caution!
187 # host serving GitLab where necessary 187 # host serving GitLab where necessary
188 sudo -u gitlab -H vim config/gitlab.yml 188 sudo -u gitlab -H vim config/gitlab.yml
189 189
  190 + # Make sure GitLab can write to the log/ and tmp/ directories
  191 + sudo chown -R gitlab log/
  192 + sudo chown -R gitlab tmp/
  193 + sudo chmod -R u+rwX log/
  194 + sudo chmod -R u+rwX tmp/
  195 +
190 # Copy the example Unicorn config 196 # Copy the example Unicorn config
191 sudo -u gitlab -H cp config/unicorn.rb.example config/unicorn.rb 197 sudo -u gitlab -H cp config/unicorn.rb.example config/unicorn.rb
192 198
@@ -209,7 +215,7 @@ used for the `email.from` setting in `config/gitlab.yml`) @@ -209,7 +215,7 @@ used for the `email.from` setting in `config/gitlab.yml`)
209 sudo -u gitlab -H git config --global user.name "GitLab" 215 sudo -u gitlab -H git config --global user.name "GitLab"
210 sudo -u gitlab -H git config --global user.email "gitlab@localhost" 216 sudo -u gitlab -H git config --global user.email "gitlab@localhost"
211 217
212 -## Setup GitLab hooks 218 +## Setup GitLab Hooks
213 219
214 sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive 220 sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
215 sudo chown git:git /home/git/.gitolite/hooks/common/post-receive 221 sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
@@ -227,7 +233,7 @@ Check if GitLab and its environment is configured correctly: @@ -227,7 +233,7 @@ Check if GitLab and its environment is configured correctly:
227 233
228 To make sure you didn't miss anything run a more thorough check with: 234 To make sure you didn't miss anything run a more thorough check with:
229 235
230 - sudo -u gitlab -H bundle exec rake gitlab:app:status RAILS_ENV=production 236 + sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
231 237
232 If you are all green: congratulations, you successfully installed GitLab! 238 If you are all green: congratulations, you successfully installed GitLab!
233 Although this is the case, there are still a few steps to go. 239 Although this is the case, there are still a few steps to go.
@@ -248,6 +254,8 @@ Make GitLab start on boot: @@ -248,6 +254,8 @@ Make GitLab start on boot:
248 Start your GitLab instance: 254 Start your GitLab instance:
249 255
250 sudo service gitlab start 256 sudo service gitlab start
  257 + # or
  258 + sudo /etc/init.d/gitlab restart
251 259
252 260
253 # 7. Nginx 261 # 7. Nginx
doc/raketasks/maintenance.md
@@ -54,9 +54,18 @@ Git: /usr/bin/git @@ -54,9 +54,18 @@ Git: /usr/bin/git
54 ``` 54 ```
55 55
56 56
57 -### Check GitLab installation status 57 +### Check GitLab configuration
58 58
59 -[Trouble-Shooting-Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide) 59 +Runs the following rake tasks:
  60 +
  61 +* gitlab:env:check
  62 +* gitlab:gitolite:check
  63 +* gitlab:resque:check
  64 +* gitlab:app:check
  65 +
  66 +It will check that each component was setup according to the installation guide and suggest fixes for issues found.
  67 +
  68 +You may also have a look at our [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide).
60 69
61 ``` 70 ```
62 bundle exec rake gitlab:check 71 bundle exec rake gitlab:check
@@ -65,21 +74,68 @@ bundle exec rake gitlab:check @@ -65,21 +74,68 @@ bundle exec rake gitlab:check
65 Example output: 74 Example output:
66 75
67 ``` 76 ```
68 -config/database.yml............exists  
69 -config/gitlab.yml............exists  
70 -/home/git/repositories/............exists  
71 -/home/git/repositories/ is writable?............YES  
72 -Can clone gitolite-admin?............YES  
73 -Can git commit?............YES  
74 -UMASK for .gitolite.rc is 0007? ............YES  
75 -/home/git/.gitolite/hooks/common/post-receive exists? ............YES  
76 -  
77 -Validating projects repositories:  
78 -* abcd.....post-receive file ok  
79 -* abcdtest.....post-receive file missing  
80 -  
81 -Finished  
82 - 77 +Checking Environment ...
  78 +
  79 +gitlab user is in git group? ... yes
  80 +Has no "-e" in ~git/.profile ... yes
  81 +Git configured for gitlab user? ... yes
  82 +Has python2? ... yes
  83 +python2 is supported version? ... yes
  84 +
  85 +Checking Environment ... Finished
  86 +
  87 +Checking Gitolite ...
  88 +
  89 +Using recommended version ... yes
  90 +Repo umask is 0007 in .gitolite.rc? ... yes
  91 +Allow all Git config keys in .gitolite.rc ... yes
  92 +Config directory exists? ... yes
  93 +Config directory owned by git:git? ... yes
  94 +Config directory access is drwxr-x---? ... yes
  95 +Repo base directory exists? ... yes
  96 +Repo base owned by git:git? ... yes
  97 +Repo base access is drwsrws---? ... yes
  98 +Can clone gitolite-admin? ... yes
  99 +Can commit to gitolite-admin? ... yes
  100 +post-receive hook exists? ... yes
  101 +post-receive hook up-to-date? ... yes
  102 +post-receive hooks in repos are links: ...
  103 +GitLab ... ok
  104 +Non-Ascii Files Test ... ok
  105 +Touch Commit Test ... ok
  106 +Without Master Test ... ok
  107 +Git config in repos: ...
  108 +GitLab ... ok
  109 +Non-Ascii Files Test ... ok
  110 +Touch Commit Test ... ok
  111 +Without Master Test ... ok
  112 +
  113 +Checking Gitolite ... Finished
  114 +
  115 +Checking Resque ...
  116 +
  117 +Running? ... yes
  118 +
  119 +Checking Resque ... Finished
  120 +
  121 +Checking GitLab ...
  122 +
  123 +Database config exists? ... yes
  124 +Database is not SQLite ... yes
  125 +All migrations up? ... yes
  126 +GitLab config exists? ... yes
  127 +GitLab config not outdated? ... yes
  128 +Log directory writable? ... yes
  129 +Tmp directory writable? ... yes
  130 +Init script exists? ... yes
  131 +Init script up-to-date? ... yes
  132 +Projects have satellites? ...
  133 +GitLab ... yes
  134 +Non-Ascii Files Test ... yes
  135 +Touch Commit Test ... yes
  136 +Without Master Test ... yes
  137 +
  138 +Checking GitLab ... Finished
83 ``` 139 ```
84 140
85 141
lib/tasks/gitlab/check.rake 0 → 100644
@@ -0,0 +1,959 @@ @@ -0,0 +1,959 @@
  1 +namespace :gitlab do
  2 + desc "GITLAB | Check the configuration of GitLab and its environment"
  3 + task check: %w{gitlab:env:check
  4 + gitlab:gitolite:check
  5 + gitlab:resque:check
  6 + gitlab:app:check}
  7 +
  8 +
  9 +
  10 + namespace :app do
  11 + desc "GITLAB | Check the configuration of the GitLab Rails app"
  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
  115 +
  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
  123 + else
  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
  141 + return
  142 + end
  143 +
  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
  168 + else
  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
  182 + return
  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
  242 + end
  243 + end
  244 +
  245 +
  246 +
  247 + namespace :env do
  248 + desc "GITLAB | Check the configuration of the environment"
  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
  376 + end
  377 + end
  378 +
  379 +
  380 +
  381 + namespace :gitolite do
  382 + desc "GITLAB | Check the configuration of Gitolite"
  383 + task check: :environment do
  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---? ... "
  490 +
  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
  499 + else
  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
  518 + return
  519 + end
  520 +
  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
  622 + else
  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
  644 + return
  645 + end
  646 +
  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
  692 + return
  693 + end
  694 +
  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
  716 + return
  717 + end
  718 +
  719 + if `stat --printf %U #{repo_base_path}` == "git" && # user
  720 + `stat --printf %G #{repo_base_path}` == "git" #group
  721 + puts "yes".green
  722 + else
  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
  740 + return
  741 + end
  742 + puts ""
  743 +
  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
  757 + else
  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
  766 + 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
  781 +
  782 + unless Project.count > 0
  783 + puts "can't check, you have no projects".magenta
  784 + return
  785 + end
  786 + puts ""
  787 +
  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)
  791 +
  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
  803 +
  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
  815 + end
  816 + 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
  837 + end
  838 +
  839 +
  840 +
  841 + namespace :resque do
  842 + desc "GITLAB | Check the configuration of Resque"
  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
  957 + end
  958 + 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}`
lib/tasks/gitlab/status.rake
@@ -1,113 +0,0 @@ @@ -1,113 +0,0 @@
1 -namespace :gitlab do  
2 - namespace :app do  
3 - desc "GITLAB | Check GitLab installation status"  
4 - task :status => :environment do  
5 - puts "\nStarting diagnostics".yellow  
6 - git_base_path = Gitlab.config.git_base_path  
7 -  
8 - print "config/database.yml............"  
9 - if File.exists?(Rails.root.join "config", "database.yml")  
10 - puts "exists".green  
11 - else  
12 - puts "missing".red  
13 - return  
14 - end  
15 -  
16 - print "config/gitlab.yml............"  
17 - if File.exists?(Rails.root.join "config", "gitlab.yml")  
18 - puts "exists".green  
19 - else  
20 - puts "missing".red  
21 - return  
22 - end  
23 -  
24 - print "#{git_base_path}............"  
25 - if File.exists?(git_base_path)  
26 - puts "exists".green  
27 - else  
28 - puts "missing".red  
29 - return  
30 - end  
31 -  
32 - print "#{git_base_path} is writable?............"  
33 - if File.stat(git_base_path).writable?  
34 - puts "YES".green  
35 - else  
36 - puts "NO".red  
37 - return  
38 - end  
39 -  
40 - FileUtils.rm_rf("/tmp/gitolite_gitlab_test")  
41 - begin  
42 - `git clone -q #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite_gitlab_test`  
43 - raise unless $?.success?  
44 - print "Can clone gitolite-admin?............"  
45 - puts "YES".green  
46 - rescue  
47 - print "Can clone gitolite-admin?............"  
48 - puts "NO".red  
49 - return  
50 - end  
51 -  
52 - begin  
53 - Dir.chdir("/tmp/gitolite_gitlab_test") do  
54 - `touch blah && git add blah && git commit -qm blah -- blah`  
55 - raise unless $?.success?  
56 - end  
57 - print "Can git commit?............"  
58 - puts "YES".green  
59 - rescue  
60 - print "Can git commit?............"  
61 - puts "NO".red  
62 - return  
63 - ensure  
64 - FileUtils.rm_rf("/tmp/gitolite_gitlab_test")  
65 - end  
66 -  
67 - print "UMASK for .gitolite.rc is 0007? ............"  
68 - if open(File.absolute_path("#{git_base_path}/../.gitolite.rc")).grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?  
69 - puts "YES".green  
70 - else  
71 - puts "NO".red  
72 - return  
73 - end  
74 -  
75 - gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")  
76 - gitlab_hook_files = ['post-receive']  
77 - gitlab_hook_files.each do |file_name|  
78 - dest = File.join(gitolite_hooks_path, file_name)  
79 - print "#{dest} exists? ............"  
80 - if File.exists?(dest)  
81 - puts "YES".green  
82 - else  
83 - puts "NO".red  
84 - return  
85 - end  
86 - end  
87 -  
88 - if Project.count > 0  
89 - puts "\nValidating projects repositories:".yellow  
90 - Project.find_each(:batch_size => 100) do |project|  
91 - print "* #{project.name}....."  
92 - hook_file = File.join(project.path_to_repo, 'hooks', 'post-receive')  
93 -  
94 - unless File.exists?(hook_file)  
95 - puts "post-receive file missing".red  
96 - next  
97 - end  
98 -  
99 - original_content = File.read(Rails.root.join('lib', 'hooks', 'post-receive'))  
100 - new_content = File.read(hook_file)  
101 -  
102 - if original_content == new_content  
103 - puts "post-receive file ok".green  
104 - else  
105 - puts "post-receive file content does not match".red  
106 - end  
107 - end  
108 - end  
109 -  
110 - puts "\nFinished".blue  
111 - end  
112 - end  
113 -end