BigW Consortium Gitlab

check.rake 27.1 KB
Newer Older
1
namespace :gitlab do
2
  desc "GitLab | Check the configuration of GitLab and its environment"
3
  task check: %w{gitlab:gitlab_shell:check
4
                 gitlab:sidekiq:check
5
                 gitlab:incoming_email:check
6
                 gitlab:ldap:check
Riyad Preukschas committed
7 8 9
                 gitlab:app:check}


10

11
  namespace :app do
12
    desc "GitLab | Check the configuration of the GitLab Rails app"
13
    task check: :environment  do
Riyad Preukschas committed
14 15 16
      warn_user_is_not_gitlab
      start_checking "GitLab"

17
      check_git_config
Riyad Preukschas committed
18 19 20
      check_database_config_exists
      check_database_is_not_sqlite
      check_migrations_are_up
21
      check_orphaned_group_members
Riyad Preukschas committed
22 23 24 25
      check_gitlab_config_exists
      check_gitlab_config_not_outdated
      check_log_writable
      check_tmp_writable
Ben Bodenmiller committed
26
      check_uploads
Riyad Preukschas committed
27 28
      check_init_script_exists
      check_init_script_up_to_date
Hiroyuki Sato committed
29
      check_projects_have_namespace
30
      check_redis_version
31
      check_ruby_version
32
      check_git_version
33
      check_active_users
Riyad Preukschas committed
34 35 36 37 38 39 40 41

      finished_checking "GitLab"
    end


    # Checks
    ########################

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    def check_git_config
      print "Git configured with autocrlf=input? ... "

      options = {
        "core.autocrlf" => "input"
      }

      correct_options = options.map do |name, value|
        run(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value
      end

      if correct_options.all?
        puts "yes".green
      else
        print "Trying to fix Git error automatically. ..."

        if auto_fix_git_config(options)
          puts "Success".green
        else
          puts "Failed".red
          try_fixing_it(
            sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
          )
          for_more_information(
            see_installation_guide_section "GitLab"
          )
       end
      end
    end

Riyad Preukschas committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    def check_database_config_exists
      print "Database config exists? ... "

      database_config_file = Rails.root.join("config", "database.yml")

      if File.exists?(database_config_file)
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "Copy config/database.yml.<your db> to config/database.yml",
          "Check that the information in config/database.yml is correct"
        )
        for_more_information(
          see_database_guide,
          "http://guides.rubyonrails.org/getting_started.html#configuring-a-database"
        )
Riyad Preukschas committed
89
        fix_and_rerun
Riyad Preukschas committed
90 91 92 93
      end
    end

    def check_database_is_not_sqlite
94
      print "Database is SQLite ... "
Riyad Preukschas committed
95 96 97

      database_config_file = Rails.root.join("config", "database.yml")

98
      unless File.read(database_config_file) =~ /adapter:\s+sqlite/
99
        puts "no".green
Riyad Preukschas committed
100
      else
101
        puts "yes".red
102
        puts "Please fix this by removing the SQLite entry from the database.yml".blue
Riyad Preukschas committed
103 104 105 106
        for_more_information(
          "https://github.com/gitlabhq/gitlabhq/wiki/Migrate-from-SQLite-to-MySQL",
          see_database_guide
        )
Riyad Preukschas committed
107
        fix_and_rerun
Riyad Preukschas committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
      end
    end

    def check_gitlab_config_exists
      print "GitLab config exists? ... "

      gitlab_config_file = Rails.root.join("config", "gitlab.yml")

      if File.exists?(gitlab_config_file)
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "Copy config/gitlab.yml.example to config/gitlab.yml",
          "Update config/gitlab.yml to match your setup"
        )
        for_more_information(
          see_installation_guide_section "GitLab"
        )
Riyad Preukschas committed
127
        fix_and_rerun
Riyad Preukschas committed
128 129 130 131
      end
    end

    def check_gitlab_config_not_outdated
