deployaml 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+