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


R
Riyad Preukschas 已提交
10

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

17
      check_git_config
R
Riyad Preukschas 已提交
18 19 20
      check_database_config_exists
      check_database_is_not_sqlite
      check_migrations_are_up
21
      check_orphaned_group_members
R
Riyad Preukschas 已提交
22 23 24 25
      check_gitlab_config_exists
      check_gitlab_config_not_outdated
      check_log_writable
      check_tmp_writable
B
Ben Bodenmiller 已提交
26
      check_uploads
R
Riyad Preukschas 已提交
27 28
      check_init_script_exists
      check_init_script_up_to_date
H
Hiroyuki Sato 已提交
29
      check_projects_have_namespace
30
      check_redis_version
31
      check_ruby_version
32
      check_git_version
33
      check_active_users
R
Riyad Preukschas 已提交
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

R
Riyad Preukschas 已提交
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"
        )
R
Riyad Preukschas 已提交
89
        fix_and_rerun
R
Riyad Preukschas 已提交
90 91 92 93
      end
    end

    def check_database_is_not_sqlite
R
Riyad Preukschas 已提交
94
      print "Database is SQLite ... "
R
Riyad Preukschas 已提交
95 96 97

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

98
      unless File.read(database_config_file) =~ /adapter:\s+sqlite/
R
Riyad Preukschas 已提交
99
        puts "no".green
R
Riyad Preukschas 已提交
100
      else
R
Riyad Preukschas 已提交
101
        puts "yes".red
102
        puts "Please fix this by removing the SQLite entry from the database.yml".blue
R
Riyad Preukschas 已提交
103 104 105 106
        for_more_information(
          "https://github.com/gitlabhq/gitlabhq/wiki/Migrate-from-SQLite-to-MySQL",
          see_database_guide
        )
R
Riyad Preukschas 已提交
107
        fix_and_rerun
R
Riyad Preukschas 已提交
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"
        )
R
Riyad Preukschas 已提交
127
        fix_and_rerun
R
Riyad Preukschas 已提交
128 129 130 131
      end
    end

    def check_gitlab_config_not_outdated
R
Riyad Preukschas 已提交
132
      print "GitLab config outdated? ... "
R
Riyad Preukschas 已提交
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']
R
Riyad Preukschas 已提交
141
        puts "no".green
R
Riyad Preukschas 已提交
142
      else
R
Riyad Preukschas 已提交
143
        puts "yes".red
R
Riyad Preukschas 已提交
144
        try_fixing_it(
R
Riyad Preukschas 已提交
145
          "Backup your config/gitlab.yml",
R
Riyad Preukschas 已提交
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"
        )
R
Riyad Preukschas 已提交
152
        fix_and_rerun
R
Riyad Preukschas 已提交
153 154
      end
    end
155

R
Riyad Preukschas 已提交
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

R
Riyad Preukschas 已提交
164 165 166 167
      script_path = "/etc/init.d/gitlab"

      if File.exists?(script_path)
        puts "yes".green
N
Nihad Abbasov 已提交
168
      else
R
Riyad Preukschas 已提交
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"
        )
R
Riyad Preukschas 已提交
176
        fix_and_rerun
R
Riyad Preukschas 已提交
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")
R
Riyad Preukschas 已提交
189
      script_path = "/etc/init.d/gitlab"
190

R
Riyad Preukschas 已提交
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)
R
Riyad Preukschas 已提交
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"
        )
R
Riyad Preukschas 已提交
209
        fix_and_rerun
R
Riyad Preukschas 已提交
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))
R
Riyad Preukschas 已提交
217 218 219

      unless migration_status =~ /down\s+\d{14}/
        puts "yes".green
220
      else
R
Riyad Preukschas 已提交
221 222
        puts "no".red
        try_fixing_it(
223
          sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production")
R
Riyad Preukschas 已提交
224
        )
R
Riyad Preukschas 已提交
225
        fix_and_rerun
R
Riyad Preukschas 已提交
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

R
Riyad Preukschas 已提交
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}",
B
bassrock 已提交
253
          "sudo chmod -R u+rwX #{log_path}"
R
Riyad Preukschas 已提交
254 255 256 257
        )
        for_more_information(
          see_installation_guide_section "GitLab"
        )
R
Riyad Preukschas 已提交
258
        fix_and_rerun
R
Riyad Preukschas 已提交
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}",
B
bassrock 已提交
273
          "sudo chmod -R u+rwX #{tmp_path}"
R
Riyad Preukschas 已提交
274 275
        )
        for_more_information(
B
Ben Bodenmiller 已提交
276 277 278 279 280
          see_installation_guide_section "GitLab"
        )
        fix_and_rerun
      end
    end
281