132
      print "GitLab config outdated? ... "
Riyad Preukschas committed
133 134 135 136 137 138 139

      gitlab_config_file = Rails.root.join("config", "gitlab.yml")
      unless File.exists?(gitlab_config_file)
        puts "can't check because of previous errors".magenta
      end

      # omniauth or ldap could have been deleted from the file
140
      unless Gitlab.config['git_host']
141
        puts "no".green
Riyad Preukschas committed
142
      else
143
        puts "yes".red
Riyad Preukschas committed
144
        try_fixing_it(
145
          "Backup your config/gitlab.yml",
Riyad Preukschas committed
146 147 148 149 150 151
          "Copy config/gitlab.yml.example to config/gitlab.yml",
          "Update config/gitlab.yml to match your setup"
        )
        for_more_information(
          see_installation_guide_section "GitLab"
        )
Riyad Preukschas committed
152
        fix_and_rerun
Riyad Preukschas committed
153 154
      end
    end
155

Riyad Preukschas committed
156 157 158
    def check_init_script_exists
      print "Init script exists? ... "

159 160 161 162 163
      if omnibus_gitlab?
        puts 'skipped (omnibus-gitlab has no init script)'.magenta
        return
      end

Riyad Preukschas committed
164 165 166 167
      script_path = "/etc/init.d/gitlab"

      if File.exists?(script_path)
        puts "yes".green
Nihad Abbasov committed
168
      else
Riyad Preukschas committed
169 170 171 172 173 174 175
        puts "no".red
        try_fixing_it(
          "Install the init script"
        )
        for_more_information(
          see_installation_guide_section "Install Init Script"
        )
Riyad Preukschas committed
176
        fix_and_rerun
Riyad Preukschas committed
177 178 179 180 181 182
      end
    end

    def check_init_script_up_to_date
      print "Init script up-to-date? ... "

183 184 185 186 187
      if omnibus_gitlab?
        puts 'skipped (omnibus-gitlab has no init script)'.magenta
        return
      end

188
      recipe_path = Rails.root.join("lib/support/init.d/", "gitlab")
Riyad Preukschas committed
189
      script_path = "/etc/init.d/gitlab"
190

Riyad Preukschas committed
191 192
      unless File.exists?(script_path)
        puts "can't check because of previous errors".magenta
193 194 195
        return
      end

196
      recipe_content = File.read(recipe_path)
Riyad Preukschas committed
197 198 199 200 201 202 203 204 205 206 207 208
      script_content = File.read(script_path)

      if recipe_content == script_content
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "Redownload the init script"
        )
        for_more_information(
          see_installation_guide_section "Install Init Script"
        )
Riyad Preukschas committed
209
        fix_and_rerun
Riyad Preukschas committed
210 211 212 213 214 215
      end
    end

    def check_migrations_are_up
      print "All migrations up? ... "

216
      migration_status, _ = Gitlab::Popen.popen(%W(bundle exec rake db:migrate:status))
Riyad Preukschas committed
217 218 219

      unless migration_status =~ /down\s+\d{14}/
        puts "yes".green
220
      else
Riyad Preukschas committed
221 222
        puts "no".red
        try_fixing_it(
223
          sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production")
Riyad Preukschas committed
224
        )
Riyad Preukschas committed
225
        fix_and_rerun
Riyad Preukschas committed
226 227 228
      end
    end

229
    def check_orphaned_group_members
230 231
      print "Database contains orphaned GroupMembers? ... "
      if GroupMember.where("user_id not in (select id from users)").count > 0
232
        puts "yes".red
233 234
        try_fixing_it(
          "You can delete the orphaned records using something along the lines of:",
235
          sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'")
236
        )
237 238 239 240 241
      else
        puts "no".green
      end
    end

