upgrader.rb 3.03 KB
Newer Older
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
1 2 3
module Gitlab
  class Upgrader
    def execute
4
      puts "GitLab #{current_version.major} upgrade tool"
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
5 6 7 8
      puts "Your version is #{current_version}"
      puts "Latest available version for GitLab #{current_version.major} is #{latest_version}"

      if latest_version?
9
        puts "You are using the latest GitLab version"
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
10 11
      else
        puts "Newer GitLab version is available"
12

13
        answer = if ARGV.first == "-y"
14 15
                   "yes"
                 else
16
                   prompt("Do you want to upgrade (yes/no)? ", %w{yes no})
17
                 end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
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

        if answer == "yes"
          upgrade
        else
          exit 0
        end
      end
    end

    def latest_version?
      current_version >= latest_version
    end

    def current_version
      @current_version ||= Gitlab::VersionInfo.parse(current_version_raw)
    end

    def latest_version
      @latest_version ||= Gitlab::VersionInfo.parse(latest_version_raw)
    end

    def current_version_raw
      File.read(File.join(gitlab_path, "VERSION")).strip
    end

    def latest_version_raw
Martins Polakovs's avatar
Martins Polakovs committed
44 45 46
      git_tags = fetch_git_tags
      git_tags = git_tags.select { |version| version =~ /v\d+\.\d+\.\d+\Z/ }
      git_versions = git_tags.map { |tag| Gitlab::VersionInfo.parse(tag.match(/v\d+\.\d+\.\d+/).to_s) }
47
      "v#{git_versions.sort.last}"
Martins Polakovs's avatar
Martins Polakovs committed
48 49 50
    end

    def fetch_git_tags
51
      remote_tags, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
Martins Polakovs's avatar
Martins Polakovs committed
52
      remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
53 54 55 56
    end

    def update_commands
      {
57 58 59
        "Stash changed files" => %W(#{Gitlab.config.git.bin_path} stash),
        "Get latest code" => %W(#{Gitlab.config.git.bin_path} fetch),
        "Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}),
60 61 62 63
        "Install gems" => %w(bundle),
        "Migrate DB" => %w(bundle exec rake db:migrate),
        "Recompile assets" => %w(bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile),
        "Clear cache" => %w(bundle exec rake cache:clear)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
64 65 66
      }
    end

67
    def env
68 69 70 71
      {
        'RAILS_ENV' => 'production',
        'NODE_ENV' => 'production'
      }
72 73
    end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
74 75
    def upgrade
      update_commands.each do |title, cmd|
76
        puts title
77
        puts " -> #{cmd.join(' ')}"
78

79
        if system(env, *cmd)
80
          puts " -> OK"
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
81
        else
82
          puts " -> FAILED"
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
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
          puts "Failed to upgrade. Try to repeat task or proceed with upgrade manually "
          exit 1
        end
      end

      puts "Done"
    end

    def gitlab_path
      File.expand_path(File.join(File.dirname(__FILE__), '../..'))
    end

    # Prompt the user to input something
    #
    # message - the message to display before input
    # choices - array of strings of acceptable answers or nil for any answer
    #
    # Returns the user's answer
    def prompt(message, choices = nil)
      begin
        print(message)
        answer = STDIN.gets.chomp
      end while !choices.include?(answer)
      answer
    end
  end
end