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,71 @@
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 GitScmProvider
21
+
22
+ # Initializes the provider
23
+ #
24
+ # @param env [TaskExecutionEnvironment] Environment for the commands to be executed in
25
+ def initialize(env)
26
+ raise ArgumentError, "env must be a TaskExecutionEnvironment" unless env.kind_of?(TaskExecutionEnvironment)
27
+
28
+ @env = env
29
+ end
30
+
31
+ # Checks out repository code from a system and switches to the given branch
32
+ #
33
+ # @param url [String] the repository location
34
+ # @param local_dir [String] path to the working copy
35
+ # @param branch [String] the branch to check out
36
+ def checkout_from_remote(url, local_dir, branch)
37
+ res = @env.command("git clone #{url} #{local_dir}")
38
+ raise RuntimeError, "Could not clone from git url #{url}" unless res.retval == 0
39
+
40
+ @env.chdir(local_dir)
41
+ res = @env.command("git checkout #{branch}")
42
+ @env.chdir('../')
43
+
44
+ raise RuntimeError, "could not switch to branch #{branch}" 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("git rev-parse HEAD")
52
+
53
+ res.stdout.gsub("\n", "")
54
+ end
55
+
56
+ # Returns scm files to be executed in the deployment process
57
+ #
58
+ # @return [Array] array of scm control files
59
+ def scm_files
60
+ [ '.git', '.gitignore' ]
61
+ end
62
+
63
+ # Returns the scm tools that have to be installed on specific systems
64
+ #
65
+ # @return [Array] array of utilities
66
+ def cli_utils
67
+ [ 'git' ]
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,68 @@
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
+ # scm provider facade
21
+ class ScmProvider
22
+
23
+ # Initializes the scm provider
24
+ #
25
+ # @param env [TaskExecutionEnvironment] env for the commands to be executed in
26
+ # @param scm [Symbol] the scm provider to user
27
+ def initialize(env, scm)
28
+ raise ArgumentError, 'env must be a TaskExecutionEnvironment' unless env.is_a?(TaskExecutionEnvironment)
29
+
30
+ @env = env
31
+ @real_provider = nil
32
+
33
+ if scm == :git
34
+ @real_provider = GitScmProvider.new(env)
35
+ end
36
+ end
37
+
38
+ # Checks out repository code from a system and switches to the given branch
39
+ #
40
+ # @param url [String] the repository location
41
+ # @param local_dir [String] path to the working copy
42
+ # @param branch [String] the branch to check out
43
+ def checkout_from_remote(url, local_dir, branch)
44
+ @real_provider.checkout_from_remote(url, local_dir, branch)
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 scm_files
51
+ @real_provider.scm_files
52
+ end
53
+
54
+ # Returns scm files to be executed in the deployment process
55
+ #
56
+ # @return [Array] array of scm control files
57
+ def cli_utils
58
+ @real_provider.cli_utils
59
+ end
60
+
61
+ # Returns the scm tools that have to be installed on specific systems
62
+ #
63
+ # @return [Array] array of utilities
64
+ def revision
65
+ @real_provider.revision
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,117 @@
1
+ Avocado::Deployment.configure do
2
+
3
+ # AVOCADO
4
+ # The flexible and easy to use deployment framework for web applications
5
+ #
6
+ # Welcome to your deployment manifest. Here you can configure the
7
+ # whole deployment process of your application to various target systems.
8
+ # This is a example file that has been created by `avo install`.
9
+ # While you are presented with the common configuration options for
10
+ # most common use cases, there are plenty more available and you might want
11
+ # to check them out. Because of the fact, that, currently, there is no
12
+ # official documentation, you have to lookup all the configuration options
13
+ # right in the applications' source code. But don't be afraid, you'll find
14
+ # them all in one place. Just take a look in the `config.rb` file at the
15
+ # method called `setup_config_defaults`.
16
+ #
17
+
18
+ # =============== GENERAL PROJECT CONFIGURATION ==================
19
+ # Set your project name here. This is not used right now but may
20
+ # be used for various purposes in future releases.
21
+ #
22
+ set :project_name, 'myproject'
23
+
24
+ # ===================== SCM CONFIGURATION ========================
25
+ # Configure the version control software you use for your project.
26
+ # Currently the only supported provider is Git, but this will change
27
+ # in the future.
28
+ #
29
+ # Valid options:
30
+ # :git
31
+ #
32
+ set :scm, :git
33
+
34
+ # This is your repository url in the following format:
35
+ # username@host:repository
36
+ #
37
+ set :repo_url, 'foo@github.com:foo/myproject.git'
38
+
39
+ # Specify the branch you'd like to deploy here. By default this is
40
+ # set to :master but could be every branch you wish. If your branch
41
+ # name contains special characters like slashes, just use a
42
+ # string rather than a symbol.
43
+ #
44
+ # Examples:
45
+ # :master
46
+ # :develop
47
+ # 'feature/AVO-123_manifest'
48
+ #
49
+ set :branch, :master
50
+
51
+ # ==================== DEPLOYMENT STRATEGY =======================
52
+ # Set your deployment strategy here. Currently only `local_copy`
53
+ # is implemented. The additional configuration values depend on
54
+ # the selected strategy.
55
+ #
56
+ # `local_copy`: Files are checked out of version control into a
57
+ # local directory, eventually preprocess and then
58
+ # packed (tarball), uploaded (via scp) and unpacked
59
+ # on the target system.
60
+ #
61
+ # Valid options:
62
+ # : local_copy
63
+ #
64
+ set :strategy, :local_copy
65
+
66
+ # Files to be ignored for the deployment process. Those files will
67
+ # not be overwritten on the target system
68
+ #
69
+ set :ignore_files, [ '.htaccess' ]
70
+
71
+ # ================= ADDITIONAL TASK DEFINITION ====================
72
+ # Avocado consists of a task system. Every step that is done while
73
+ # the deployment process is represented as a task definition.
74
+ # Due to the fact that most of the tasks depend on each other
75
+ # tasks can be related into a chain of tasks. When you call a task
76
+ # from the CLI utility, the whole chain for this task will be executed.
77
+ # This is a powerful tool for you to customize the deployment process
78
+ # for your needs. A full list of which tasks are defined and where you
79
+ # can hook on to do this or that can be found in the definition of each
80
+ # strategy in the `strategy/` directory.
81
+ #
82
+ # A basic task definition can look like that:
83
+ #
84
+ # task :do_that do
85
+ # command "echo 'foo'"
86
+ # end
87
+ #
88
+ # This task has no relations and therefore has to be called directly via
89
+ # the CLI interface. When you call `avo start staging do_that` this task
90
+ # would execute the command `echo 'foo'` LOCALLY, because no `scope` is defined.
91
+ # Take a look at the following code to see a fully featured example in action.
92
+ #
93
+ # task :install_composer, before: :create_deployment_tarball, scope: :local, desc: "installs the composer" do
94
+ # command "php composer.phar install"
95
+ # end
96
+
97
+ # ==================== STAGES CONFIGURATION =======================
98
+ <% stages.each do |stage| %>
99
+ setup_stage :<%= stage %>, desc: "Configuration for <%= stage %>" do
100
+ # In this section you can overwrite every configuration choice
101
+ # you have made above. You can define additional tasks, that
102
+ # are only usable within the current scope or change the
103
+ # repository url or branch for your current needs.
104
+ #
105
+
106
+ # ============== TARGET SYSTEM CONFIGURATION =================
107
+ # Files are transmitted over SCP. Therefore you must configure
108
+ # your target systems' SSH access credentials.
109
+ #
110
+
111
+ # Currently only pubkey-auth is supported
112
+ #
113
+ target :web, host: 'my.host.tld', user: 'deploy', auth: :pubkey, deploy_dir: '/var/www/staging/'
114
+ end
115
+ <% end %>
116
+
117
+ end
@@ -0,0 +1,29 @@
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
+ Avocado::Deployment.configure do
20
+
21
+ task :deploy, visibility: :public do
22
+ # stub for cli calls
23
+ end
24
+
25
+ task :check_ssh_connection, before: :deploy, scope: :remote, visibility: :private do
26
+ log.info "checking ssh connection"
27
+ end
28
+
29
+ end
@@ -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
+ Avocado::Deployment.configure do
20
+
21
+ task :check_local_tools, before: :deploy, scope: :local, visibility: :private do
22
+ check_util_availability [ 'tar' ].concat(@scm.cli_utils)
23
+ end
24
+
25
+ task :check_remote_system, before: :deploy, scope: :remote, visibility: :private do
26
+ check_util_availability [ 'tar' ]
27
+ end
28
+
29
+ task :check_temp_existance, visibility: :private, after: :deploy, scope: :local do
30
+ if File.exist?('.avocado-tmp')
31
+ raise RuntimeError, 'The avocado tmp directory (.avocado-tmp) does already exist. That may indicate that another deployment is already running.'
32
+ end
33
+ end
34
+
35
+ task :switch_to_temp_dir, visibility: :private, after: :check_temp_existance, scope: :local do
36
+ command "mkdir .avocado-tmp/"
37
+ chdir(".avocado-tmp/")
38
+ end
39
+
40
+ task :checkout_from_scm, visibility: :private, after: :switch_to_temp_dir, scope: :local do
41
+ @scm.checkout_from_remote(get(:repo_url), 'working-copy', get(:branch))
42
+ end
43
+
44
+ task :get_scm_info, visibility: :private, after: :checkout_from_scm, scope: :local do
45
+ chdir("working-copy/")
46
+
47
+ set(:revision, @scm.revision)
48
+
49
+ chdir("../")
50
+ end
51
+
52
+ task :delete_ignored_files, visibility: :private, after: :get_scm_info, scope: :local do
53
+ if get(:ignore_files).concat(@scm.scm_files).size > 0
54
+ chdir("working-copy/")
55
+ command "rm -rfv #{get(:ignore_files).concat(@scm.scm_files).join(' ')}"
56
+ chdir("../")
57
+ end
58
+ end
59
+
60
+ task :create_revision_file, visibility: :private, after: :delete_ignored_files, scope: :local do
61
+ chdir("working-copy/")
62
+ command "echo '#{get(:revision)}' > REVISION"
63
+ chdir("../")
64
+ end
65
+
66
+ task :create_deployment_tarball, visibility: :private, after: :create_revision_file, scope: :local do
67
+ chdir("working-copy/")
68
+ command "tar cvfz ../deploy.tar.gz ."
69
+ chdir("../")
70
+ end
71
+
72
+ task :upload, visibility: :private, after: :create_deployment_tarball, scope: :local do
73
+ targets.each_pair do |key, target|
74
+ copy_to_target(target, 'deploy.tar.gz', '/tmp/deploy.tar.gz')
75
+ end
76
+ end
77
+
78
+ task :create_deploy_dir, visibility: :private, after: :upload, scope: :remote do
79
+ command "if [ ! -d '#{get(:deploy_dir)}' ]; then mkdir -p #{get(:deploy_dir)}; fi"
80
+ end
81
+
82
+ task :unpack, visibility: :private, after: :create_deploy_dir, scope: :remote do
83
+ command "tar xvfz /tmp/deploy.tar.gz -C #{get(:deploy_dir)}/"
84
+ end
85
+
86
+ task :cleanup_remote, visibility: :private, after: :unpack, scope: :remote do
87
+ command "rm /tmp/deploy.tar.gz"
88
+ end
89
+
90
+ task :log_deployment, visibility: :private, after: :cleanup_remote, scope: :remote do
91
+ command "echo '[#{ Time.now.strftime('%Y-%m-%d %H-%M-%S')}] revision #{get(:revision)} deployed by #{ENV['USER']}' >> #{get(:log_file)}"
92
+ end
93
+
94
+ task :cleanup_local, visibility: :private, after: :cleanup_remote, scope: :local do
95
+ chdir("../")
96
+ command "rm -rf .avocado-tmp"
97
+ end
98
+
99
+ end
@@ -0,0 +1,49 @@
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 Target
21
+
22
+ attr_reader :name
23
+ attr_reader :config
24
+
25
+ # Initializes the deployment target
26
+ #
27
+ # @param name [Symbol] target name
28
+ # @param config [Hash] target config
29
+ def initialize(name, config)
30
+ @name = name
31
+ @config = default_config.merge(config)
32
+ end
33
+
34
+ private
35
+ # Sets up the config defaults
36
+ #
37
+ # @return [Hash] config defaults
38
+ def default_config
39
+ {
40
+ :host => nil,
41
+ :user => 'root',
42
+ :auth => :pubkey,
43
+ :deploy_dir => '/var/www/',
44
+ :log_file => '/var/www/deploy.log',
45
+ }
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,127 @@
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 LocalTaskExecutionEnvironment < TaskExecutionEnvironment
21
+
22
+ # Initialized the environment
23
+ #
24
+ # @param config [Hash] deployment configuration
25
+ def initialize(config)
26
+ super
27
+
28
+ @dir = Dir.pwd
29
+ end
30
+
31
+ # Checks, if all utilities are available for the deployment process
32
+ # to be executed
33
+ #
34
+ # @param utils [Array] array with utilities to check
35
+ def check_util_availability(utils)
36
+ super(utils, 'locally')
37
+ end
38
+
39
+ # Changes the directory for commands to be executed in
40
+ #
41
+ # @param dir [String] the directory to change to
42
+ def chdir(dir)
43
+ log.debug "changing directory [#{dir.yellow}] " + "locally".cyan
44
+
45
+ Dir.chdir(dir)
46
+ @dir = Dir.pwd
47
+ end
48
+
49
+ # Returns the current working directory
50
+ #
51
+ # @return [String] current working directory
52
+ def cwd
53
+ @dir
54
+ end
55
+
56
+ # Returns all target systems to deploy to
57
+ #
58
+ # @return [Hash] hash of target systems
59
+ def targets
60
+ Avocado::Deployment.instance.config.targets
61
+ end
62
+
63
+ # Copies a file to a remote system (= target)
64
+ #
65
+ # @param target [Target] the target system to deploy to
66
+ # @param file [String] the local file to upload
67
+ # @param remote [String] path on the remote system
68
+ def copy_to_target(target, file, remote)
69
+ log = Avocado::Deployment.instance.log
70
+
71
+ log.info "started upload of file #{file} to #{target.name}"
72
+
73
+ Net::SSH.start(
74
+ target.config[:host],
75
+ target.config[:user]
76
+ ) do |session|
77
+ session.scp.upload!(file, remote, :recursive => true) do |ch, name, sent, total|
78
+ percentage = 0
79
+
80
+ begin
81
+ percentage = (sent.to_f * 100 / total.to_f).to_i
82
+ rescue Exception => e
83
+ Avocado::Deployment.instance.handle_abort(e)
84
+ end
85
+
86
+ #log.info "\r#{name}: #{percentage}%"
87
+ end
88
+ end
89
+
90
+ log.info "upload completed"
91
+ end
92
+
93
+ # Executes a command locally in the current directory
94
+ #
95
+ # @param cmd [String] the command to execute
96
+ # @return [CommandExecutionResult] result of the command exection
97
+ def command(cmd)
98
+ log = Avocado::Deployment.instance.log
99
+
100
+ log.info "Executing [" + cmd.yellow + "] " + "locally".cyan
101
+
102
+ result = Avocado::CommandExecutionResult.new
103
+
104
+ begin
105
+ stdout, stderr, status = ::Open3.capture3(cmd, :chdir => cwd())
106
+
107
+ result.stdin = cmd
108
+ result.stdout = stdout
109
+ result.stderr = stderr
110
+ result.retval = status.exitstatus
111
+
112
+ if result.stdout.nil? == false && result.stdout.empty? == false
113
+ log.debug "Stdout: " + result.stdout.green
114
+ end
115
+
116
+ if result.stderr.nil? == false && result.stderr.empty? == false
117
+ log.debug "Stderr: " + result.stderr.red
118
+ end
119
+ rescue Exception => e
120
+ handle_abort e
121
+ end
122
+
123
+ result
124
+ end
125
+
126
+ end
127
+ end