avodeploy 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'awesome_print'
4
+ gem 'table_print'
5
+
6
+ gem 'net-ssh'
7
+ gem 'net-scp'
8
+
9
+ gem 'thor'
@@ -0,0 +1,99 @@
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 Avocado
20
+ class Bootstrap
21
+ # Runs the avocado bootstrap
22
+ #
23
+ # @param stage [Symbol] the stage to bootstrap
24
+ # @param verbose [Boolean] run in verbose mode
25
+ # @param debug [Boolean] run in boolean mode
26
+ def self.run(stage, verbose = false, debug = false)
27
+ if stage.is_a?(String)
28
+ stage = stage.to_sym
29
+ end
30
+
31
+ require File.join(File.dirname(__FILE__), 'core_ext/string_colors.rb')
32
+ require File.join(File.dirname(__FILE__), 'core_ext/hash_insert_at.rb')
33
+
34
+ require File.join(File.dirname(__FILE__), 'task/task.rb')
35
+ require File.join(File.dirname(__FILE__), 'task/task_dependency.rb')
36
+ require File.join(File.dirname(__FILE__), 'task/task_manager.rb')
37
+ require File.join(File.dirname(__FILE__), 'task/task_execution_environment.rb')
38
+ require File.join(File.dirname(__FILE__), 'task/local_task_execution_environment.rb')
39
+ require File.join(File.dirname(__FILE__), 'task/remote_task_execution_environment.rb')
40
+
41
+ require File.join(File.dirname(__FILE__), 'scm_provider/scm_provider.rb')
42
+ require File.join(File.dirname(__FILE__), 'scm_provider/git_scm_provider.rb')
43
+
44
+ require File.join(File.dirname(__FILE__), 'multi_io.rb')
45
+ require File.join(File.dirname(__FILE__), 'command_execution_result.rb')
46
+ require File.join(File.dirname(__FILE__), 'target.rb')
47
+ require File.join(File.dirname(__FILE__), 'config.rb')
48
+ require File.join(File.dirname(__FILE__), 'deployment.rb')
49
+
50
+ begin
51
+ # defaults
52
+ Avocado::Deployment.configure do
53
+ set :stage, stage
54
+ end
55
+
56
+ if File.exist?(Dir.pwd.concat('/Avofile')) == false
57
+ raise RuntimeError, 'Could not find Avofile. Run `avo install` first.'
58
+ end
59
+
60
+ instance = Avocado::Deployment.instance
61
+
62
+ # load user config initially to determine strategy
63
+ begin
64
+ load File.join(Dir.pwd, 'Avofile')
65
+ rescue RuntimeError => e
66
+ # `find_chain_index_containing': could not find a chain containing task create_deployment_tarball (RuntimeError)
67
+ # error not neccessary because dependencies are not loaded
68
+ end
69
+
70
+ if debug
71
+ instance.log.level = Logger::DEBUG
72
+ elsif verbose
73
+ instance.log.level = Logger::INFO
74
+ else
75
+ instance.log.level = instance.config.get(:log_level)
76
+ end
77
+
78
+ instance.log.debug "Loading deployment strategy #{instance.config.get(:strategy).to_s}..."
79
+
80
+ # load strategy
81
+ # @todo pruefen
82
+ require File.join(File.dirname(__FILE__), "strategy/base.rb")
83
+ require File.join(File.dirname(__FILE__), "strategy/#{instance.config.get(:strategy).to_s}.rb")
84
+
85
+
86
+ instance.log.debug "Loading user configuration..."
87
+
88
+ # override again by user config to allow manipulation of tasks
89
+ load File.join(Dir.pwd, 'Avofile')
90
+ rescue Exception => e
91
+ Avocado::Deployment.instance.log.error e.message.red
92
+
93
+ Kernel.exit(true)
94
+ end
95
+
96
+ Avocado::Deployment.instance
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,26 @@
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 Avocado
20
+ class CommandExecutionResult
21
+ attr_accessor :stdin
22
+ attr_accessor :stdout
23
+ attr_accessor :stderr
24
+ attr_accessor :retval
25
+ end
26
+ end
@@ -0,0 +1,113 @@
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 Avocado
20
+ class Config
21
+
22
+ attr_reader :config
23
+ attr_reader :stages
24
+ attr_reader :targets
25
+
26
+ # Intializes the config object
27
+ def initialize
28
+ @config = setup_config_defaults
29
+ @stages = {}
30
+ @targets = {}
31
+ end
32
+
33
+ # Sets a configuration item
34
+ #
35
+ # @param key [Symbol] configuration key
36
+ # @param value [mixed] configuration value
37
+ def set(key, value)
38
+ @config[key] = value
39
+ end
40
+
41
+ # Returns a configuration item if set
42
+ #
43
+ # @param key [Symbol] configuration key
44
+ # @return [mixed] configuration value
45
+ def get(key)
46
+ raise ArgumentError, "key #{key} is not set" unless @config.has_key?(key)
47
+
48
+ @config[key]
49
+ end
50
+
51
+ # Defines a task
52
+ #
53
+ # @param name [Symbol] task name
54
+ # @param options [Hash] task options
55
+ # @param block [Block] the code to be executed when the task is started
56
+ def task(name, options = {}, &block)
57
+ Avocado::Deployment.instance.task_manager.add_task(name, options, &block)
58
+ end
59
+
60
+ # Defines a stage
61
+ #
62
+ # @param name [Symbol] stage name
63
+ # @param options [Hash] stage options
64
+ # @param block [Block] the stage configuration
65
+ def setup_stage(name, options = {}, &block)
66
+ if options.has_key?(:desc)
67
+ stages[name] = options[:desc]
68
+ end
69
+
70
+ if name == get(:stage)
71
+ instance_eval(&block)
72
+ end
73
+ end
74
+
75
+ # Defines a deployment target
76
+ #
77
+ # @param name [Symbol] the deployment targets' name
78
+ # @param options [Hash] target options
79
+ def target(name, options = {})
80
+ @targets[name] = Avocado::Target.new(name, options)
81
+ end
82
+
83
+ # Merges the configuration with another config hash
84
+ #
85
+ # @param other_config [Hash] configuration hash
86
+ # @return [Hash] the merged hash
87
+ def merge(other_config)
88
+ @config.merge(other_config)
89
+ end
90
+
91
+ private
92
+ # Sets up configuration defaults
93
+ #
94
+ # @return [Hash] configuration defaults
95
+ def setup_config_defaults
96
+ {
97
+ :project_name => '',
98
+ :scm => :git,
99
+ :repo_url => '',
100
+ :branch => :master,
101
+ :ssh_host => '',
102
+ :ssh_user => 'root',
103
+ :ssh_auth => :pubkey,
104
+ :deploy_dir => '/var/www/',
105
+ :stage => :production,
106
+ :strategy => :local_copy,
107
+ :ignore_files => [],
108
+ :log_level => Logger::WARN,
109
+ }
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,42 @@
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
+ class Hash
20
+
21
+ # Inserts a Key/Value-Pair at a specific position of in a Hash
22
+ #
23
+ # @param position [Symbol] the position to add the new pair, either `:before` or `:after`
24
+ def insert_at(position, key, kvpair)
25
+ raise ArgumentError, 'position must be either :before or :after' unless [:before, :after].include?(position)
26
+
27
+ arr = to_a
28
+ pos = arr.index(arr.assoc(key))
29
+
30
+ if pos && position == :after
31
+ pos += 1
32
+ end
33
+
34
+ if pos
35
+ arr.insert(pos, kvpair)
36
+ else
37
+ arr << kvpair
38
+ end
39
+
40
+ replace Hash[arr]
41
+ end
42
+ end
@@ -0,0 +1,45 @@
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
+ class String
20
+
21
+ # Paints the string red on CLI
22
+ def red
23
+ "\033[31m#{self}\033[0m"
24
+ end
25
+
26
+ # Paints the string green on CLI
27
+ def green
28
+ "\033[32m#{self}\033[0m"
29
+ end
30
+
31
+ # Paints the string cyan on CLI
32
+ def cyan
33
+ "\033[36m#{self}\033[0m"
34
+ end
35
+
36
+ # Paints the string yellow on CLI
37
+ def yellow
38
+ "\e[33m#{self}\e[0m"
39
+ end
40
+
41
+ # Paints the string gray on CLI
42
+ def gray
43
+ "\033[37m#{self}\033[0m"
44
+ end
45
+ end
@@ -0,0 +1,76 @@
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 Avocado
20
+ class Deployment
21
+
22
+ attr_accessor :config
23
+ attr_accessor :task_manager
24
+ attr_reader :log
25
+ attr_reader :log_file
26
+
27
+ # Initializes the deployment
28
+ def initialize
29
+ @stages = {}
30
+ @task_manager = Avocado::TaskManager.new
31
+ @config = Avocado::Config.new
32
+
33
+ @log = ::Logger.new(STDOUT)
34
+ end
35
+
36
+ # Configures the deployment
37
+ #
38
+ # @param block [Block] configuration block
39
+ def self.configure(&block)
40
+ @instance = self.instance
41
+ @instance.config.instance_eval(&block)
42
+
43
+ # @todo check config and throw exception
44
+ end
45
+
46
+ # Returns the deployment instance
47
+ #
48
+ # @return [Deployment] the deployment instance
49
+ def self.instance
50
+ if @instance.nil?
51
+ @instance = self.new
52
+ end
53
+
54
+ @instance
55
+ end
56
+
57
+ # Handles exceptions
58
+ #
59
+ # @param [Exception] the exception to handle
60
+ def handle_abort(e)
61
+ if e.class != SystemExit
62
+ @log.error e.message.red
63
+ @log.info "cleaning up..."
64
+
65
+ task_manager.invoke_task_oneshot(:cleanup_local)
66
+
67
+ #if e.kind_of?(::Net::SSH::AuthenticationFailed) == false
68
+ # task_manager.invoke_task_oneshot(:cleanup_remote)
69
+ #end
70
+
71
+ Kernel.exit(true)
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,40 @@
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 Avocado
20
+ class MultiIO
21
+ # Initializes the MultiIO with various target
22
+ #
23
+ # @param targets [Array] targets to handle
24
+ def initialize(*targets)
25
+ @targets = targets
26
+ end
27
+
28
+ # Writes to all targets
29
+ #
30
+ # @param args [mixed] arguments
31
+ def write(*args)
32
+ @targets.each {|t| t.write(*args)}
33
+ end
34
+
35
+ # Closes the targets
36
+ def close
37
+ @targets.each(&:close)
38
+ end
39
+ end
40
+ end