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 | 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}` | ... | ... |