B
Ben Bodenmiller 已提交
282 283 284 285 286 287
    def check_uploads
      print "Uploads directory setup correctly? ... "

      unless File.directory?(Rails.root.join('public/uploads'))
        puts "no".red
        try_fixing_it(
288
          "sudo -u #{gitlab_user} mkdir -m 0700 #{Rails.root}/public/uploads"
B
Ben Bodenmiller 已提交
289 290 291 292 293 294 295 296 297 298 299
        )
        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')

300
      if File.stat(upload_path).mode == 040700
B
Ben Bodenmiller 已提交
301 302 303 304 305
        unless Dir.exists?(upload_path_tmp)
          puts 'skipped (no tmp uploads folder yet)'.magenta
          return
        end

306 307 308
        # If tmp upload dir has incorrect permissions, assume others do as well
        # Verify drwx------ permissions
        if File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp)
B
Ben Bodenmiller 已提交
309 310 311 312 313 314
          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 {} \\;",
315
            "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
B
Ben Bodenmiller 已提交
316 317 318 319 320 321 322 323 324
          )
          for_more_information(
            see_installation_guide_section "GitLab"
          )
          fix_and_rerun
        end
      else
        puts "no".red
        try_fixing_it(
325
          "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
B
Ben Bodenmiller 已提交
326 327
        )
        for_more_information(
R
Riyad Preukschas 已提交
328 329
          see_installation_guide_section "GitLab"
        )
R
Riyad Preukschas 已提交
330
        fix_and_rerun
R
Riyad Preukschas 已提交
331
      end
R
Riyad Preukschas 已提交
332
    end
333

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

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

356
  namespace :gitlab_shell do
357
    desc "GitLab | Check the configuration of GitLab Shell"
R
Riyad Preukschas 已提交
358
    task check: :environment  do
R
Riyad Preukschas 已提交
359
      warn_user_is_not_gitlab
B
Ben Bodenmiller 已提交
360
      start_checking "GitLab Shell"
R
Riyad Preukschas 已提交
361

362
      check_gitlab_shell
R
Riyad Preukschas 已提交
363
      check_repo_base_exists
364
      check_repo_base_is_not_symlink
R
Riyad Preukschas 已提交
365 366
      check_repo_base_user_and_group
      check_repo_base_permissions
367
      check_repos_hooks_directory_is_link
368
      check_gitlab_shell_self_test
R
Riyad Preukschas 已提交
369

B
Ben Bodenmiller 已提交
370
      finished_checking "GitLab Shell"
R
Riyad Preukschas 已提交
371 372 373 374 375 376 377 378 379
    end


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

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

380
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
R
Riyad Preukschas 已提交
381 382 383 384 385 386 387

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

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

402
      repo_base_path = Gitlab.config.gitlab_shell.repos_path
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
      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

R
Riyad Preukschas 已提交
419
    def check_repo_base_permissions
420
      print "Repo base access is drwxrws---? ... "
R
Riyad Preukschas 已提交
421

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

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

    def check_repo_base_user_and_group
445 446 447
      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}? ... "
R
Riyad Preukschas 已提交
448

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

455 456 457
      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
R
Riyad Preukschas 已提交
458
        puts "yes".green
459
      else
R
Riyad Preukschas 已提交
460
        puts "no".red
461
        puts "  User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".blue
R
Riyad Preukschas 已提交
462
        try_fixing_it(
463
          "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}"
R
Riyad Preukschas 已提交
464 465
        )
        for_more_information(
B
Ben Bodenmiller 已提交
466
          see_installation_guide_section "GitLab Shell"
R
Riyad Preukschas 已提交
467
        )
R
Riyad Preukschas 已提交
468
        fix_and_rerun
R
Riyad Preukschas 已提交
469 470 471
      end
    end

472 473
    def check_repos_hooks_directory_is_link
      print "hooks directories in repos are links: ... "
R
Riyad Preukschas 已提交
474

475
      gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
476

R
Riyad Preukschas 已提交
477 478 479 480 481
      unless Project.count > 0
        puts "can't check, you have no projects".magenta
        return
      end
      puts ""
482

R
Riyad Preukschas 已提交
483
      Project.find_each(batch_size: 100) do |project|
M
Marin Jankovski 已提交
484
        print sanitized_message(project)
485
        project_hook_directory = File.join(project.repository.path_to_repo, "hooks")
486

R
Riyad Preukschas 已提交
487 488
        if project.empty_repo?
          puts "repository is empty".magenta
489 490
        elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) &&
            (File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path))
491
          puts 'ok'.green
R
Riyad Preukschas 已提交
492
        else
