etsy-deployinator 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +368 -0
- data/Rakefile +16 -0
- data/bin/deployinator-tailer.rb +78 -0
- data/deployinator.gemspec +31 -0
- data/lib/deployinator.rb +114 -0
- data/lib/deployinator/app.rb +204 -0
- data/lib/deployinator/base.rb +58 -0
- data/lib/deployinator/config.rb +7 -0
- data/lib/deployinator/controller.rb +147 -0
- data/lib/deployinator/helpers.rb +610 -0
- data/lib/deployinator/helpers/deploy.rb +68 -0
- data/lib/deployinator/helpers/dsh.rb +42 -0
- data/lib/deployinator/helpers/git.rb +348 -0
- data/lib/deployinator/helpers/plugin.rb +50 -0
- data/lib/deployinator/helpers/stack-tail.rb +32 -0
- data/lib/deployinator/helpers/version.rb +62 -0
- data/lib/deployinator/helpers/view.rb +67 -0
- data/lib/deployinator/logging.rb +16 -0
- data/lib/deployinator/plugin.rb +7 -0
- data/lib/deployinator/stack-tail.rb +34 -0
- data/lib/deployinator/static/css/diff_style.css +283 -0
- data/lib/deployinator/static/css/highlight.css +235 -0
- data/lib/deployinator/static/css/style.css +1223 -0
- data/lib/deployinator/static/js/flot/jquery.flot.min.js +1 -0
- data/lib/deployinator/static/js/flot/jquery.flot.selection.js +299 -0
- data/lib/deployinator/static/js/jquery-1.8.3.min.js +2 -0
- data/lib/deployinator/static/js/jquery-ui-1.8.24.min.js +5 -0
- data/lib/deployinator/static/js/jquery.timed_bar.js +36 -0
- data/lib/deployinator/tasks/initialize.rake +84 -0
- data/lib/deployinator/tasks/tests.rake +22 -0
- data/lib/deployinator/templates/deploys_status.mustache +42 -0
- data/lib/deployinator/templates/generic_single_push.mustache +64 -0
- data/lib/deployinator/templates/index.mustache +12 -0
- data/lib/deployinator/templates/layout.mustache +604 -0
- data/lib/deployinator/templates/log.mustache +24 -0
- data/lib/deployinator/templates/log_table.mustache +90 -0
- data/lib/deployinator/templates/messageboxes.mustache +29 -0
- data/lib/deployinator/templates/run_logs.mustache +15 -0
- data/lib/deployinator/templates/scroll_control.mustache +8 -0
- data/lib/deployinator/templates/stream.mustache +13 -0
- data/lib/deployinator/version.rb +3 -0
- data/lib/deployinator/views/deploys_status.rb +22 -0
- data/lib/deployinator/views/index.rb +14 -0
- data/lib/deployinator/views/layout.rb +48 -0
- data/lib/deployinator/views/log.rb +12 -0
- data/lib/deployinator/views/log_table.rb +35 -0
- data/lib/deployinator/views/run_logs.rb +32 -0
- data/templates/app.rb.erb +7 -0
- data/templates/config.ru.erb +10 -0
- data/templates/helper.rb.erb +15 -0
- data/templates/stack.rb.erb +17 -0
- data/templates/template.mustache +1 -0
- data/templates/view.rb.erb +7 -0
- data/test/unit/helpers_dsh_test.rb +40 -0
- data/test/unit/helpers_test.rb +77 -0
- data/test/unit/version_test.rb +104 -0
- metadata +245 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'deployinator/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "etsy-deployinator"
|
8
|
+
gem.version = Deployinator::VERSION
|
9
|
+
gem.authors = ["JPaul"]
|
10
|
+
gem.email = ["jpaul@etsy.com"]
|
11
|
+
gem.description = %q{Deployinator as a Gem}
|
12
|
+
gem.summary = %q{Rewrite of deployinator to be a gem}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency "mocha"
|
21
|
+
|
22
|
+
gem.add_runtime_dependency "rake"
|
23
|
+
gem.add_runtime_dependency "json"
|
24
|
+
gem.add_runtime_dependency "mustache", "~> 0.99"
|
25
|
+
gem.add_runtime_dependency "pony"
|
26
|
+
gem.add_runtime_dependency "tlsmail"
|
27
|
+
gem.add_runtime_dependency "eventmachine"
|
28
|
+
gem.add_runtime_dependency "eventmachine-tail"
|
29
|
+
gem.add_runtime_dependency "em-websocket"
|
30
|
+
gem.add_runtime_dependency "sinatra", ">=1.4.3"
|
31
|
+
end
|
data/lib/deployinator.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'deployinator/version'
|
2
|
+
# = Deployinator
|
3
|
+
#
|
4
|
+
# This is the main entry point for all things in the Deployination.
|
5
|
+
module Deployinator
|
6
|
+
|
7
|
+
# = Config settings
|
8
|
+
class << self
|
9
|
+
# File to log to
|
10
|
+
attr_accessor :log_file
|
11
|
+
|
12
|
+
# Your company domain name
|
13
|
+
attr_accessor :domain
|
14
|
+
|
15
|
+
# Hostname where deployinator runs
|
16
|
+
attr_accessor :hostname
|
17
|
+
|
18
|
+
# Default username for passwordless ssh
|
19
|
+
attr_accessor :default_user
|
20
|
+
|
21
|
+
# Default github_host
|
22
|
+
attr_accessor :github_host
|
23
|
+
|
24
|
+
# Bug or issue tracker - proc that takes the issue id as an argument
|
25
|
+
# ex: Deployinator.issue_tracker = proc {|issue| "http://foo/browse/#{issue}"}
|
26
|
+
attr_accessor :issue_tracker
|
27
|
+
|
28
|
+
# a hash for context specifics settings (test,dev,production) of deployinator itself
|
29
|
+
attr_accessor :app_context
|
30
|
+
|
31
|
+
# Your install root
|
32
|
+
attr_accessor :root_dir
|
33
|
+
|
34
|
+
# Git info per stack
|
35
|
+
attr_accessor :git_info_for_stack
|
36
|
+
|
37
|
+
# Deploy Host
|
38
|
+
attr_accessor :deploy_host
|
39
|
+
|
40
|
+
# Timing Log path
|
41
|
+
attr_accessor :timing_log_path
|
42
|
+
|
43
|
+
# Log path
|
44
|
+
attr_accessor :log_path
|
45
|
+
|
46
|
+
attr_accessor :git_sha_length
|
47
|
+
|
48
|
+
attr_accessor :global_plugins
|
49
|
+
|
50
|
+
attr_accessor :stack_plugins
|
51
|
+
|
52
|
+
attr_accessor :stack_tailer_port
|
53
|
+
|
54
|
+
attr_accessor :admin_groups
|
55
|
+
@admin_groups = []
|
56
|
+
|
57
|
+
# the controller class. defaults to Deployinator::Controller
|
58
|
+
# if you override this it should be a subclass of Deployinator::Controller
|
59
|
+
attr_accessor :deploy_controller
|
60
|
+
|
61
|
+
def initialize
|
62
|
+
@stack_plugins = {}
|
63
|
+
@global_plugins = []
|
64
|
+
@admin_groups = []
|
65
|
+
end
|
66
|
+
|
67
|
+
# Base root path
|
68
|
+
# Takes an optional argument of a string or array and returns the path(s)
|
69
|
+
# From the root of deployinator
|
70
|
+
def root(path = nil)
|
71
|
+
base = Deployinator.root_dir
|
72
|
+
path ? File.join(base, path) : base
|
73
|
+
end
|
74
|
+
|
75
|
+
# is a log file defined?
|
76
|
+
def log_file?
|
77
|
+
log_file
|
78
|
+
end
|
79
|
+
|
80
|
+
# Running environment for deployinator
|
81
|
+
# This is taken from RACK_ENV or RAILS_ENV
|
82
|
+
# *note* this is different from deployinator's concept of stacks/environments
|
83
|
+
def env
|
84
|
+
ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Gets all the stack files in the stack directory
|
88
|
+
def get_stack_files
|
89
|
+
Dir[Deployinator.root(["stacks", "*.rb"])]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Gets all the stack names without the .rb extension
|
93
|
+
def get_stacks
|
94
|
+
self.get_stack_files.sort.map do |file|
|
95
|
+
File.basename(file, ".rb")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
Deployinator.root_dir = Dir.pwd
|
102
|
+
Deployinator.app_context = {}
|
103
|
+
Deployinator.admin_groups = []
|
104
|
+
Deployinator.global_plugins = []
|
105
|
+
Deployinator.log_file = Deployinator.root(["log", "development.log"])
|
106
|
+
Deployinator.log_path = Deployinator.root(["log", "deployinator.log"])
|
107
|
+
Deployinator.timing_log_path = Deployinator.root(["log", "deployinator-timing.log"])
|
108
|
+
Deployinator.git_sha_length = "10"
|
109
|
+
Deployinator.default_user = `whoami`
|
110
|
+
Deployinator.stack_tailer_port = 7778
|
111
|
+
Deployinator.github_host = 'github.com'
|
112
|
+
Deployinator.app_context['context'] = 'dev'
|
113
|
+
|
114
|
+
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'mustache/sinatra'
|
3
|
+
require 'deployinator'
|
4
|
+
require 'deployinator/controller'
|
5
|
+
require 'deployinator/helpers'
|
6
|
+
require 'deployinator/helpers/deploy'
|
7
|
+
require 'deployinator/helpers/version'
|
8
|
+
require 'deployinator/helpers/git'
|
9
|
+
require 'deployinator/helpers/plugin'
|
10
|
+
require 'deployinator/views/index'
|
11
|
+
require 'deployinator/views/log'
|
12
|
+
require 'deployinator/views/run_logs'
|
13
|
+
require 'deployinator/views/log_table'
|
14
|
+
require 'deployinator/views/deploys_status'
|
15
|
+
|
16
|
+
module Deployinator
|
17
|
+
class DeployinatorApp < Sinatra::Base
|
18
|
+
register Mustache::Sinatra
|
19
|
+
helpers Deployinator::Helpers,
|
20
|
+
Deployinator::Helpers::DeployHelpers,
|
21
|
+
Deployinator::Helpers::GitHelpers,
|
22
|
+
Deployinator::Helpers::VersionHelpers,
|
23
|
+
Deployinator::Helpers::PluginHelpers
|
24
|
+
|
25
|
+
def github_diff_url(params)
|
26
|
+
stack = params[:stack].intern
|
27
|
+
gh_info = git_info_for_stack[stack]
|
28
|
+
"https://#{which_github_host(stack)}/#{gh_info[:user]}/#{gh_info[:repository]}/compare/#{params[:r1]}...#{params[:r2]}"
|
29
|
+
end
|
30
|
+
|
31
|
+
set :mustache, {
|
32
|
+
:views => Deployinator.root('views'),
|
33
|
+
:templates => Deployinator.root('templates'),
|
34
|
+
:namespace => Deployinator::Views
|
35
|
+
}
|
36
|
+
|
37
|
+
set :public_folder, Deployinator.root('public')
|
38
|
+
set :static, true
|
39
|
+
|
40
|
+
before do
|
41
|
+
register_plugins(nil)
|
42
|
+
init(env)
|
43
|
+
@disabled_override = params[:override].nil? ? false : true
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/' do
|
47
|
+
mustache Deployinator::Views::Index
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/run_logs/view/:log' do
|
51
|
+
template = open("#{File.dirname(__FILE__)}/templates/stream.mustache").read
|
52
|
+
template.gsub!("{{ yield }}", "{{{yield}}}")
|
53
|
+
Mustache.render(template, :yield => open("run_logs/" + params[:log]).read)
|
54
|
+
end
|
55
|
+
|
56
|
+
get '/run_logs/?' do
|
57
|
+
@stack = "log"
|
58
|
+
@params = params
|
59
|
+
mustache Deployinator::Views::RunLogs
|
60
|
+
end
|
61
|
+
|
62
|
+
get '/run_logs/latest/:log_type' do
|
63
|
+
run_logs = get_run_logs(:limit => 1, :type => params[:log_type])
|
64
|
+
if run_logs.count == 1
|
65
|
+
run_log = run_logs.first[:name]
|
66
|
+
redirect "/run_logs/view/#{run_log}"
|
67
|
+
else
|
68
|
+
redirect "/"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
get '/log/?' do
|
73
|
+
@stack = "log"
|
74
|
+
@params = params
|
75
|
+
mustache Deployinator::Views::LogTable
|
76
|
+
end
|
77
|
+
|
78
|
+
get '/:stack/can-deploy' do
|
79
|
+
lock_info = push_lock_info(params["stack"]) || {}
|
80
|
+
lock_info[:can_deploy] = lock_info.empty?
|
81
|
+
content_type "application/json"
|
82
|
+
lock_info.to_json
|
83
|
+
end
|
84
|
+
|
85
|
+
get '/diff/:stack/:r1/:r2/?' do
|
86
|
+
@stack = params[:stack]
|
87
|
+
diff(params["r1"], params["r2"], params["stack"], params[:time])
|
88
|
+
end
|
89
|
+
|
90
|
+
get '/diff/:stack/:r1/:r2/github/?' do
|
91
|
+
redirect github_diff_url(params)
|
92
|
+
end
|
93
|
+
|
94
|
+
get '/head_rev/:stack' do
|
95
|
+
git_head_rev(params[:stack]).chomp
|
96
|
+
end
|
97
|
+
|
98
|
+
get '/:thing' do
|
99
|
+
@stack = params[:thing]
|
100
|
+
@params = params
|
101
|
+
register_plugins(@stack)
|
102
|
+
begin
|
103
|
+
mustache @stack
|
104
|
+
rescue Errno::ENOENT
|
105
|
+
pass
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
get '/:stack/remove-lock' do
|
110
|
+
stack = params[:stack]
|
111
|
+
unlock_pushes(stack) if can_remove_stack_lock?
|
112
|
+
redirect "/#{stack}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# return a list of all deploys as JSON
|
116
|
+
get '/deploys/?' do
|
117
|
+
get_list_of_deploys.to_json
|
118
|
+
end
|
119
|
+
|
120
|
+
get '/static/css/style.css?:version' do
|
121
|
+
send_file "#{File.dirname(__FILE__)}/static/css/style.css"
|
122
|
+
end
|
123
|
+
|
124
|
+
get '/static/css/diff_style.css' do
|
125
|
+
send_file "#{File.dirname(__FILE__)}/static/css/diff_style.css"
|
126
|
+
end
|
127
|
+
|
128
|
+
get '/static/css/highlight.css' do
|
129
|
+
send_file "#{File.dirname(__FILE__)}/static/css/highlight.css"
|
130
|
+
end
|
131
|
+
|
132
|
+
get '/js/flot/jquery.flot.min.js' do
|
133
|
+
send_file "#{File.dirname(__FILE__)}/static/js/flot/jquery.flot.min.js"
|
134
|
+
end
|
135
|
+
|
136
|
+
get '/js/flot/jquery.flot.selection.js' do
|
137
|
+
send_file "#{File.dirname(__FILE__)}/static/js/flot/jquery.flot.selection.js"
|
138
|
+
end
|
139
|
+
|
140
|
+
get '/js/jquery-1.8.3.min.js' do
|
141
|
+
send_file "#{File.dirname(__FILE__)}/static/js/jquery-1.8.3.min.js"
|
142
|
+
end
|
143
|
+
|
144
|
+
get '/js/jquery-ui-1.8.24.min.js' do
|
145
|
+
send_file "#{File.dirname(__FILE__)}/static/js/jquery-ui-1.8.24.min.js"
|
146
|
+
end
|
147
|
+
|
148
|
+
get '/js/jquery.timed_bar.js' do
|
149
|
+
send_file "#{File.dirname(__FILE__)}/static/js/jquery.timed_bar.js"
|
150
|
+
end
|
151
|
+
|
152
|
+
get '/deploys_status' do
|
153
|
+
mustache Deployinator::Views::DeploysStatus
|
154
|
+
end
|
155
|
+
|
156
|
+
get '/log.txt' do
|
157
|
+
content_type :text
|
158
|
+
`tac #{Deployinator.log_path}#{ " | head -n #{params[:limit]}" if params[:limit]}`
|
159
|
+
end
|
160
|
+
|
161
|
+
get '/timing_log.txt' do
|
162
|
+
content_type :text
|
163
|
+
`tac #{Deployinator.timing_log_path}`
|
164
|
+
end
|
165
|
+
|
166
|
+
get '/ti/:stack/:env' do
|
167
|
+
@stack = params[:stack]
|
168
|
+
average_duration(params["env"], params["stack"]).to_s
|
169
|
+
end
|
170
|
+
|
171
|
+
# this is the API endpoint to asynchronously start a deploy that runs in
|
172
|
+
# the background.
|
173
|
+
post '/deploys/?' do
|
174
|
+
params[:username] = @username
|
175
|
+
params[:block] = Proc.new { |line| foo = line }
|
176
|
+
deploy_running = is_deploy_active?(params[:stack], params[:stage])
|
177
|
+
|
178
|
+
# if this deploy is already running, return 403
|
179
|
+
if deploy_running
|
180
|
+
return 403
|
181
|
+
end
|
182
|
+
|
183
|
+
fork {
|
184
|
+
Signal.trap("HUP") { exit }
|
185
|
+
Deployinator.setup_logging
|
186
|
+
$0 = get_deploy_process_title(params[:stack], params[:stage])
|
187
|
+
controller = Deployinator.deploy_controller || Deployinator::Controller
|
188
|
+
d = controller.new
|
189
|
+
d.run(params)
|
190
|
+
}
|
191
|
+
200
|
192
|
+
end
|
193
|
+
|
194
|
+
delete '/deploys/?' do
|
195
|
+
return 400 if (params[:stack].nil? || params[:stage].nil?)
|
196
|
+
res = stop_deploy(params[:stack], params[:stage])
|
197
|
+
unless res
|
198
|
+
return 404
|
199
|
+
end
|
200
|
+
|
201
|
+
200
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
require 'deployinator'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift Deployinator.root unless $LOAD_PATH.include? Deployinator.root
|
8
|
+
$LOAD_PATH.unshift Deployinator.root("lib") unless $LOAD_PATH.include? Deployinator.root("lib")
|
9
|
+
|
10
|
+
require 'deployinator/config'
|
11
|
+
|
12
|
+
require "socket"
|
13
|
+
require 'pony'
|
14
|
+
|
15
|
+
require 'sinatra/base'
|
16
|
+
require "mustache/sinatra"
|
17
|
+
|
18
|
+
# Silence mustache warnings
|
19
|
+
module Mustache::Sinatra::Helpers
|
20
|
+
def warn(msg); nil; end
|
21
|
+
end
|
22
|
+
|
23
|
+
# ruby Std lib
|
24
|
+
require 'open3'
|
25
|
+
require 'benchmark'
|
26
|
+
require 'net/http'
|
27
|
+
require 'open-uri'
|
28
|
+
require 'uri'
|
29
|
+
require 'time'
|
30
|
+
require 'json'
|
31
|
+
require 'resolv'
|
32
|
+
|
33
|
+
require "deployinator/helpers"
|
34
|
+
require "deployinator/views/layout"
|
35
|
+
require "deployinator/helpers/view"
|
36
|
+
require "deployinator/app"
|
37
|
+
|
38
|
+
class Mustache
|
39
|
+
include Deployinator::Helpers,
|
40
|
+
Deployinator::Helpers::ViewHelpers
|
41
|
+
end
|
42
|
+
|
43
|
+
# Ruby 1.8.6 is teh LAMEZ0Rz
|
44
|
+
unless Symbol.respond_to?(:to_proc)
|
45
|
+
class Symbol
|
46
|
+
def to_proc
|
47
|
+
Proc.new { |obj, *args| obj.send(self, *args) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
unless String.respond_to?(:start_with?)
|
53
|
+
class String
|
54
|
+
def start_with?(str)
|
55
|
+
self.index(str) == 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'deployinator'
|
2
|
+
require 'deployinator/helpers'
|
3
|
+
require 'deployinator/helpers/version'
|
4
|
+
require "deployinator/helpers/plugin"
|
5
|
+
|
6
|
+
module Deployinator
|
7
|
+
|
8
|
+
# Public: this class represents the Deploy object with all the properties
|
9
|
+
# the different helper and stack methods need to do the deploy. It is
|
10
|
+
# basically an almost empty class and gets all of its functionality by the
|
11
|
+
# modules it includes/extends based on the stack we are deploying.
|
12
|
+
class Deploy
|
13
|
+
include Deployinator::Helpers,
|
14
|
+
Deployinator::Helpers::VersionHelpers,
|
15
|
+
Deployinator::Helpers::PluginHelpers
|
16
|
+
|
17
|
+
# Public: initialize the deploy class with instance variables that are
|
18
|
+
# needed by the deploy methods, runlog helpers and all that
|
19
|
+
#
|
20
|
+
# Params:
|
21
|
+
# args - hash which at least has the following fields:
|
22
|
+
# { :username => "name of the person that is deploying",
|
23
|
+
# :stack => "the name of the stack to deploy",
|
24
|
+
# :stage => "stage of the stack to deploy"
|
25
|
+
# }
|
26
|
+
#
|
27
|
+
# Returns the runlog filename
|
28
|
+
def initialize(args)
|
29
|
+
@deploy_start_time = Time.now.to_i
|
30
|
+
@start_time = Time.now.to_i
|
31
|
+
@username = args[:username]
|
32
|
+
@host = `hostname -s`
|
33
|
+
@stack = args[:stack]
|
34
|
+
@method = args[:method]
|
35
|
+
@filename = "#{@deploy_start_time}-#{@username}-#{args[:method]}.html"
|
36
|
+
@deploy_time = Time.now.to_i
|
37
|
+
|
38
|
+
# This gets the runlog output on the console; is used by log_and_stream
|
39
|
+
@block = args[:block] || Proc.new do |output|
|
40
|
+
$stdout.write output.gsub!(/(<[^>]*>)|\n|\t/s) {" "}
|
41
|
+
$stdout.write "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_filename
|
46
|
+
@filename
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_deploy_time
|
50
|
+
@deploy_time
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Public: the main Controller class knows how to extract options from the
|
55
|
+
# options argument it gets passed from its run method and then prepares the
|
56
|
+
# Deploy class to be ready to deploy.
|
57
|
+
class Controller
|
58
|
+
|
59
|
+
# Public: get the correct method name for the stage to deploy. This allows us to
|
60
|
+
# call things princess and prod even though the methods in the stacks have crazy
|
61
|
+
# names.
|
62
|
+
#
|
63
|
+
# Params:
|
64
|
+
# stack - the name of the stack to deploy
|
65
|
+
# stage - the stage of the stack to deploy
|
66
|
+
#
|
67
|
+
# Returns the name of the deploy method as a String which then can be sent
|
68
|
+
# to the Deploy class
|
69
|
+
def stage_to_method(stack, stage)
|
70
|
+
"#{stack}_#{stage}"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Public: run the actual deploy from the given parameters
|
74
|
+
#
|
75
|
+
# Params:
|
76
|
+
# options - hash that includes at least the following fields:
|
77
|
+
# { :username => "name of the user that is deploying",
|
78
|
+
# :stack => "name of the stack to deploy",
|
79
|
+
# :stage => "name of the stage of the stack to deploy"
|
80
|
+
# }
|
81
|
+
#
|
82
|
+
# Returns nothing
|
83
|
+
def run(options)
|
84
|
+
options[:method] = stage_to_method(options[:stack], options[:stage])
|
85
|
+
if options[:method].nil?
|
86
|
+
raise "No method defined for me to call: #{options[:stack]}, #{options[:stage]}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# config pus needs :env populated here
|
90
|
+
options[:env] = {
|
91
|
+
:username => options[:username]
|
92
|
+
}
|
93
|
+
|
94
|
+
if Deployinator.get_stacks.include?(options[:stack])
|
95
|
+
require "stacks/#{options[:stack]}"
|
96
|
+
klass = "#{Mustache.classify(options[:stack])}Deploy"
|
97
|
+
deploy_class = Deployinator::Stacks.const_get("#{klass}")
|
98
|
+
else
|
99
|
+
raise "No such stack #{options[:stack]}"
|
100
|
+
end
|
101
|
+
|
102
|
+
deploy_instance = deploy_class.new(options)
|
103
|
+
deploy_instance.register_plugins(options[:stack])
|
104
|
+
|
105
|
+
deploy_instance.lock_pushes(options[:stack], options[:username], options[:method])
|
106
|
+
|
107
|
+
@start_time = Time.now
|
108
|
+
deploy_instance.log_and_stream "Push started at #{@start_time.to_i}\n"
|
109
|
+
deploy_instance.log_and_stream "Calling #{options[:method]}\n";
|
110
|
+
deploy_instance.link_stack_logfile(deploy_instance.get_filename, options[:stack])
|
111
|
+
|
112
|
+
deploy_instance.raise_event(:deploy_start)
|
113
|
+
|
114
|
+
begin
|
115
|
+
state = deploy_instance.send(options[:method], options)
|
116
|
+
rescue Exception => e
|
117
|
+
deploy_instance.log_error("There was an exception during this deploy. Aborted!", e)
|
118
|
+
deploy_instance.raise_event(:deploy_error)
|
119
|
+
end
|
120
|
+
|
121
|
+
if state.nil? || !state.is_a?(Hash)
|
122
|
+
state = {}
|
123
|
+
end
|
124
|
+
deploy_instance.raise_event(:deploy_end, state)
|
125
|
+
|
126
|
+
if options[:method].match(/config_push/)
|
127
|
+
env = options[:method].match(/prod/) ? "production" : "princess"
|
128
|
+
elsif options[:method].match(/force_builda/)
|
129
|
+
env = "force asset rebuild"
|
130
|
+
else
|
131
|
+
env = options[:method][/(dev|qa|production|princess|prod|webs|stage|config)/i, 1] || "other"
|
132
|
+
env = "production" if env.match(/prod|webs/)
|
133
|
+
end
|
134
|
+
|
135
|
+
# display a message that the deploy is done and call the JavaScript
|
136
|
+
# deploy done function
|
137
|
+
msg = "<h4>#{env.to_s.upcase} deploy in #{options[:stack]} stack complete</h4>"
|
138
|
+
deploy_instance.log_and_stream(msg+"<p class='output'>")
|
139
|
+
deploy_instance.log_and_stream("<script id='deploy-done'>window.deploy_done('#{msg}', '#{options[:stage]}');</script>")
|
140
|
+
|
141
|
+
deploy_instance.unlock_pushes(options[:stack])
|
142
|
+
deploy_instance.move_stack_logfile(options[:stack])
|
143
|
+
|
144
|
+
return deploy_instance
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|