Riyad Preukschas committed
242 243 244 245 246 247 248 249 250 251 252
    def check_log_writable
      print "Log directory writable? ... "

      log_path = Rails.root.join("log")

      if File.writable?(log_path)
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "sudo chown -R gitlab #{log_path}",
bassrock committed
253
          "sudo chmod -R u+rwX #{log_path}"
Riyad Preukschas committed
254 255 256 257
        )
        for_more_information(
          see_installation_guide_section "GitLab"
        )
Riyad Preukschas committed
258
        fix_and_rerun
Riyad Preukschas committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272
      end
    end

    def check_tmp_writable
      print "Tmp directory writable? ... "

      tmp_path = Rails.root.join("tmp")

      if File.writable?(tmp_path)
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "sudo chown -R gitlab #{tmp_path}",
bassrock committed
273
          "sudo chmod -R u+rwX #{tmp_path}"
Riyad Preukschas committed
274 275
        )
        for_more_information(
Ben Bodenmiller committed
276 277 278 279 280
          see_installation_guide_section "GitLab"
        )
        fix_and_rerun
      end
    end
281

Ben Bodenmiller committed
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
    def check_uploads
      print "Uploads directory setup correctly? ... "

      unless File.directory?(Rails.root.join('public/uploads'))
        puts "no".red
        try_fixing_it(
          "sudo -u #{gitlab_user} mkdir -m 750 #{Rails.root}/public/uploads"
        )
        for_more_information(
          see_installation_guide_section "GitLab"
        )
        fix_and_rerun
        return
      end

      upload_path = File.realpath(Rails.root.join('public/uploads'))
      upload_path_tmp = File.join(upload_path, 'tmp')

      if File.stat(upload_path).mode == 040750
        unless Dir.exists?(upload_path_tmp)
          puts 'skipped (no tmp uploads folder yet)'.magenta
          return
        end

        # if tmp upload dir has incorrect permissions, assume others do as well
        if File.stat(upload_path_tmp).mode == 040755 && File.owned?(upload_path_tmp) # verify drwxr-xr-x permissions
          puts "yes".green
        else
          puts "no".red
          try_fixing_it(
            "sudo chown -R #{gitlab_user} #{upload_path}",
            "sudo find #{upload_path} -type f -exec chmod 0644 {} \\;",
            "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0755 {} \\;"
          )
          for_more_information(
            see_installation_guide_section "GitLab"
          )
          fix_and_rerun
        end
      else
        puts "no".red
        try_fixing_it(
          "sudo chmod 0750 #{upload_path}",
        )
        for_more_information(
Riyad Preukschas committed
327 328
          see_installation_guide_section "GitLab"
        )
Riyad Preukschas committed
329
        fix_and_rerun
Riyad Preukschas committed
330
      end
331
    end
332

333
    def check_redis_version
334
      min_redis_version = "2.8.0"
335
      print "Redis version >= #{min_redis_version}? ... "
336

tonic committed
337
      redis_version = run(%W(redis-cli --version))
338
      redis_version = redis_version.try(:match, /redis-cli (\d+\.\d+\.\d+)/)
339 340
      if redis_version &&
          (Gem::Version.new(redis_version[1]) > Gem::Version.new(min_redis_version))
341
        puts "yes".green
342
      else
343 344
        puts "no".red
        try_fixing_it(
345
          "Update your redis server to a version >= #{min_redis_version}"
346 347 348 349 350 351
        )
        for_more_information(
          "gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq"
        )
        fix_and_rerun
      end
352
    end
353 354
  end

355
  namespace :gitlab_shell do
356
    desc "GitLab | Check the configuration of GitLab Shell"
357
    task check: :environment  do
Riyad Preukschas committed
358
      warn_user_is_not_gitlab
359
      start_checking "GitLab Shell"
Riyad Preukschas committed
360

361
      check_gitlab_shell
Riyad Preukschas committed
362
      check_repo_base_exists
363
      check_repo_base_is_not_symlink
Riyad Preukschas committed
364 365
      check_repo_base_user_and_group
      check_repo_base_permissions
