Method: AppRb::Command#deploy

Defined in:
lib/app-rb/command.rb

#deploy(target) ⇒ Object



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
# File 'lib/app-rb/command.rb', line 7

def deploy(target)
  @base = "#{@config.app}-#{Time.now.to_i}"
  start_at = Time.now
  user = AppRb::Util.just_cmd("git config user.name")

  # init
  current_hash = AppRb::Util::Consul.kv_get(@config.consul, @config.app, "hash")
  build_nodes = @config.nodes(@config.image["constraint"])
  if build_nodes.empty?
    puts "FATAL ERROR: no build nodes found"
    exit -1
  end
  pre_payloads = @config.pre_deploy.map do |pre|
    payload = {
      "nodes" => @config.nodes(pre["constraint"]),
      "cmd" => pre["cmd"],
      "opts" => pre["opts"] || [],
    }
    if payload["nodes"].empty?
      puts "FATAL ERROR: no pre deploy nodes found"
      exit -1
    end
    payload
  end
  deploy_payloads = @config.deploy.map { |key, section|
    nodes = @config.nodes(section["constraint"])
    if nodes.empty?
      puts "FATAL ERROR: no deploy `#{key}` nodes found"
      exit -1
    end
    {
      "key" => key,
      "nodes" => nodes,
      "amount" => (section["per"] ? section["per"]*nodes.count : section["amount"]),
      "cmd" => section["cmd"],
      "port" => section["port"],
      "check_url" => section["check_url"],
      "opts" => section["opts"] || [],
    }
  }
  if @config.run["constraint"]
    run_nodes = @config.nodes(@config.run["constraint"])
  else
    run_nodes = deploy_payloads.flat_map { |payload| payload["nodes"] }.uniq
  end
  if run_nodes.empty?
    puts "FATAL ERROR: no run nodes found"
    exit -1
  end
  cron_payloads = @config.cron.map { |key, section|
    nodes = @config.nodes(section["constraint"])
    if nodes.empty?
      puts "FATAL ERROR: no cron `#{key}` nodes found"
      exit -1
    end
    {
      "key" => key,
      "nodes" => nodes,
      "cmd" => section["cmd"],
      "at" => "#{section["minute"] || "*"} #{section["hour"] || "*"} #{section["day"] || "*"} #{section["month"] || "*"} #{section["weekday"] || "*"}"
    }
  }
  old_ips = AppRb::Util::Consul.kv_get(@config.consul, @config.app, "nodes").split(",")
  new_ips = (
    build_nodes.map(&:ip) +
    pre_payloads.flat_map { |p| p["nodes"].map(&:ip) } +
    deploy_payloads.flat_map { |p| p["nodes"].map(&:ip) } +
    run_nodes.map(&:ip) +
    cron_payloads.flat_map { |p| p["nodes"].map(&:ip) }
  ).uniq
  ips = (old_ips + new_ips).uniq
  AppRb::Util::Consul.kv_set(@config.consul, @config.app, "nodes", ips.join(","))

  # pre
  new_hash = prepare_image(build_nodes, target)
  if @config.slack?
    notify_slack(@config.slack_url, @config.slack_channel, "#{user} start deploy *#{@config.app}* - https://github.com/#{@config.image["repo"]}/compare/#{current_hash.to_s[0..6]}...#{new_hash.to_s[0..6]}")
  end
  pre_deploy(pre_payloads, new_hash)
  stop_bg_jobs(ips)

  # deploy
  do_deploy(deploy_payloads, new_hash)

  # switch
  blue_green(deploy_payloads, new_hash)

  # update one time scripts
  one_time_scripts(run_nodes, ips, new_hash)

  # update crons
  set_crons(cron_payloads, ips, new_hash)

  # clean
  stop_services(ips)
  clean_registry(current_hash, [current_hash, new_hash].uniq)
  remove_old_images(ips, [current_hash, new_hash].uniq)

  # finish
  AppRb::Util::Consul.kv_set(@config.consul, @config.app, "nodes", new_ips.join(","))

  if @config.slack?
    notify_slack(@config.slack_url, @config.slack_channel, "#{user} finish deploy *#{@config.app}* :cat: :cat: :cat: - #{((Time.now.to_f - start_at.to_f)/60).round(1)} minutes")
  end

  puts AppRb::Util.green("Done.")
  if current_hash != "" && !target && current_hash != target
    puts "to rollback fire: app-rb #{ARGV[0]} deploy #{current_hash}"
  end
end