493 494
          puts "wrong or missing hooks".red
          try_fixing_it(
495
            sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')}"),
496 497 498 499 500 501 502
            '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
503
        end
504

505
      end
R
Riyad Preukschas 已提交
506
    end
R
Riyad Preukschas 已提交
507

508
    def check_gitlab_shell_self_test
509
      gitlab_shell_repo_base = gitlab_shell_path
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
      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

H
Hiroyuki Sato 已提交
525 526 527 528 529 530 531 532 533 534
    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|
M
Marin Jankovski 已提交
535
        print sanitized_message(project)
H
Hiroyuki Sato 已提交
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550

        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
R
Riyad Preukschas 已提交
551 552 553 554

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

555 556
    def gitlab_shell_path
      Gitlab.config.gitlab_shell.path
R
Riyad Preukschas 已提交
557 558
    end

559
    def gitlab_shell_version
560
      Gitlab::Shell.new.version
R
Riyad Preukschas 已提交
561 562
    end

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

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

    def gitlab_shell_patch_version
572
      Gitlab::Shell.version_required.split('.')[2].to_i
573
    end
R
Riyad Preukschas 已提交
574
  end
575

R
Riyad Preukschas 已提交
576 577


R
Riyad Preukschas 已提交
578
  namespace :sidekiq do
579
    desc "GitLab | Check the configuration of Sidekiq"
R
Riyad Preukschas 已提交
580
    task check: :environment  do
R
Riyad Preukschas 已提交
581
      warn_user_is_not_gitlab
R
Riyad Preukschas 已提交
582
      start_checking "Sidekiq"
R
Riyad Preukschas 已提交
583

R
Riyad Preukschas 已提交
584
      check_sidekiq_running
585
      only_one_sidekiq_running
R
Riyad Preukschas 已提交
586

R
Riyad Preukschas 已提交
587
      finished_checking "Sidekiq"
R
Riyad Preukschas 已提交
588 589 590 591 592 593
    end


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

R
Riyad Preukschas 已提交
594
    def check_sidekiq_running
R
Riyad Preukschas 已提交
595 596
      print "Running? ... "

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

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

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

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

637

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

644
      if Gitlab.config.incoming_email.enabled
645 646
        check_address_formatted_correctly
        check_imap_authentication
D
Douwe Maan 已提交
647

D
Douwe Maan 已提交
648 649 650 651 652 653
        if Rails.env.production?
          check_initd_configured_correctly
          check_mail_room_running
        else
          check_foreman_configured_correctly
        end
654 655 656 657 658 659 660 661 662 663 664 665 666 667
      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? ... "

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

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

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

687 688 689 690 691 692 693 694 695 696
      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(
697
          "doc/incoming_email/README.md"
698 699 700 701 702
        )
        fix_and_rerun
      end
    end

D
Douwe Maan 已提交
703 704 705 706 707
    def check_foreman_configured_correctly
      print "Foreman configured correctly? ... "

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

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

722 723 724 725 726 727 728 729 730 731
    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

D
Douwe Maan 已提交
732
      if mail_room_running?
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
        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? ... "

750
      config = Gitlab.config.incoming_email
751 752 753

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

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

D
Douwe Maan 已提交
777
    def mail_room_running?
778
      ps_ux, _ = Gitlab::Popen.popen(%W(ps ux))
D
Douwe Maan 已提交
779
      ps_ux.include?("mail_room")
780 781 782
    end
  end

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

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

      finished_checking "LDAP"
    end

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

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

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

V
Vinnie Okada 已提交
817
  namespace :repo do
818
    desc "GitLab | Check the integrity of the repositories managed by GitLab"
V
Vinnie Okada 已提交
819 820 821 822 823 824 825
    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, '*'))
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
        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
V
Vinnie Okada 已提交
847 848 849 850
      end
    end
  end

R
Riyad Preukschas 已提交
851 852 853
  # Helper methods
  ##########################

R
Riyad Preukschas 已提交
854
  def fix_and_rerun
R
Riyad Preukschas 已提交
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 880
    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

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

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

R
Riyad Preukschas 已提交
889 890 891 892 893 894 895 896 897 898 899 900 901
  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
902 903

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

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

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

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

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

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

936
    puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
S
Sato Hiroyuki 已提交
937 938
    print "Git version >= #{required_version} ? ... "

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

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

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

M
Marin Jankovski 已提交
958
  def sanitized_message(project)
959
    if should_sanitize?
M
Marin Jankovski 已提交
960 961 962 963 964 965
      "#{project.namespace_id.to_s.yellow}/#{project.id.to_s.yellow} ... "
    else
      "#{project.name_with_namespace.yellow} ... "
    end
  end

966
  def should_sanitize?
967 968 969 970 971 972
    if ENV['SANITIZE'] == "true"
      true
    else
      false
    end
  end
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 1003

  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
1004
end