366
      check_repos_hooks_directory_is_link
367
      check_gitlab_shell_self_test
Riyad Preukschas committed
368

369
      finished_checking "GitLab Shell"
Riyad Preukschas committed
370 371 372 373 374 375 376 377 378
    end


    # Checks
    ########################

    def check_repo_base_exists
      print "Repo base directory exists? ... "

379
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
Riyad Preukschas committed
380 381 382 383 384 385 386

      if File.exists?(repo_base_path)
        puts "yes".green
      else
        puts "no".red
        puts "#{repo_base_path} is missing".red
        try_fixing_it(
387
          "This should have been created when setting up GitLab Shell.",
Riyad Preukschas committed
388
          "Make sure it's set correctly in config/gitlab.yml",
389
          "Make sure GitLab Shell is installed correctly."
Riyad Preukschas committed
390 391
        )
        for_more_information(
392
          see_installation_guide_section "GitLab Shell"
Riyad Preukschas committed
393
        )
Riyad Preukschas committed
394
        fix_and_rerun
Riyad Preukschas committed
395 396 397
      end
    end

398 399 400
    def check_repo_base_is_not_symlink
      print "Repo base directory is a symlink? ... "

401
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
      unless File.exists?(repo_base_path)
        puts "can't check because of previous errors".magenta
        return
      end

      unless File.symlink?(repo_base_path)
        puts "no".green
      else
        puts "yes".red
        try_fixing_it(
          "Make sure it's set to the real directory in config/gitlab.yml"
        )
        fix_and_rerun
      end
    end

Riyad Preukschas committed
418
    def check_repo_base_permissions
419
      print "Repo base access is drwxrws---? ... "
Riyad Preukschas committed
420

421
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
Riyad Preukschas committed
422 423
      unless File.exists?(repo_base_path)
        puts "can't check because of previous errors".magenta
424 425 426
        return
      end

427
      if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770")
Riyad Preukschas committed
428 429 430 431
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
432
          "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
433
          "sudo chmod -R ug-s #{repo_base_path}",
434
          "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
Riyad Preukschas committed
435 436
        )
        for_more_information(
437
          see_installation_guide_section "GitLab Shell"
Riyad Preukschas committed
438
        )
Riyad Preukschas committed
439
        fix_and_rerun
Riyad Preukschas committed
440 441 442 443
      end
    end

    def check_repo_base_user_and_group
444 445 446
      gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
      gitlab_shell_owner_group = Gitlab.config.gitlab_shell.owner_group
      print "Repo base owned by #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group}? ... "
Riyad Preukschas committed
447

448
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
Riyad Preukschas committed
449 450
      unless File.exists?(repo_base_path)
        puts "can't check because of previous errors".magenta
451 452 453
        return
      end

454 455 456
      uid = uid_for(gitlab_shell_ssh_user)
      gid = gid_for(gitlab_shell_owner_group)
      if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid
Riyad Preukschas committed
457
        puts "yes".green
458
      else
Riyad Preukschas committed
459
        puts "no".red
460
        puts "  User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".blue
Riyad Preukschas committed
461
        try_fixing_it(
462
          "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}"
Riyad Preukschas committed
463 464
        )
        for_more_information(
465
          see_installation_guide_section "GitLab Shell"
Riyad Preukschas committed
466
        )
Riyad Preukschas committed
467
        fix_and_rerun
Riyad Preukschas committed
468 469 470
      end
    end

471 472
    def check_repos_hooks_directory_is_link
      print "hooks directories in repos are links: ... "
Riyad Preukschas committed
473

474
      gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
475

Riyad Preukschas committed
476 477 478 479 480
      unless Project.count > 0
        puts "can't check, you have no projects".magenta
        return
      end
      puts ""
481

Riyad Preukschas committed
482
      Project.find_each(batch_size: 100) do |project|
483
        print sanitized_message(project)
