avodeploy 0.4.2 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +20 -0
- data/README.md +1 -1
- data/avodeploy.gemspec +16 -14
- data/bin/avo +101 -104
- data/lib/avodeploy.rb +1 -0
- data/lib/avodeploy/bootstrap.rb +65 -73
- data/lib/avodeploy/command_execution_result.rb +6 -6
- data/lib/avodeploy/config.rb +120 -99
- data/lib/avodeploy/core_ext/string_colors.rb +9 -9
- data/lib/avodeploy/deployment.rb +43 -46
- data/lib/avodeploy/multi_io.rb +11 -11
- data/lib/avodeploy/scm_provider/bzr_scm_provider.rb +111 -0
- data/lib/avodeploy/scm_provider/git_scm_provider.rb +66 -45
- data/lib/avodeploy/scm_provider/scm_provider.rb +57 -43
- data/lib/avodeploy/skel/manifest_template.rb.erb +127 -116
- data/lib/avodeploy/strategy/base.rb +7 -7
- data/lib/avodeploy/strategy/local_copy.rb +99 -79
- data/lib/avodeploy/strategy/local_copy_partial.rb +86 -0
- data/lib/avodeploy/target.rb +32 -31
- data/lib/avodeploy/task/local_task_execution_environment.rb +112 -107
- data/lib/avodeploy/task/remote_task_execution_environment.rb +90 -94
- data/lib/avodeploy/task/task.rb +53 -42
- data/lib/avodeploy/task/task_dependency.rb +5 -5
- data/lib/avodeploy/task/task_execution_environment.rb +70 -59
- data/lib/avodeploy/task/task_manager.rb +187 -165
- data/lib/avodeploy/version.rb +1 -1
- metadata +7 -5
@@ -17,10 +17,10 @@
|
|
17
17
|
=end
|
18
18
|
|
19
19
|
module AvoDeploy
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
class CommandExecutionResult
|
21
|
+
attr_accessor :stdin
|
22
|
+
attr_accessor :stdout
|
23
|
+
attr_accessor :stderr
|
24
|
+
attr_accessor :retval
|
25
|
+
end
|
26
26
|
end
|
data/lib/avodeploy/config.rb
CHANGED
@@ -17,103 +17,124 @@
|
|
17
17
|
=end
|
18
18
|
|
19
19
|
module AvoDeploy
|
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
|
-
|
20
|
+
class Config
|
21
|
+
|
22
|
+
attr_reader :config
|
23
|
+
attr_reader :stages
|
24
|
+
attr_reader :targets
|
25
|
+
attr_reader :loaded_stage
|
26
|
+
|
27
|
+
# Intializes the config object
|
28
|
+
def initialize
|
29
|
+
@config = setup_config_defaults
|
30
|
+
@stages = {}
|
31
|
+
@targets = {}
|
32
|
+
@loaded_stage = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets a configuration item
|
36
|
+
#
|
37
|
+
# @param key [Symbol] configuration key
|
38
|
+
# @param value [mixed] configuration value
|
39
|
+
def set(key, value)
|
40
|
+
# compatibility with releases < 0.5
|
41
|
+
if key == :strategy
|
42
|
+
inherit_strategy(value)
|
43
|
+
return
|
44
|
+
end
|
45
|
+
|
46
|
+
@config[key] = value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Loads a strategy. Because the strategy files are loaded in
|
50
|
+
# the specified order, it's possible to override tasks.
|
51
|
+
# This is how inheritance of strategies is realized.
|
52
|
+
#
|
53
|
+
# @param strategy [Symbol] the strategy to load
|
54
|
+
def inherit_strategy(strategy)
|
55
|
+
AvoDeploy::Deployment.instance.log.debug "Loading deployment strategy #{strategy.to_s}..."
|
56
|
+
|
57
|
+
strategy_file_path = File.dirname(__FILE__) + "/strategy/#{strategy.to_s}.rb"
|
58
|
+
|
59
|
+
if File.exist?(strategy_file_path)
|
60
|
+
require strategy_file_path
|
61
|
+
else
|
62
|
+
raise RuntimeError, "The requested strategy '#{strategy.to_s}' does not exist"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a configuration item if set
|
67
|
+
#
|
68
|
+
# @param key [Symbol] configuration key
|
69
|
+
# @return [mixed] configuration value
|
70
|
+
def get(key)
|
71
|
+
raise ArgumentError, "key #{key} is not set" unless @config.has_key?(key)
|
72
|
+
|
73
|
+
@config[key]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Defines a task
|
77
|
+
#
|
78
|
+
# @param name [Symbol] task name
|
79
|
+
# @param options [Hash] task options
|
80
|
+
# @param block [Block] the code to be executed when the task is started
|
81
|
+
def task(name, options = {}, &block)
|
82
|
+
AvoDeploy::Deployment.instance.log.debug "registering task #{name}..."
|
83
|
+
AvoDeploy::Deployment.instance.task_manager.add_task(name, options, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Defines a stage
|
87
|
+
#
|
88
|
+
# @param name [Symbol] stage name
|
89
|
+
# @param options [Hash] stage options
|
90
|
+
# @param block [Block] the stage configuration
|
91
|
+
def setup_stage(name, options = {}, &block)
|
92
|
+
stages[name] = ''
|
93
|
+
|
94
|
+
if options.has_key?(:desc)
|
95
|
+
stages[name] = options[:desc]
|
96
|
+
end
|
97
|
+
|
98
|
+
if name.to_s == get(:stage).to_s
|
99
|
+
@loaded_stage = name
|
100
|
+
|
101
|
+
instance_eval(&block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Defines a deployment target
|
106
|
+
#
|
107
|
+
# @param name [Symbol] the deployment targets' name
|
108
|
+
# @param options [Hash] target options
|
109
|
+
def target(name, options = {})
|
110
|
+
@targets[name] = AvoDeploy::Target.new(name, options)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Merges the configuration with another config hash
|
114
|
+
#
|
115
|
+
# @param other_config [Hash] configuration hash
|
116
|
+
# @return [Hash] the merged hash
|
117
|
+
def merge(other_config)
|
118
|
+
@config.merge(other_config)
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
# Sets up configuration defaults
|
123
|
+
#
|
124
|
+
# @return [Hash] configuration defaults
|
125
|
+
def setup_config_defaults
|
126
|
+
{
|
127
|
+
:project_name => '',
|
128
|
+
:scm => :git,
|
129
|
+
:repo_url => '',
|
130
|
+
:branch => :master,
|
131
|
+
:stage => :production,
|
132
|
+
:strategy => nil,
|
133
|
+
:ignore_files => [],
|
134
|
+
:log_level => Logger::WARN,
|
135
|
+
:force_tag => false,
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
119
140
|
end
|
@@ -19,27 +19,27 @@
|
|
19
19
|
class String
|
20
20
|
|
21
21
|
# Paints the string red on CLI
|
22
|
-
|
22
|
+
def red
|
23
23
|
"\033[31m#{self}\033[0m"
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Paints the string green on CLI
|
27
27
|
def green
|
28
|
-
"\033[32m#{self}\033[0m"
|
28
|
+
"\033[32m#{self}\033[0m"
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# Paints the string cyan on CLI
|
32
32
|
def cyan
|
33
|
-
"\033[36m#{self}\033[0m"
|
33
|
+
"\033[36m#{self}\033[0m"
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Paints the string yellow on CLI
|
37
37
|
def yellow
|
38
|
-
"\e[33m#{self}\e[0m"
|
38
|
+
"\e[33m#{self}\e[0m"
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
# Paints the string gray on CLI
|
42
42
|
def gray
|
43
|
-
"\033[37m#{self}\033[0m"
|
43
|
+
"\033[37m#{self}\033[0m"
|
44
44
|
end
|
45
45
|
end
|
data/lib/avodeploy/deployment.rb
CHANGED
@@ -17,60 +17,57 @@
|
|
17
17
|
=end
|
18
18
|
|
19
19
|
module AvoDeploy
|
20
|
-
|
20
|
+
class Deployment
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
attr_reader :log_file
|
22
|
+
attr_accessor :config
|
23
|
+
attr_accessor :task_manager
|
24
|
+
attr_reader :log
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
# Initializes the deployment
|
27
|
+
def initialize
|
28
|
+
@stages = {}
|
29
|
+
@task_manager = AvoDeploy::Task::TaskManager.new
|
30
|
+
@config = AvoDeploy::Config.new
|
32
31
|
|
33
|
-
|
34
|
-
|
32
|
+
@log = ::Logger.new(STDOUT)
|
33
|
+
end
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
# Configures the deployment
|
36
|
+
#
|
37
|
+
# @param block [Block] configuration block
|
38
|
+
def self.configure(&block)
|
39
|
+
@instance = self.instance
|
40
|
+
@instance.config.instance_eval(&block)
|
42
41
|
|
43
|
-
|
44
|
-
|
42
|
+
# @todo check config and throw exception
|
43
|
+
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
# Returns the deployment instance
|
46
|
+
#
|
47
|
+
# @return [Deployment] the deployment instance
|
48
|
+
def self.instance
|
49
|
+
if @instance.nil?
|
50
|
+
@instance = self.new
|
51
|
+
end
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
@instance
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
56
|
+
# Handles exceptions
|
57
|
+
#
|
58
|
+
# @param e [Exception] the exception to handle
|
59
|
+
def handle_abort(e)
|
60
|
+
if log.level == ::Logger::DEBUG
|
61
|
+
raise e
|
62
|
+
elsif e.class != SystemExit
|
63
|
+
@log.error e.message.red
|
64
|
+
@log.info 'cleaning up...'
|
64
65
|
|
65
|
-
|
66
|
+
task_manager.invoke_task_oneshot(:cleanup_local)
|
67
|
+
end
|
68
|
+
|
69
|
+
Kernel.exit(true)
|
70
|
+
end
|
66
71
|
|
67
|
-
|
68
|
-
# task_manager.invoke_task_oneshot(:cleanup_remote)
|
69
|
-
#end
|
70
|
-
|
71
|
-
Kernel.exit(true)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
72
|
+
end
|
76
73
|
end
|
data/lib/avodeploy/multi_io.rb
CHANGED
@@ -17,24 +17,24 @@
|
|
17
17
|
=end
|
18
18
|
|
19
19
|
module AvoDeploy
|
20
|
-
|
20
|
+
class MultiIO
|
21
21
|
# Initializes the MultiIO with various target
|
22
22
|
#
|
23
23
|
# @param targets [Array] targets to handle
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
def initialize(*targets)
|
25
|
+
@targets = targets
|
26
|
+
end
|
27
27
|
|
28
28
|
# Writes to all targets
|
29
29
|
#
|
30
30
|
# @param args [mixed] arguments
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def write(*args)
|
32
|
+
@targets.each { |t| t.write(*args) }
|
33
|
+
end
|
34
34
|
|
35
35
|
# Closes the targets
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
def close
|
37
|
+
@targets.each(&:close)
|
38
|
+
end
|
39
|
+
end
|
40
40
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
=begin
|
2
|
+
AVOCADO
|
3
|
+
The flexible and easy to use deployment framework for web applications
|
4
|
+
|
5
|
+
This program is free software; you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License Version 2
|
7
|
+
as published by the Free Software Foundation.
|
8
|
+
|
9
|
+
This program is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
GNU General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU General Public License
|
15
|
+
along with this program; if not, write to the Free Software
|
16
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
+
=end
|
18
|
+
|
19
|
+
module AvoDeploy
|
20
|
+
module ScmProvider
|
21
|
+
class BzrScmProvider < ScmProvider
|
22
|
+
|
23
|
+
# Initializes the provider
|
24
|
+
#
|
25
|
+
# @param env [TaskExecutionEnvironment] Environment for the commands to be executed in
|
26
|
+
def initialize(env)
|
27
|
+
super(env)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Checks out repository code from a system and switches to the given branch
|
31
|
+
#
|
32
|
+
# @param url [String] the repository location
|
33
|
+
# @param local_dir [String] path to the working copy
|
34
|
+
# @param branch [String] the branch to check out, not used here because branches are encoded in the bazaar urls
|
35
|
+
# @param tag [String] tag to check out
|
36
|
+
def checkout_from_remote(url, local_dir, branch, tag = nil)
|
37
|
+
cmd = "bzr co --lightweight #{url} #{local_dir}"
|
38
|
+
|
39
|
+
if tag.nil? == false
|
40
|
+
cmd += " -r tag:#{tag}"
|
41
|
+
end
|
42
|
+
|
43
|
+
res = @env.command(cmd)
|
44
|
+
raise RuntimeError, "Could not checkout from bzr url #{url}" unless res.retval == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the current revision of the working copy
|
48
|
+
#
|
49
|
+
# @return [String] the current revision of the working copy
|
50
|
+
def revision
|
51
|
+
res = @env.command('bzr revno --tree')
|
52
|
+
|
53
|
+
res.stdout.gsub("\n", '')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Finds files that differ between two revisions and returns them
|
57
|
+
# as a array
|
58
|
+
#
|
59
|
+
# @param rev1 [String] sha1
|
60
|
+
# @param rev2 [String] sha1
|
61
|
+
#
|
62
|
+
# @return [Array]
|
63
|
+
def diff_files_between_revisions(rev1, rev2)
|
64
|
+
# same revision, nothing changed
|
65
|
+
if rev1 == rev2
|
66
|
+
return []
|
67
|
+
end
|
68
|
+
|
69
|
+
# exclude rev1 itself
|
70
|
+
rev1 = rev1.to_i + 1
|
71
|
+
|
72
|
+
res = @env.command("bzr log -r#{rev1}..#{rev2} -v --short")
|
73
|
+
|
74
|
+
files = []
|
75
|
+
|
76
|
+
res.stdout.lines.each do |line|
|
77
|
+
line.strip!
|
78
|
+
next unless line.start_with?('A') || line.start_with?('M')
|
79
|
+
|
80
|
+
files << line[3, line.length]
|
81
|
+
end
|
82
|
+
|
83
|
+
files
|
84
|
+
end
|
85
|
+
|
86
|
+
# Finds files unknown file in the working directory and returns them
|
87
|
+
# as a array
|
88
|
+
#
|
89
|
+
# @return [Array]
|
90
|
+
def unknown_files_in_workdir
|
91
|
+
res = @env.command("bzr status --short | grep '^? ' | awk '/^? (.*)$/ {print $2}'")
|
92
|
+
res.stdout.lines
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns scm files to be executed in the deployment process
|
96
|
+
#
|
97
|
+
# @return [Array] array of scm control files
|
98
|
+
def scm_files
|
99
|
+
['.bzr', '.bzrignore']
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns the scm tools that have to be installed on specific systems
|
103
|
+
#
|
104
|
+
# @return [Array] array of utilities
|
105
|
+
def cli_utils
|
106
|
+
['bzr']
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|