deployaml 0.1

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.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0 2010-08-26
2
+
3
+ * 1 major enhancement:
4
+ * Initial commit
data/Manifest.txt ADDED
@@ -0,0 +1,19 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ bin/deployaml
6
+ lib/deployaml.rb
7
+ lib/deployaml/deployment.rb
8
+ lib/deployaml/destination.rb
9
+ lib/deployaml/local_destination.rb
10
+ lib/deployaml/post_install/pending_migrations.rb
11
+ lib/deployaml/post_install/restart_passenger.rb
12
+ lib/deployaml/pre_install/minify.rb
13
+ lib/deployaml/pre_install/write_string_to_file.rb
14
+ lib/deployaml/remote_destination.rb
15
+ lib/deployaml/scm/filesystem.rb
16
+ lib/deployaml/scm/git.rb
17
+ lib/deployaml/scm_base.rb
18
+ vendor/yuicompressor/build.xml
19
+ vendor/yuicompressor/build/yuicompressor-2.4.2.jar
data/README.rdoc ADDED
@@ -0,0 +1,105 @@
1
+ = deployaml
2
+
3
+ * http://www.advancethinking.com/open_source/deployaml
4
+
5
+ == DESCRIPTION:
6
+
7
+ YAML based deployment framework for your code.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * If a repo is used more than once, it will be cloned more than once (annoying)
12
+ * Not compressing remote file transfer (slow)
13
+
14
+ == SYNOPSIS:
15
+
16
+ To deploy your code using the deplo.yml file in the current directory:
17
+
18
+ $ deployaml
19
+
20
+ To view help:
21
+
22
+ $ deployaml --help
23
+
24
+ Example of very simple deplo.yml (with minification of CSS & JS):
25
+
26
+ - name: my deployment
27
+ repository:
28
+ path: username@source-host.com:/path/to/git/project
29
+ scm: git
30
+ pre_install:
31
+ - task: minify
32
+
33
+ destinations:
34
+ - path: /path/to/where/your/code/is/run
35
+ host: destination-host.com
36
+ username: destination_username
37
+
38
+ This will deploy the source code from source-host.com:/path/to/git/project, minify
39
+ the CSS and JavaScript and pop the resulting code in
40
+ destination-host.com:/path/to/where/your/code/is/run/releases/YYMMDDHHSS with a
41
+ corresponding symbolic link
42
+ destination-host.com:/path/to/where/your/code/is/run/releases/current
43
+
44
+
45
+ == REQUIREMENTS:
46
+
47
+ * highline
48
+ * net-ssh
49
+ * net-scp
50
+
51
+ == INSTALL:
52
+
53
+ * sudo gem install deployaml
54
+
55
+ == DEVELOPERS:
56
+
57
+ After checking out the source, run:
58
+
59
+ $ rake newb
60
+
61
+ This task will install any missing dependencies, run the tests/specs,
62
+ and generate the RDoc.
63
+
64
+ Before you can run your tests cleanly, you will need to create two yaml
65
+ files in the "stuff_not_to_be_committed" directory. One called
66
+ "host_and_username_and_password.yml" containing the following
67
+ (replacing "PUTSOMETHINGHERE"):
68
+
69
+ host: PUTSOMETHINGHERE
70
+ username: PUTSOMETHINGHERE
71
+ password: PUTSOMETHINGHERE
72
+
73
+ And another called "host_and_username_with_ssh_keys.yml" containing the following:
74
+
75
+ host: PUTSOMETHINGHERE
76
+ username: PUTSOMETHINGHERE
77
+
78
+ For this, you will need to setup some ssh keys so you are not prompted for a password.
79
+
80
+ IMPORTANT!! Needless to say, you should never commit these files!!
81
+
82
+ == LICENSE:
83
+
84
+ (The MIT License)
85
+
86
+ Copyright (c) 2010 FIX
87
+
88
+ Permission is hereby granted, free of charge, to any person obtaining
89
+ a copy of this software and associated documentation files (the
90
+ 'Software'), to deal in the Software without restriction, including
91
+ without limitation the rights to use, copy, modify, merge, publish,
92
+ distribute, sublicense, and/or sell copies of the Software, and to
93
+ permit persons to whom the Software is furnished to do so, subject to
94
+ the following conditions:
95
+
96
+ The above copyright notice and this permission notice shall be
97
+ included in all copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
100
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
101
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
102
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
103
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
104
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
105
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/deployaml'
6
+
7
+ Hoe.plugin :newgem
8
+
9
+ $hoe = Hoe.spec 'deployaml' do
10
+ self.developer 'Stephen Hardisty', 'moowahaha@hotmail.com'
11
+ self.rubyforge_name = self.name
12
+ self.extra_deps = [
13
+ ['net-ssh', '>= 2.0.11'],
14
+ ['net-scp', '>= 1.0.3'],
15
+ ['highline', '>= 1.2.9']
16
+ ]
17
+ end
18
+
19
+ require 'newgem/tasks'
20
+ Dir['tasks/*.rake'].each { |t| load t }
data/bin/deployaml ADDED
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $usage = %Q{
4
+ == Synopsis
5
+
6
+ deployaml: deploys your project using the details from a deplo.yml file in the current directory
7
+
8
+ == Usage
9
+
10
+ deployaml [OPTION]
11
+
12
+ -h, --help
13
+ show help and exit
14
+
15
+ -v VERSION, --version=VERSION
16
+ deploy a given version of the code (such as a tag)
17
+
18
+ -t, --tasks
19
+ list available pre and post install tasks and exit
20
+
21
+ -s, --scms
22
+ list available source control systems and exit
23
+
24
+ -d, --deployments
25
+ lists the deployments from your deplo.yml file and exit
26
+
27
+ -I DIRECTORY, --include=DIRECTORY
28
+ path containing custom pre/post install tasks and source control handling
29
+ }
30
+
31
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
32
+
33
+ require 'getoptlong'
34
+ require 'rdoc/usage'
35
+ require 'deployaml'
36
+
37
+
38
+ def list_tasks deployaml
39
+ %w{ pre_install post_install }.each do |thingy|
40
+ puts "All #{thingy}:"
41
+ deployaml.send('all_' + thingy).each do |elem|
42
+ puts "\t#{elem}"
43
+ end
44
+ puts "\n"
45
+ end
46
+
47
+ exit(0)
48
+ end
49
+
50
+ def list_scms deployaml
51
+ puts "All scms:"
52
+ deployaml.all_scms.each do |elem|
53
+ puts "\t#{elem}"
54
+ end
55
+ puts "\n"
56
+
57
+ exit(0)
58
+ end
59
+
60
+ def list_deployments deployaml
61
+ puts "Available deployments:"
62
+ deployaml.available_deployments.each do |deployment|
63
+ puts "\t#{deployment}"
64
+ end
65
+ puts "\n"
66
+
67
+ exit(0)
68
+ end
69
+
70
+ def show_usage
71
+ markup = SM::SimpleMarkup.new
72
+ flow_convertor = SM::ToFlow.new
73
+
74
+ flow = markup.convert($usage, flow_convertor)
75
+
76
+ options = RI::Options.instance
77
+ formatter = options.formatter.new(options, "")
78
+ formatter.display_flow(flow)
79
+
80
+ exit(0)
81
+ end
82
+
83
+ def include_path_from_options(opts)
84
+ include_path = nil
85
+
86
+ remaining_options = []
87
+ opts.each do |opt, arg|
88
+ case opt
89
+ when '--include'
90
+ include_path = arg
91
+ else
92
+ remaining_options << [opt, arg]
93
+ end
94
+ end
95
+
96
+ return include_path, remaining_options
97
+ end
98
+
99
+ include_path, opts = include_path_from_options(
100
+ GetoptLong.new(
101
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
102
+ ['--tasks', '-l', GetoptLong::NO_ARGUMENT],
103
+ ['--scms', '-s', GetoptLong::NO_ARGUMENT],
104
+ ['--deployments', '-d', GetoptLong::NO_ARGUMENT],
105
+ ['--version', '-v', GetoptLong::REQUIRED_ARGUMENT],
106
+ ['--include', '-I', GetoptLong::REQUIRED_ARGUMENT]
107
+ )
108
+ )
109
+
110
+ deployaml = Deployaml::Runner.new(include_path ? {:include => include_path} : {})
111
+ version = nil
112
+
113
+ opts.each do |opt, arg|
114
+ case opt
115
+ when '--help'
116
+ show_usage
117
+ when '--tasks'
118
+ list_tasks(deployaml)
119
+ when '--scms'
120
+ list_scms(deployaml)
121
+ when '--deployments'
122
+ list_deployments(deployaml)
123
+ when '--version'
124
+ version = arg
125
+ end
126
+ end
127
+
128
+ deployaml.go!(:version => version)
129
+
data/lib/deployaml.rb ADDED
@@ -0,0 +1,120 @@
1
+ require 'fileutils'
2
+
3
+ Dir.glob(File.join(File.dirname(__FILE__), 'deployaml', '**', '*.rb')).each do |file|
4
+ require file
5
+ end
6
+
7
+ module Deployaml
8
+ class Runner
9
+ VERSION = '0.1'
10
+
11
+ def initialize(args = {})
12
+ load_custom_path(args[:include]) if args[:include]
13
+ load_deployments
14
+ load_scm
15
+ load_pre_install_tasks
16
+ load_post_install_tasks
17
+ end
18
+
19
+ def all_scms
20
+ @scms.keys.sort
21
+ end
22
+
23
+ def all_pre_install
24
+ @pre_install.keys.sort
25
+ end
26
+
27
+ def all_post_install
28
+ @post_install.keys.sort
29
+ end
30
+
31
+ def available_deployments
32
+ @deployments.sort { |a, b| a.name <=> b.name }.map do |deployment|
33
+ "#{deployment.name} (from #{deployment.scm})"
34
+ end
35
+ end
36
+
37
+ def go!(args = {})
38
+ @deployments.each do |deployment|
39
+ puts "Deploying #{deployment.name}"
40
+ scm = concrete_scm(deployment)
41
+ scm.stage(deployment, args[:version])
42
+
43
+ run_pre_install_tasks(deployment)
44
+
45
+ deployment.destinations.each do |destination|
46
+ destination.install_from deployment.staging_path
47
+ run_post_install_tasks(deployment, destination)
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def children_of constant
55
+ classes = {}
56
+
57
+ Deployaml.const_get(constant).constants.each do |scm|
58
+ underscore_name = scm.gsub(/[A-Z]/) { |x| '_' + x.downcase }.gsub(/^_/, '')
59
+ classes[underscore_name] = Deployaml.const_get(constant).const_get(scm).new
60
+ end
61
+
62
+ classes
63
+ end
64
+
65
+ def find_class_from_collection collection, nice_collection_type, nice_class, deployment
66
+ klass = collection.find { |x| x[0] == nice_class }
67
+
68
+ return klass[1] if klass
69
+
70
+ raise "Do not know of #{nice_collection_type} '#{nice_class}' for '#{deployment.name}'. Available: #{collection.keys.sort.join(', ')}"
71
+ end
72
+
73
+ def concrete_scm deployment
74
+ find_class_from_collection(@scms, 'scm', deployment.scm, deployment)
75
+ end
76
+
77
+ def load_scm
78
+ @scms = children_of 'Scm'
79
+ end
80
+
81
+ def load_pre_install_tasks
82
+ @pre_install = children_of 'PreInstall'
83
+ end
84
+
85
+ def load_post_install_tasks
86
+ @post_install = children_of 'PostInstall'
87
+ end
88
+
89
+ def load_custom_path path
90
+ Dir.glob(File.join(path, '**', '*.rb')).each do |file|
91
+ require file
92
+ end
93
+ end
94
+
95
+ def run_pre_install_tasks deployment
96
+ return if deployment.pre_install_tasks.nil? || deployment.pre_install_tasks.empty?
97
+
98
+ deployment.pre_install_tasks.each do |task|
99
+ task_klass = find_class_from_collection(@pre_install, 'pre_install', task['task'], deployment)
100
+ task_klass.run(deployment, task['parameters'])
101
+ end
102
+ end
103
+
104
+ def run_post_install_tasks deployment, destination
105
+ return if deployment.post_install_tasks.nil? || deployment.post_install_tasks.empty?
106
+
107
+ deployment.post_install_tasks.each do |task|
108
+ task_klass = find_class_from_collection(@post_install, 'post_install', task['task'], deployment)
109
+ task_klass.run(deployment, destination, task['parameters'])
110
+ end
111
+ end
112
+
113
+ def load_deployments
114
+ yaml_file = File.join(Dir.pwd, 'deplo.yml')
115
+ raise "Cannot find deployment YAML file #{yaml_file}" unless File.exists?(yaml_file)
116
+ yaml = YAML.load_file(yaml_file)
117
+ @deployments = yaml ? yaml.map { |d| Deployaml::Deployment.new(d) }.compact : []
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,48 @@
1
+ require 'tmpdir'
2
+ require File.join(File.dirname(__FILE__), 'destination')
3
+ require File.join(File.dirname(__FILE__), 'local_destination')
4
+ require File.join(File.dirname(__FILE__), 'remote_destination')
5
+
6
+ module Deployaml
7
+ class Deployment
8
+ attr_reader :scm, :name, :repository_path, :staging_path, :pre_install_tasks, :post_install_tasks, :destinations
9
+
10
+ def initialize params
11
+ validate params
12
+
13
+ @scm = params['repository']['scm'] || 'filesystem'
14
+ @name = params['name']
15
+ @repository_path = params['repository']['path']
16
+ @pre_install_tasks = params['pre_install']
17
+ @post_install_tasks = params['post_install']
18
+
19
+ initialize_destinations(params)
20
+ construct_stage
21
+ end
22
+
23
+ def construct_stage
24
+ @staging_path = File.join(Dir.tmpdir, 'deployaml', File.basename(repository_path))
25
+ FileUtils.rm_r(@staging_path) if File.directory?(@staging_path)
26
+ FileUtils.mkdir_p(@staging_path)
27
+ end
28
+
29
+ private
30
+
31
+ def initialize_destinations params
32
+ @destinations = []
33
+
34
+ params['destinations'].map {|d| @destinations << Deployaml::Destination.new(d)}
35
+ end
36
+
37
+ def validate params
38
+ raise "Deployment has no name" unless param_specified?(params['name'])
39
+ raise "Deployment '#{params['name']}' has no repository specified" unless param_specified?(params['repository'])
40
+ raise "No destinations specified for '#{params['name']}'" unless param_specified?(params['destinations'])
41
+ raise "No repository path specified for '#{params['name']}'" unless param_specified?(params['repository']['path'])
42
+ end
43
+
44
+ def param_specified? param
45
+ !param.nil? && !param.empty?
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ module Deployaml
2
+ class Destination
3
+ attr_reader :path, :live_path
4
+
5
+ def initialize params
6
+ @path = params['path'] || raise("A destination path must be specified")
7
+ @live_path = File.join(path, 'current')
8
+
9
+ @delegatee = params.has_key?('host') ?
10
+ Deployaml::RemoteDestination.new(params) :
11
+ Deployaml::LocalDestination.new(params)
12
+ end
13
+
14
+ def install_from local_path
15
+ exec("mkdir -p #{File.join(path, 'releases')}")
16
+
17
+ destination_path = File.join(path, 'releases', Time.now.strftime('%Y%m%d%H%M%S'))
18
+
19
+ @delegatee.copy(local_path, destination_path)
20
+
21
+ exec("rm -f #{live_path}")
22
+ exec("ln -s #{destination_path} #{live_path}")
23
+ end
24
+
25
+ def exec command
26
+ ok_message = rand.to_s
27
+
28
+ extra_command = " && echo #{ok_message}"
29
+
30
+ puts "$ #{command}"
31
+ had_error, output = @delegatee.execute_and_verify(command, extra_command, ok_message)
32
+ puts "\n"
33
+
34
+ raise "Error executing '#{command}'" if had_error
35
+
36
+ return output
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'open3'
2
+
3
+ module Deployaml
4
+ class LocalDestination
5
+ def initialize params
6
+ end
7
+
8
+ def execute_and_verify(command, extra_command, ok_message)
9
+ had_error = true
10
+ output = ''
11
+
12
+ Open3.popen3(command + extra_command) do |stdin, stdout, stderr|
13
+ stdout_output, stderr_output = stdout.read, stderr.read
14
+
15
+ if !stdout_output.empty?
16
+ if stdout_output.gsub!(/#{ok_message}\n/, '')
17
+ had_error = false
18
+ end
19
+
20
+ output += stdout_output
21
+ $stdout.print stdout_output
22
+ end
23
+
24
+ if !stderr_output.empty?
25
+ output += stderr_output
26
+ $stderr.print stderr_output
27
+ end
28
+ end
29
+
30
+ return had_error, output
31
+ end
32
+
33
+ def copy from, to
34
+ puts "Copying #{from} => #{to}"
35
+ FileUtils.cp_r(from, to)
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ module Deployaml
2
+ module PostInstall
3
+ class PendingMigrations
4
+
5
+ def run deployment, destination, params
6
+ destination.exec("RAILS_ENV=production cd #{destination.live_path} && rake db:migrate")
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Deployaml
2
+ module PostInstall
3
+ class RestartPassenger
4
+
5
+ def run deployment, destination, params
6
+ tmp_dir = File.join(destination.live_path, 'tmp')
7
+ destination.exec('mkdir -p ' + tmp_dir)
8
+ destination.exec('touch ' + File.join(tmp_dir, 'restart.txt'))
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ module Deployaml
2
+ module PreInstall
3
+ class Minify
4
+
5
+ def run deployment, params
6
+ yui_jar = File.join(
7
+ File.dirname(__FILE__),
8
+ '..', '..', '..', 'vendor', 'yuicompressor', 'build', 'yuicompressor-2.4.2.jar'
9
+ )
10
+
11
+ base_pattern = [deployment.staging_path, '**']
12
+
13
+ [Dir.glob(File.join(base_pattern + ['*.js'])), Dir.glob(File.join(base_pattern + ['*.css']))].flatten.each do |file|
14
+ puts "Minifying #{file}"
15
+ `java -jar #{yui_jar} #{file} -o #{file}`
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ module Deployaml
2
+ module PreInstall
3
+ class WriteStringToFile
4
+
5
+ def run deployment, params
6
+ File.open(File.join(deployment.staging_path, params['file']), 'w') do |fh|
7
+ fh.write(params['string'])
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,122 @@
1
+ require 'net/ssh'
2
+ require 'net/scp'
3
+ require 'highline'
4
+
5
+ module Deployaml
6
+ class RemoteDestination
7
+ def initialize params
8
+ @host = params['host'] || raise('A remote host must be specified')
9
+ @username = params['username'] || ENV['USER']
10
+ end
11
+
12
+ def session
13
+ @session_not_to_ever_be_called_directly ||= ssh_connect
14
+ end
15
+
16
+ def execute_and_verify(command, extra_command, ok_message)
17
+ had_error = true
18
+ output = ''
19
+
20
+ session.exec!(command + extra_command) do |ch, stream, data|
21
+ if stream == :stderr
22
+ $stderr.print data
23
+ output += data
24
+ else
25
+ if data.strip == ok_message
26
+ had_error = false
27
+ else
28
+ $stdout.print data
29
+ output += data
30
+ end
31
+ end
32
+ end
33
+
34
+ return had_error, output
35
+ end
36
+
37
+ def copy from, to
38
+ compressed_file = compress(from, to)
39
+ puts "Copying #{from} #{@username}@#{@host}:#{to}"
40
+
41
+ session.scp.upload!(compressed_file, to)
42
+
43
+ decompress(to)
44
+
45
+ puts "\n"
46
+
47
+ end
48
+
49
+ private
50
+
51
+ def compress from, to
52
+ puts "Compressing for transfer..."
53
+ root_directory, to_zip = File.dirname(from), File.basename(to)
54
+
55
+ compressed_file = to_zip + '.tgz'
56
+ `cd #{root_directory} && cp -rf #{from} #{to_zip} && tar -zcf #{compressed_file} #{to_zip}`
57
+
58
+ File.join(root_directory, compressed_file)
59
+ end
60
+
61
+ def decompress destination
62
+ puts "Inflating at destination..."
63
+ destination_root = File.dirname(destination)
64
+ compressed_file = File.basename(destination)
65
+ session.exec!("cd #{destination_root} && tar -zxf #{compressed_file}")
66
+ end
67
+
68
+ def ssh_connect
69
+ begin
70
+ connect_without_password
71
+ rescue Net::SSH::AuthenticationFailed
72
+ connect_with_password
73
+ end
74
+ end
75
+
76
+ def connect_without_password
77
+ Net::SSH.start(@host, @username)
78
+ end
79
+
80
+ def connect_with_password
81
+ flush_stdin
82
+ Net::SSH.start(
83
+ @host,
84
+ @username,
85
+ :password => HighLine.new.ask(
86
+ "#{@username}@#{@host}'s password: "
87
+ ) { |a| a.echo = false }
88
+ )
89
+ end
90
+
91
+ def flush_stdin
92
+ begin
93
+ require 'fcntl'
94
+ STDIN.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
95
+ STDIN.read
96
+ rescue
97
+ #
98
+ end
99
+ end
100
+
101
+ end
102
+ end
103
+
104
+ # weird string monkey patch
105
+ class String
106
+ def shellescape
107
+ # An empty argument will be skipped, so return empty quotes.
108
+ return "''" if self.empty?
109
+
110
+ str = self.dup
111
+
112
+ # Process as a single byte sequence because not all shell
113
+ # implementations are multibyte aware.
114
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
115
+
116
+ # A LF cannot be escaped with a backslash because a backslash + LF
117
+ # combo is regarded as line continuation and simply ignored.
118
+ str.gsub!(/\n/, "'\n'")
119
+
120
+ return str
121
+ end
122
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../scm_base'
2
+
3
+ module Deployaml
4
+ module Scm
5
+ class Filesystem < ScmBase
6
+ def fetch_files
7
+ raise "Cannot read repository #{deployment.repository_path} for '#{deployment.name}'" unless File.exists?(deployment.repository_path)
8
+
9
+ FileUtils.cp_r(deployment.repository_path, File.dirname(deployment.staging_path), :remove_destination => true)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/../scm_base'
2
+
3
+ module Deployaml
4
+ module Scm
5
+ class Git < ScmBase
6
+ def fetch_files
7
+ puts "Cloning #{deployment.repository_path}"
8
+ FileUtils.rm_r(deployment.staging_path) if File.exists?(deployment.staging_path)
9
+ cloned?(`git clone #{deployment.repository_path} #{deployment.staging_path} 2>&1`)
10
+
11
+ `cd #{deployment.staging_path} && git checkout #{version}` if version
12
+
13
+ `cd #{deployment.staging_path} && git submodule init && git submodule update`
14
+ end
15
+
16
+ def cloned? result
17
+ if result =~ /fatal:/
18
+ raise "Cannot read repository #{deployment.repository_path} for '#{deployment.name}'" if result =~ /not a git archive/ || result =~ /not appear to be a git repository/ || result =~ /Could not switch to/
19
+ raise "Error cloning #{deployment.repository_path}: #{result}"
20
+ end
21
+ end
22
+
23
+ def clean
24
+ # remove all the gittish files
25
+ Dir.glob(File.join(deployment.staging_path, '**', '.git*')).each do |git_file|
26
+ FileUtils.rm_r(git_file)
27
+ end
28
+
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ module Deployaml
2
+ class ScmBase
3
+ attr_reader :deployment, :version
4
+
5
+ def stage deployment, version = nil
6
+ @deployment = deployment
7
+ @version = version
8
+ fetch_files
9
+ clean
10
+ end
11
+
12
+ def clean
13
+ deploy_file = File.join(deployment.staging_path, 'deplo.yml')
14
+ File.unlink(deploy_file) if File.exists?(deploy_file)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <project name="YUI Compressor" default="build.jar" basedir=".">
3
+
4
+ <target name="clean" depends="-load.properties">
5
+ <delete dir="${build.dir}" quiet="true"/>
6
+ </target>
7
+
8
+ <target name="-load.properties">
9
+ <property file="ant.properties"/>
10
+ </target>
11
+
12
+ <target name="-init" depends="-load.properties">
13
+ <mkdir dir="${build.dir}"/>
14
+ </target>
15
+
16
+ <target name="build.classes" depends="-init">
17
+ <mkdir dir="${build.dir}/classes"/>
18
+ <javac srcdir="${src.dir}"
19
+ destdir="${build.dir}/classes"
20
+ includes="**/*.java"
21
+ deprecation="off"
22
+ debug="on"
23
+ source="1.4">
24
+ <classpath>
25
+ <pathelement location="${lib.dir}/jargs-1.0.jar"/>
26
+ <pathelement location="${lib.dir}/rhino-1.6R7.jar"/>
27
+ </classpath>
28
+ </javac>
29
+ </target>
30
+
31
+ <target name="build.jar" depends="build.classes">
32
+ <mkdir dir="${build.dir}/jar"/>
33
+ <!-- The order is important here. Rhino MUST be unjarred first!
34
+ (some of our own classes will override the Rhino classes) -->
35
+ <unjar src="${lib.dir}/jargs-1.0.jar" dest="${build.dir}/jar"/>
36
+ <unjar src="${lib.dir}/rhino-1.6R7.jar" dest="${build.dir}/jar"/>
37
+ <copy todir="${build.dir}/jar">
38
+ <fileset dir="${build.dir}/classes" includes="**/*.class"/>
39
+ </copy>
40
+ <jar destfile="${build.dir}/${jar.name}" basedir="${build.dir}/jar">
41
+ <manifest>
42
+ <attribute name="Main-Class" value="com.yahoo.platform.yui.compressor.Bootstrap"/>
43
+ </manifest>
44
+ </jar>
45
+ </target>
46
+
47
+ <target name="build.dist.package" depends="build.jar">
48
+ <mkdir dir="${build.dir}/${dist.package.name}"/>
49
+ <mkdir dir="${build.dir}/${dist.package.name}/build"/>
50
+ <copy file="${build.dir}/${jar.name}" todir="${build.dir}/${dist.package.name}/build"/>
51
+ <copy todir="${build.dir}/${dist.package.name}">
52
+ <fileset dir=".">
53
+ <include name="ant.properties"/>
54
+ <include name="build.xml"/>
55
+ <include name="doc/**/*"/>
56
+ <include name="lib/**/*"/>
57
+ <include name="src/**/*"/>
58
+ <exclude name="**/CVS"/>
59
+ </fileset>
60
+ </copy>
61
+ <zip destfile="${build.dir}/${dist.package.name}.zip"
62
+ basedir="${build.dir}"
63
+ includes="${dist.package.name}/**/*"/>
64
+ </target>
65
+
66
+ </project>
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deployaml
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Stephen Hardisty
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-09-20 00:00:00 +10:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: net-ssh
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 2
28
+ - 0
29
+ - 11
30
+ version: 2.0.11
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: net-scp
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 0
43
+ - 3
44
+ version: 1.0.3
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: highline
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 2
57
+ - 9
58
+ version: 1.2.9
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubyforge
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 2
70
+ - 0
71
+ - 4
72
+ version: 2.0.4
73
+ type: :development
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: hoe
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 2
84
+ - 6
85
+ - 1
86
+ version: 2.6.1
87
+ type: :development
88
+ version_requirements: *id005
89
+ description: YAML based deployment framework for your code.
90
+ email:
91
+ - moowahaha@hotmail.com
92
+ executables:
93
+ - deployaml
94
+ extensions: []
95
+
96
+ extra_rdoc_files:
97
+ - History.txt
98
+ - Manifest.txt
99
+ files:
100
+ - History.txt
101
+ - Manifest.txt
102
+ - README.rdoc
103
+ - Rakefile
104
+ - bin/deployaml
105
+ - lib/deployaml.rb
106
+ - lib/deployaml/deployment.rb
107
+ - lib/deployaml/destination.rb
108
+ - lib/deployaml/local_destination.rb
109
+ - lib/deployaml/post_install/pending_migrations.rb
110
+ - lib/deployaml/post_install/restart_passenger.rb
111
+ - lib/deployaml/pre_install/minify.rb
112
+ - lib/deployaml/pre_install/write_string_to_file.rb
113
+ - lib/deployaml/remote_destination.rb
114
+ - lib/deployaml/scm/filesystem.rb
115
+ - lib/deployaml/scm/git.rb
116
+ - lib/deployaml/scm_base.rb
117
+ - vendor/yuicompressor/build.xml
118
+ - vendor/yuicompressor/build/yuicompressor-2.4.2.jar
119
+ has_rdoc: true
120
+ homepage: http://www.advancethinking.com/open_source/deployaml
121
+ licenses: []
122
+
123
+ post_install_message:
124
+ rdoc_options:
125
+ - --main
126
+ - README.rdoc
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ requirements: []
144
+
145
+ rubyforge_project: deployaml
146
+ rubygems_version: 1.3.6
147
+ signing_key:
148
+ specification_version: 3
149
+ summary: YAML based deployment framework for your code.
150
+ test_files: []
151
+