484
        project_hook_directory = File.join(project.repository.path_to_repo, "hooks")
485

486 487
        if project.empty_repo?
          puts "repository is empty".magenta
488 489
        elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) &&
            (File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path))
490
          puts 'ok'.green
Riyad Preukschas committed
491
        else
492 493
          puts "wrong or missing hooks".red
          try_fixing_it(
494
            sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')}"),
495 496 497 498 499 500 501
            'Check the hooks_path in config/gitlab.yml',
            'Check your gitlab-shell installation'
          )
          for_more_information(
            see_installation_guide_section "GitLab Shell"
          )
          fix_and_rerun
502
        end
503

504
      end
505
    end
Riyad Preukschas committed
506

507
    def check_gitlab_shell_self_test
508
      gitlab_shell_repo_base = gitlab_shell_path
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
      check_cmd = File.expand_path('bin/check', gitlab_shell_repo_base)
      puts "Running #{check_cmd}"
      if system(check_cmd, chdir: gitlab_shell_repo_base)
        puts 'gitlab-shell self-check successful'.green
      else
        puts 'gitlab-shell self-check failed'.red
        try_fixing_it(
          'Make sure GitLab is running;',
          'Check the gitlab-shell configuration file:',
          sudo_gitlab("editor #{File.expand_path('config.yml', gitlab_shell_repo_base)}")
        )
        fix_and_rerun
      end
    end

Hiroyuki Sato committed
524 525 526 527 528 529 530 531 532 533
    def check_projects_have_namespace
      print "projects have namespace: ... "

      unless Project.count > 0
        puts "can't check, you have no projects".magenta
        return
      end
      puts ""

      Project.find_each(batch_size: 100) do |project|
534
        print sanitized_message(project)
Hiroyuki Sato committed
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549

        if project.namespace
          puts "yes".green
        else
          puts "no".red
          try_fixing_it(
            "Migrate global projects"
          )
          for_more_information(
            "doc/update/5.4-to-6.0.md in section \"#global-projects\""
          )
          fix_and_rerun
        end
      end
    end
Riyad Preukschas committed
550 551 552 553

    # Helper methods
    ########################

554 555
    def gitlab_shell_path
      Gitlab.config.gitlab_shell.path
Riyad Preukschas committed
556 557
    end

558
    def gitlab_shell_version
559
      Gitlab::Shell.new.version
Riyad Preukschas committed
560 561
    end

562
    def gitlab_shell_major_version
563
      Gitlab::Shell.version_required.split('.')[0].to_i
564 565 566
    end

    def gitlab_shell_minor_version
567
      Gitlab::Shell.version_required.split('.')[1].to_i
568 569 570
    end

    def gitlab_shell_patch_version
571
      Gitlab::Shell.version_required.split('.')[2].to_i
572
    end
573
  end
574

Riyad Preukschas committed
575 576


577
  namespace :sidekiq do
578
    desc "GitLab | Check the configuration of Sidekiq"
579
    task check: :environment  do
Riyad Preukschas committed
580
      warn_user_is_not_gitlab
581
      start_checking "Sidekiq"
Riyad Preukschas committed
582

583
      check_sidekiq_running
584
      only_one_sidekiq_running
Riyad Preukschas committed
585

586
      finished_checking "Sidekiq"
Riyad Preukschas committed
587 588 589 590 591 592
    end


    # Checks
    ########################

593
    def check_sidekiq_running
Riyad Preukschas committed
594 595
      print "Running? ... "

596
      if sidekiq_process_count > 0
Riyad Preukschas committed
597 598 599 600
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
601
          sudo_gitlab("RAILS_ENV=production bin/background_jobs start")
Riyad Preukschas committed
602 603 604
        )
        for_more_information(
          see_installation_guide_section("Install Init Script"),
605
          "see log/sidekiq.log for possible errors"
Riyad Preukschas committed
606
        )
Riyad Preukschas committed
607
        fix_and_rerun
