summaryrefslogtreecommitdiff
path: root/lib/tasks/gitlab/shell.rake
blob: ba93945bd031874cc642842648a67243c06c31c1 (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
namespace :gitlab do
  namespace :shell do
    desc "GitLab | Install or upgrade gitlab-shell"
    task :install, [:tag, :repo] => :environment do |t, args|
      warn_user_is_not_gitlab

      default_version = Gitlab::Shell.version_required
      default_version_tag = 'v' + default_version
      args.with_defaults(tag: default_version_tag, repo: "https://gitlab.com/gitlab-org/gitlab-shell.git")

      user = Gitlab.config.gitlab.user
      home_dir = Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
      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

      # Clone if needed
      if File.directory?(target_dir)
        Dir.chdir(target_dir) do
          system(*%W(Gitlab.config.git.bin_path} fetch --tags --quiet))
          system(*%W(Gitlab.config.git.bin_path} checkout --quiet #{default_version_tag}))
        end
      else
        system(*%W(#{Gitlab.config.git.bin_path} clone -- #{args.repo} #{target_dir}))
      end

      # Make sure we're on the right tag
      Dir.chdir(target_dir) do
        # First try to checkout without fetching
        # to avoid stalling tests if the Internet is down.
        reseted = reset_to_commit(args)

        unless reseted
          system(*%W(#{Gitlab.config.git.bin_path} fetch origin))
          reset_to_commit(args)
        end

        config = {
          user: user,
          gitlab_url: gitlab_url,
          http_settings: {self_signed_cert: false}.stringify_keys,
          auth_file: File.join(home_dir, ".ssh", "authorized_keys"),
          redis: {
            bin: %x{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}

        # Launch installation process
        system(*%W(bin/install) + repository_storage_paths_args)

        # (Re)create hooks
        system(*%W(bin/create-hooks) + repository_storage_paths_args)
      end

      # Required for debian packaging with PKGR: Setup .ssh/environment with
      # the current PATH, so that the correct ruby version gets loaded
      # Requires to set "PermitUserEnvironment yes" in sshd config (should not
      # be an issue since it is more than likely that there are no "normal"
      # user accounts on a gitlab server). The alternative is for the admin to
      # install a ruby (1.9.3+) in the global path.
      File.open(File.join(home_dir, ".ssh", "environment"), "w+") do |f|
        f.puts "PATH=#{ENV['PATH']}"
      end

      Gitlab::Shell.new.generate_and_link_secret_token
    end

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

    desc "GitLab | Build missing projects"
    task build_missing_projects: :environment do
      Project.find_each(batch_size: 1000) do |project|
        path_to_repo = project.repository.path_to_repo
        if File.exists?(path_to_repo)
          print '-'
        else
          if Gitlab::Shell.new.add_repository(project.repository_storage_path,
                                              project.path_with_namespace)
            print '.'
          else
            print 'F'
          end
        end
      end
    end
  end

  def setup
    warn_user_is_not_gitlab

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

    Gitlab::Shell.new.remove_all_keys

    Gitlab::Shell.new.batch_add_keys do |adder|
      Key.find_each(batch_size: 1000) do |key|
        adder.add_key(key.shell_id, key.key)
        print '.'
      end
    end
    puts ""

    unless $?.success?
      puts "Failed to add keys...".color(:red)
      exit 1
    end

  rescue Gitlab::TaskAbortedByUserError
    puts "Quitting...".color(:red)
    exit 1
  end

  def reset_to_commit(args)
    tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- #{args.tag}))

    unless status.zero?
      tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- origin/#{args.tag}))
    end

    tag = tag.strip
    system(*%W(#{Gitlab.config.git.bin_path} reset --hard #{tag}))
  end
end