summaryrefslogtreecommitdiff
path: root/lib/tasks/gitlab/shell.rake
blob: ee3ef9dad6eec959929be1f0e15293fad1be3cb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
namespace :gitlab do
  namespace :shell do
    desc "GitLab | Install or upgrade gitlab-shell"
    task :install, [:repo] => :gitlab_environment do |t, args|
      warn_user_is_not_gitlab

      default_version = Gitlab::Shell.version_required
      args.with_defaults(repo: 'https://gitlab.com/gitlab-org/gitlab-shell.git')

      gitlab_url = Gitlab.config.gitlab.url
      # gitlab-shell requires a / at the end of the url
      gitlab_url += '/' unless gitlab_url.end_with?('/')
      target_dir = Gitlab.config.gitlab_shell.path

      checkout_or_clone_version(version: default_version, repo: args.repo, target_dir: target_dir)

      # Make sure we're on the right tag
      Dir.chdir(target_dir) do
        config = {
          user: Gitlab.config.gitlab.user,
          gitlab_url: gitlab_url,
          http_settings: { self_signed_cert: false }.stringify_keys,
          auth_file: File.join(user_home, ".ssh", "authorized_keys"),
          redis: {
            bin: `which redis-cli`.chomp,
            namespace: "resque:gitlab"
          }.stringify_keys,
          log_level: "INFO",
          audit_usernames: false
        }.stringify_keys

        redis_url = URI.parse(ENV['REDIS_URL'] || "redis://localhost:6379")

        if redis_url.scheme == 'unix'
          config['redis']['socket'] = redis_url.path
        else
          config['redis']['host'] = redis_url.host
          config['redis']['port'] = redis_url.port
        end

        # Generate config.yml based on existing gitlab settings
        File.open("config.yml", "w+") {|f| f.puts config.to_yaml}

        [
          %w(bin/install) + repository_storage_paths_args,
          %w(bin/compile)
        ].each do |cmd|
          unless Kernel.system(*cmd)
            raise "command failed: #{cmd.join(' ')}"
          end
        end
      end

      # (Re)create hooks
      Rake::Task['gitlab:shell:create_hooks'].invoke

      Gitlab::Shell.ensure_secret_token!
    end

    desc "GitLab | Setup gitlab-shell"
    task setup: :gitlab_environment do
      setup
    end

    desc "GitLab | Build missing projects"
    task build_missing_projects: :gitlab_environment do
      Project.find_each(batch_size: 1000) do |project|
        path_to_repo = project.repository.path_to_repo
        if File.exist?(path_to_repo)
          print '-'
        else
          if Gitlab::Shell.new.create_repository(project.repository_storage,
                                              project.disk_path)
            print '.'
          else
            print 'F'
          end
        end
      end
    end

    desc 'Create or repair repository hooks symlink'
    task create_hooks: :gitlab_environment do
      warn_user_is_not_gitlab

      puts 'Creating/Repairing hooks symlinks for all repositories'
      system(*%W(#{Gitlab.config.gitlab_shell.path}/bin/create-hooks) + repository_storage_paths_args)
      puts 'done'.color(:green)
    end
  end

  def setup
    warn_user_is_not_gitlab

    ensure_write_to_authorized_keys_is_enabled

    unless ENV['force'] == 'yes'
      puts "This task will now rebuild the authorized_keys file."
      puts "You will lose any data stored in the authorized_keys file."
      ask_to_continue
      puts ""
    end

    Gitlab::Shell.new.remove_all_keys

    Key.find_in_batches(batch_size: 1000) do |keys|
      unless Gitlab::Shell.new.batch_add_keys(keys)
        puts "Failed to add keys...".color(:red)
        exit 1
      end
    end
  rescue Gitlab::TaskAbortedByUserError
    puts "Quitting...".color(:red)
    exit 1
  end

  def ensure_write_to_authorized_keys_is_enabled
    return if Gitlab::CurrentSettings.current_application_settings.authorized_keys_enabled

    puts authorized_keys_is_disabled_warning

    unless ENV['force'] == 'yes'
      puts 'Do you want to permanently enable the "Write to authorized_keys file" setting now?'
      ask_to_continue
    end

    puts 'Enabling the "Write to authorized_keys file" setting...'
    Gitlab::CurrentSettings.current_application_settings.update!(authorized_keys_enabled: true)

    puts 'Successfully enabled "Write to authorized_keys file"!'
    puts ''
  end

  def authorized_keys_is_disabled_warning
    <<-MSG.strip_heredoc
      WARNING

      The "Write to authorized_keys file" setting is disabled, which prevents
      the file from being rebuilt!

      It should be enabled for most GitLab installations. Large installations
      may wish to disable it as part of speeding up SSH operations.

      See https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html

      If you did not intentionally disable this option in Admin Area > Settings,
      then you may have been affected by the 9.3.0 bug in which the new setting
      was disabled by default.

      https://gitlab.com/gitlab-org/gitlab-ee/issues/2738

      It was reverted in 9.3.1 and fixed in 9.3.3, however, if Settings were
      saved while the setting was unchecked, then it is still disabled.
    MSG
  end
end