Riyad Preukschas committed
608 609
      end
    end
610 611

    def only_one_sidekiq_running
612 613
      process_count = sidekiq_process_count
      return if process_count.zero?
614 615

      print 'Number of Sidekiq processes ... '
616
      if process_count == 1
617 618
        puts '1'.green
      else
619
        puts "#{process_count}".red
620 621
        try_fixing_it(
          'sudo service gitlab stop',
622 623
          "sudo pkill -u #{gitlab_user} -f sidekiq",
          "sleep 10 && sudo pkill -9 -u #{gitlab_user} -f sidekiq",
624 625 626 627 628 629
          'sudo service gitlab start'
        )
        fix_and_rerun
      end
    end

630
    def sidekiq_process_count
631 632
      ps_ux, _ = Gitlab::Popen.popen(%W(ps ux))
      ps_ux.scan(/sidekiq \d+\.\d+\.\d+/).count
633
    end
Riyad Preukschas committed
634 635
  end

636

637
  namespace :incoming_email do
638 639 640 641 642
    desc "GitLab | Check the configuration of Reply by email"
    task check: :environment  do
      warn_user_is_not_gitlab
      start_checking "Reply by email"

643
      if Gitlab.config.incoming_email.enabled
644 645
        check_address_formatted_correctly
        check_imap_authentication
646

647 648 649 650 651 652
        if Rails.env.production?
          check_initd_configured_correctly
          check_mail_room_running
        else
          check_foreman_configured_correctly
        end
653 654 655 656 657 658 659 660 661 662 663 664 665 666
      else
        puts 'Reply by email is disabled in config/gitlab.yml'
      end

      finished_checking "Reply by email"
    end


    # Checks
    ########################

    def check_address_formatted_correctly
      print "Address formatted correctly? ... "

667
      if Gitlab::IncomingEmail.address_formatted_correctly?
668 669 670 671
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
672
          "Make sure that the address in config/gitlab.yml includes the '%{key}' placeholder."
673 674 675 676 677 678 679 680
        )
        fix_and_rerun
      end
    end

    def check_initd_configured_correctly
      print "Init.d configured correctly? ... "

681 682 683 684 685
      if omnibus_gitlab?
        puts 'skipped (omnibus-gitlab has no init script)'.magenta
        return
      end

686 687 688 689 690 691 692 693 694 695
      path = "/etc/default/gitlab"

      if File.exist?(path) && File.read(path).include?("mail_room_enabled=true")
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "Enable mail_room in the init.d configuration."
        )
        for_more_information(
696
          "doc/incoming_email/README.md"
697 698 699 700 701
        )
        fix_and_rerun
      end
    end

702 703 704 705 706
    def check_foreman_configured_correctly
      print "Foreman configured correctly? ... "

      path = Rails.root.join("Procfile")

707
      if File.exist?(path) && File.read(path) =~ /^mail_room:/
708 709 710 711 712 713 714
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          "Enable mail_room in your Procfile."
        )
        for_more_information(
715
          "doc/incoming_email/README.md"
716 717 718 719 720
        )
        fix_and_rerun
      end
    end

721 722 723 724 725 726 727 728 729 730
    def check_mail_room_running
      print "MailRoom running? ... "

      path = "/etc/default/gitlab"

      unless File.exist?(path) && File.read(path).include?("mail_room_enabled=true")
        puts "can't check because of previous errors".magenta
        return
      end

731
      if mail_room_running?
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
          sudo_gitlab("RAILS_ENV=production bin/mail_room start")
        )
        for_more_information(
          see_installation_guide_section("Install Init Script"),
          "see log/mail_room.log for possible errors"
        )
        fix_and_rerun
      end
    end

    def check_imap_authentication
      print "IMAP server credentials are correct? ... "

749
      config = Gitlab.config.incoming_email
750 751 752

      if config
        begin
753 754 755
          imap = Net::IMAP.new(config.host, port: config.port, ssl: config.ssl)
          imap.starttls if config.start_tls
          imap.login(config.user, config.password)
756 757 758 759 760 761 762 763 764 765 766
          connected = true
        rescue
          connected = false
        end
      end

      if connected
        puts "yes".green
      else
        puts "no".red
        try_fixing_it(
767
          "Check that the information in config/gitlab.yml is correct"
768 769
        )
        for_more_information(
770
          "doc/incoming_email/README.md"
771 772 773 774 775
        )
        fix_and_rerun
      end
    end

776
    def mail_room_running?
777
      ps_ux, _ = Gitlab::Popen.popen(%W(ps ux))
778
      ps_ux.include?("mail_room")
779 780 781
    end
  end

782
  namespace :ldap do
783
    task :check, [:limit] => :environment do |t, args|
784 785
      # Only show up to 100 results because LDAP directories can be very big.
      # This setting only affects the `rake gitlab:check` script.
786
      args.with_defaults(limit: 100)
787 788 789
      warn_user_is_not_gitlab
      start_checking "LDAP"

790
      if Gitlab::LDAP::Config.enabled?
791
        print_users(args.limit)
792 793 794
      else
        puts 'LDAP is disabled in config/gitlab.yml'
      end
795 796 797 798

      finished_checking "LDAP"
    end

799
    def print_users(limit)
800
      puts "LDAP users with access to your GitLab server (only showing the first #{limit} results)"
801

802
      servers = Gitlab::LDAP::Config.providers
803

804 805
      servers.each do |server|
        puts "Server: #{server}"
806
        Gitlab::LDAP::Adapter.open(server) do |adapter|
807 808 809 810 811
          users = adapter.users(adapter.config.uid, '*', 100)
          users.each do |user|
            puts "\tDN: #{user.dn}\t #{adapter.config.uid}: #{user.uid}"
          end
        end
812
      end
813 814
    end
  end
Riyad Preukschas committed
815

Vinnie Okada committed
816
  namespace :repo do
817
    desc "GitLab | Check the integrity of the repositories managed by GitLab"
Vinnie Okada committed
818 819 820 821 822 823 824
    task check: :environment do
      namespace_dirs = Dir.glob(
        File.join(Gitlab.config.gitlab_shell.repos_path, '*')
      )

      namespace_dirs.each do |namespace_dir|
        repo_dirs = Dir.glob(File.join(namespace_dir, '*'))
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
        repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) }
      end
    end
  end

  namespace :user do
    desc "GitLab | Check the integrity of a specific user's repositories"
    task :check_repos, [:username] => :environment do |t, args|
      username = args[:username] || prompt("Check repository integrity for which username? ".blue)
      user = User.find_by(username: username)
      if user
        repo_dirs = user.authorized_projects.map do |p|
                      File.join(
                        Gitlab.config.gitlab_shell.repos_path,
                        "#{p.path_with_namespace}.git"
                      )
                    end

        repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) }
      else
        puts "\nUser '#{username}' not found".red
Vinnie Okada committed
846 847 848 849
      end
    end
  end

Riyad Preukschas committed
850 851 852
  # Helper methods
  ##########################

Riyad Preukschas committed
853
  def fix_and_rerun
Riyad Preukschas committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
    puts "  Please #{"fix the error above"} and rerun the checks.".red
  end

  def for_more_information(*sources)
    sources = sources.shift if sources.first.is_a?(Array)

    puts "  For more information see:".blue
    sources.each do |source|
      puts "  #{source}"
    end
  end

  def finished_checking(component)
    puts ""
    puts "Checking #{component.yellow} ... #{"Finished".green}"
    puts ""
  end

  def see_database_guide
    "doc/install/databases.md"
  end

  def see_installation_guide_section(section)
    "doc/install/installation.md in section \"#{section}\""
  end

880 881 882 883
  def sudo_gitlab(command)
    "sudo -u #{gitlab_user} -H #{command}"
  end

884 885 886 887
  def gitlab_user
    Gitlab.config.gitlab.user
  end

Riyad Preukschas committed
888 889 890 891 892 893 894 895 896 897 898 899 900
  def start_checking(component)
    puts "Checking #{component.yellow} ..."
    puts ""
  end

  def try_fixing_it(*steps)
    steps = steps.shift if steps.first.is_a?(Array)

    puts "  Try fixing it:".blue
    steps.each do |step|
      puts "  #{step}"
    end
  end
901 902

  def check_gitlab_shell
903
    required_version = Gitlab::VersionInfo.new(gitlab_shell_major_version, gitlab_shell_minor_version, gitlab_shell_patch_version)
904
    current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
905

906
    print "GitLab Shell version >= #{required_version} ? ... "
907
    if current_version.valid? && required_version <= current_version
908
      puts "OK (#{current_version})".green
909
    else
910
      puts "FAIL. Please update gitlab-shell to #{required_version} from #{current_version}".red
911 912
    end
  end
913

914
  def check_ruby_version
915
    required_version = Gitlab::VersionInfo.new(2, 1, 0)
916 917 918 919 920
    current_version = Gitlab::VersionInfo.parse(run(%W(ruby --version)))

    print "Ruby version >= #{required_version} ? ... "

    if current_version.valid? && required_version <= current_version
921
      puts "yes (#{current_version})".green
922 923 924 925 926 927 928 929 930
    else
      puts "no".red
      try_fixing_it(
        "Update your ruby to a version >= #{required_version} from #{current_version}"
      )
      fix_and_rerun
    end
  end

931
  def check_git_version
932
    required_version = Gitlab::VersionInfo.new(1, 7, 10)
933
    current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version)))
Sato Hiroyuki committed
934

935
    puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
Sato Hiroyuki committed
936 937
    print "Git version >= #{required_version} ? ... "

938
    if current_version.valid? && required_version <= current_version
939
      puts "yes (#{current_version})".green
940 941 942
    else
      puts "no".red
      try_fixing_it(
Sato Hiroyuki committed
943
        "Update your git to a version >= #{required_version} from #{current_version}"
944 945 946 947
      )
      fix_and_rerun
    end
  end
948

949 950 951 952
  def check_active_users
    puts "Active users: #{User.active.count}"
  end

953 954 955
  def omnibus_gitlab?
    Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails'
  end
956

957
  def sanitized_message(project)
958
    if should_sanitize?
959 960 961 962 963 964
      "#{project.namespace_id.to_s.yellow}/#{project.id.to_s.yellow} ... "
    else
      "#{project.name_with_namespace.yellow} ... "
    end
  end

965
  def should_sanitize?
966 967 968 969 970 971
    if ENV['SANITIZE'] == "true"
      true
    else
      false
    end
  end
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002

  def check_repo_integrity(repo_dir)
    puts "\nChecking repo at #{repo_dir.yellow}"

    git_fsck(repo_dir)
    check_config_lock(repo_dir)
    check_ref_locks(repo_dir)
  end

  def git_fsck(repo_dir)
    puts "Running `git fsck`".yellow
    system(*%W(#{Gitlab.config.git.bin_path} fsck), chdir: repo_dir)
  end

  def check_config_lock(repo_dir)
    config_exists = File.exist?(File.join(repo_dir,'config.lock'))
    config_output = config_exists ? 'yes'.red : 'no'.green
    puts "'config.lock' file exists?".yellow + " ... #{config_output}"
  end

  def check_ref_locks(repo_dir)
    lock_files = Dir.glob(File.join(repo_dir,'refs/heads/*.lock'))
    if lock_files.present?
      puts "Ref lock files exist:".red
      lock_files.each do |lock_file|
        puts "  #{lock_file}"
      end
    else
      puts "No ref lock files exist".green
    end
  end
1003
end