statistrano 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/changelog.md +161 -0
- data/doc/config/file-permissions.md +33 -0
- data/doc/config/log-files.md +32 -0
- data/doc/config/task-definitions.md +88 -0
- data/doc/getting-started.md +96 -0
- data/doc/strategies/base.md +38 -0
- data/doc/strategies/branches.md +82 -0
- data/doc/strategies/releases.md +110 -0
- data/doc/strategies.md +17 -0
- data/lib/statistrano/config/configurable.rb +53 -0
- data/lib/statistrano/config/rake_task_with_context_creation.rb +43 -0
- data/lib/statistrano/config.rb +52 -0
- data/lib/statistrano/deployment/log_file.rb +44 -0
- data/lib/statistrano/deployment/manifest.rb +88 -0
- data/lib/statistrano/deployment/rake_tasks.rb +74 -0
- data/lib/statistrano/deployment/registerable.rb +11 -0
- data/lib/statistrano/deployment/releaser/revisions.rb +163 -0
- data/lib/statistrano/deployment/releaser/single.rb +48 -0
- data/lib/statistrano/deployment/releaser.rb +2 -0
- data/lib/statistrano/deployment/strategy/base.rb +132 -0
- data/lib/statistrano/deployment/strategy/branches/index/template.html.erb +78 -0
- data/lib/statistrano/deployment/strategy/branches/index.rb +40 -0
- data/lib/statistrano/deployment/strategy/branches/release.rb +73 -0
- data/lib/statistrano/deployment/strategy/branches.rb +198 -0
- data/lib/statistrano/deployment/strategy/check_git.rb +43 -0
- data/lib/statistrano/deployment/strategy/invoke_tasks.rb +58 -0
- data/lib/statistrano/deployment/strategy/releases.rb +76 -0
- data/lib/statistrano/deployment/strategy.rb +37 -0
- data/lib/statistrano/deployment.rb +10 -0
- data/lib/statistrano/log/default_logger.rb +105 -0
- data/lib/statistrano/log.rb +33 -0
- data/lib/statistrano/remote/file.rb +79 -0
- data/lib/statistrano/remote.rb +111 -0
- data/lib/statistrano/shell.rb +17 -0
- data/lib/statistrano/util/file_permissions.rb +34 -0
- data/lib/statistrano/util.rb +27 -0
- data/lib/statistrano/version.rb +3 -0
- data/lib/statistrano.rb +55 -0
- data/readme.md +247 -0
- data/spec/integration_tests/base_integration_spec.rb +103 -0
- data/spec/integration_tests/branches_integration_spec.rb +189 -0
- data/spec/integration_tests/releases/deploy_integration_spec.rb +116 -0
- data/spec/integration_tests/releases/list_releases_integration_spec.rb +38 -0
- data/spec/integration_tests/releases/prune_releases_integration_spec.rb +86 -0
- data/spec/integration_tests/releases/rollback_release_integration_spec.rb +46 -0
- data/spec/lib/statistrano/config/configurable_spec.rb +88 -0
- data/spec/lib/statistrano/config/rake_task_with_context_creation_spec.rb +73 -0
- data/spec/lib/statistrano/config_spec.rb +34 -0
- data/spec/lib/statistrano/deployment/log_file_spec.rb +75 -0
- data/spec/lib/statistrano/deployment/manifest_spec.rb +171 -0
- data/spec/lib/statistrano/deployment/rake_tasks_spec.rb +107 -0
- data/spec/lib/statistrano/deployment/registerable_spec.rb +19 -0
- data/spec/lib/statistrano/deployment/releaser/revisions_spec.rb +486 -0
- data/spec/lib/statistrano/deployment/releaser/single_spec.rb +59 -0
- data/spec/lib/statistrano/deployment/strategy/base_spec.rb +158 -0
- data/spec/lib/statistrano/deployment/strategy/branches_spec.rb +19 -0
- data/spec/lib/statistrano/deployment/strategy/check_git_spec.rb +39 -0
- data/spec/lib/statistrano/deployment/strategy/invoke_tasks_spec.rb +66 -0
- data/spec/lib/statistrano/deployment/strategy/releases_spec.rb +257 -0
- data/spec/lib/statistrano/deployment/strategy_spec.rb +76 -0
- data/spec/lib/statistrano/deployment_spec.rb +4 -0
- data/spec/lib/statistrano/log/default_logger_spec.rb +172 -0
- data/spec/lib/statistrano/log_spec.rb +36 -0
- data/spec/lib/statistrano/remote/file_spec.rb +166 -0
- data/spec/lib/statistrano/remote_spec.rb +226 -0
- data/spec/lib/statistrano/util/file_permissions_spec.rb +25 -0
- data/spec/lib/statistrano/util_spec.rb +23 -0
- data/spec/lib/statistrano_spec.rb +52 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/support/given.rb +39 -0
- metadata +223 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module Statistrano
|
2
|
+
class Config
|
3
|
+
module Configurable
|
4
|
+
|
5
|
+
def configuration
|
6
|
+
@_configuration ||= Config.new()
|
7
|
+
end
|
8
|
+
|
9
|
+
def option key, value=nil, proc=nil
|
10
|
+
if proc
|
11
|
+
configuration.options[key] = { call: proc }
|
12
|
+
else
|
13
|
+
configuration.options[key] = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def options *args
|
18
|
+
args.each { |a| option(a) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def task name, method, description
|
22
|
+
configuration.tasks[name] = {
|
23
|
+
method: method,
|
24
|
+
desc: description
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# add a config method to objects that
|
29
|
+
# extend Configurable
|
30
|
+
#
|
31
|
+
def self.extended extending_obj
|
32
|
+
extending_obj.send :define_method,
|
33
|
+
:config,
|
34
|
+
-> {
|
35
|
+
@_config ||= Config.new( self.class.configuration.options,
|
36
|
+
self.class.configuration.tasks )
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# make sure that classes that inherit from
|
41
|
+
# classes that have been configured also inherit
|
42
|
+
# the configuration of the parent class
|
43
|
+
#
|
44
|
+
def inherited subclass
|
45
|
+
subclass.superclass.class_eval do
|
46
|
+
subclass.configuration.options.merge! subclass.superclass.configuration.options
|
47
|
+
subclass.configuration.tasks.merge! subclass.superclass.configuration.tasks
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Statistrano
|
2
|
+
class Config
|
3
|
+
|
4
|
+
module RakeTaskWithContextCreation
|
5
|
+
|
6
|
+
def self.included base
|
7
|
+
base.module_eval do
|
8
|
+
def user_task_namespaces
|
9
|
+
@_user_task_namespaces ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def user_tasks
|
13
|
+
@_user_tasks ||= []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def namespace namespace, &block
|
19
|
+
context = Context.new (user_task_namespaces + [namespace])
|
20
|
+
context.instance_eval &block
|
21
|
+
user_tasks.push *context.user_tasks
|
22
|
+
end
|
23
|
+
|
24
|
+
def task name, desc=nil, &block
|
25
|
+
task = { name: name,
|
26
|
+
namespaces: user_task_namespaces,
|
27
|
+
block: block }
|
28
|
+
task.merge!(desc: desc) if desc
|
29
|
+
|
30
|
+
user_tasks.push task
|
31
|
+
end
|
32
|
+
|
33
|
+
class Context
|
34
|
+
include RakeTaskWithContextCreation
|
35
|
+
|
36
|
+
def initialize namespaces=[]
|
37
|
+
@_user_task_namespaces = namespaces
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'config/configurable'
|
2
|
+
require_relative 'config/rake_task_with_context_creation'
|
3
|
+
|
4
|
+
module Statistrano
|
5
|
+
class Config
|
6
|
+
include RakeTaskWithContextCreation
|
7
|
+
|
8
|
+
attr_reader :options
|
9
|
+
attr_reader :tasks
|
10
|
+
|
11
|
+
# initalize with the potential for seed options
|
12
|
+
# this is required so that when config'd classes
|
13
|
+
# are extended we can pass that configuration along
|
14
|
+
def initialize options=nil, tasks=nil
|
15
|
+
@options = options.nil? ? {} : options.clone
|
16
|
+
@tasks = tasks.nil? ? {} : tasks.clone
|
17
|
+
|
18
|
+
@options.each do |key,val|
|
19
|
+
define_option_accessor key.to_sym
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def define_option_accessor name
|
26
|
+
define_singleton_method(name) do |*args, &block|
|
27
|
+
if block
|
28
|
+
if args.first == :call
|
29
|
+
@options[name] = { call: block }
|
30
|
+
else
|
31
|
+
@options[name] = block
|
32
|
+
end
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
if args.length == 1
|
37
|
+
@options[name] = args[0]
|
38
|
+
elsif args.empty?
|
39
|
+
if @options[name].respond_to? :fetch
|
40
|
+
@options[name].fetch( :call, -> { @options[name] } ).call
|
41
|
+
else
|
42
|
+
@options[name]
|
43
|
+
end
|
44
|
+
else
|
45
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
define_singleton_method("#{name}=") { |arg| @options[name] = arg }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Statistrano
|
2
|
+
module Deployment
|
3
|
+
class LogFile
|
4
|
+
|
5
|
+
attr_reader :resolved_path, :remote, :file
|
6
|
+
|
7
|
+
def initialize path, remote
|
8
|
+
@remote = remote
|
9
|
+
@resolved_path = resolve_path path
|
10
|
+
@file = Remote::File.new @resolved_path, remote
|
11
|
+
end
|
12
|
+
|
13
|
+
def append! log_entry
|
14
|
+
file.append_content! log_entry.to_json
|
15
|
+
end
|
16
|
+
|
17
|
+
def last_entry
|
18
|
+
entries(1).last || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def tail length=10
|
22
|
+
entries(length)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def entries length=10
|
28
|
+
entries = file.content.split("\n") || []
|
29
|
+
entries.reverse[0...length].map do |e|
|
30
|
+
Util.symbolize_hash_keys( JSON.parse(e) )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def resolve_path path
|
35
|
+
if path.start_with? '/'
|
36
|
+
path
|
37
|
+
else
|
38
|
+
File.join( remote.config.remote_dir, path )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Statistrano
|
2
|
+
module Deployment
|
3
|
+
class Manifest
|
4
|
+
|
5
|
+
attr_reader :remote_dir, :remote, :file
|
6
|
+
|
7
|
+
def initialize remote_dir, remote
|
8
|
+
@remote_dir = remote_dir
|
9
|
+
@remote = remote
|
10
|
+
@file = Remote::File.new remote_path, remote
|
11
|
+
end
|
12
|
+
|
13
|
+
# return an array of records from the manifest
|
14
|
+
# they are processed to all have symbolized keys
|
15
|
+
#
|
16
|
+
def data
|
17
|
+
@_data ||= Array( JSON.parse(raw) ).map { |h| Util.symbolize_hash_keys(h) }
|
18
|
+
rescue JSON::ParserError => e
|
19
|
+
Log.error "manifest on #{remote.config.hostname} had invalid JSON\n",
|
20
|
+
e.message
|
21
|
+
end
|
22
|
+
|
23
|
+
# push data into the manifest array updating a
|
24
|
+
# record if it matches with the `match_key`
|
25
|
+
#
|
26
|
+
# not that if you have used the `push` method previously
|
27
|
+
# all duplicates with the matching key **will** be removed
|
28
|
+
#
|
29
|
+
def put data, match_key
|
30
|
+
remove_if { |i| i[match_key] == data[match_key] }
|
31
|
+
push data
|
32
|
+
end
|
33
|
+
|
34
|
+
# pushes a data has into the manifest's array
|
35
|
+
#
|
36
|
+
def push new_data
|
37
|
+
unless new_data.respond_to? :to_json
|
38
|
+
raise ArgumentError, "data must be serializable as JSON"
|
39
|
+
end
|
40
|
+
|
41
|
+
data << Util.symbolize_hash_keys(new_data)
|
42
|
+
end
|
43
|
+
|
44
|
+
# pass a condition to remove records from the
|
45
|
+
# manifest if it returns true
|
46
|
+
#
|
47
|
+
# example:
|
48
|
+
# to remove all records with the name "name"
|
49
|
+
#
|
50
|
+
# manifest.remove_if |release|
|
51
|
+
# release[:name] == "name"
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
def remove_if &condition
|
55
|
+
data.delete_if do |item|
|
56
|
+
condition.call item
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# update the manifest using the data
|
61
|
+
# currently stored on the object
|
62
|
+
#
|
63
|
+
def save!
|
64
|
+
file.update_content! serialize
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def raw
|
70
|
+
content = file.content
|
71
|
+
if content.empty?
|
72
|
+
return "[]"
|
73
|
+
else
|
74
|
+
return content
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def serialize data=data
|
79
|
+
data.to_json
|
80
|
+
end
|
81
|
+
|
82
|
+
def remote_path
|
83
|
+
File.join( remote_dir, 'manifest.json' )
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Statistrano
|
2
|
+
module Deployment
|
3
|
+
|
4
|
+
module RakeTasks
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Add rake tasks
|
8
|
+
include ::Rake::DSL
|
9
|
+
|
10
|
+
# Register the rake tasks for the deployment
|
11
|
+
# @return [Void]
|
12
|
+
def register deployment
|
13
|
+
deployment.config.tasks.each do |task_name, task_attrs|
|
14
|
+
in_namespace rake_namespace(deployment) do
|
15
|
+
register_task deployment, task_name, task_attrs
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
deployment.config.user_tasks.each do |task_obj|
|
20
|
+
in_namespace rake_namespace(deployment) do
|
21
|
+
register_in_namespace_recursive deployment,
|
22
|
+
task_obj[:name],
|
23
|
+
task_obj[:desc],
|
24
|
+
task_obj[:namespaces],
|
25
|
+
task_obj[:block]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def rake_namespace deployment
|
33
|
+
deployment.name.to_sym
|
34
|
+
end
|
35
|
+
|
36
|
+
def in_namespace namespace, &block
|
37
|
+
namespace namespace do
|
38
|
+
yield
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def register_task deployment, task_name, attrs={}
|
43
|
+
desc attrs[:desc]
|
44
|
+
task task_name do
|
45
|
+
deployment.public_send attrs[:method]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def register_in_namespace_recursive deployment, task_name, task_desc, task_space, block
|
50
|
+
if task_space.empty?
|
51
|
+
register_user_task deployment, task_name, task_desc, block
|
52
|
+
else
|
53
|
+
in_namespace task_space.first do
|
54
|
+
register_in_namespace_recursive deployment, task_name, task_desc, task_space[1..-1], block
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def register_user_task deployment, task_name, task_desc, block
|
60
|
+
t = task task_name do
|
61
|
+
if block.arity == 1
|
62
|
+
block.call deployment
|
63
|
+
else
|
64
|
+
block.call
|
65
|
+
end
|
66
|
+
end
|
67
|
+
t.add_description(task_desc) if task_desc
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Statistrano
|
2
|
+
module Deployment
|
3
|
+
module Releaser
|
4
|
+
|
5
|
+
class Revisions
|
6
|
+
include Strategy::InvokeTasks
|
7
|
+
|
8
|
+
attr_reader :release_name
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@release_name = Time.now.to_i.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_release remote, build_data={}
|
15
|
+
setup_release_path remote
|
16
|
+
rsync_to_remote remote
|
17
|
+
invoke_pre_symlink_task remote
|
18
|
+
symlink_release remote
|
19
|
+
add_release_to_manifest remote, build_data
|
20
|
+
prune_releases remote
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_release_path remote
|
24
|
+
current_release = current_release remote
|
25
|
+
remote.create_remote_dir releases_path(remote)
|
26
|
+
|
27
|
+
if current_release.empty?
|
28
|
+
remote.create_remote_dir release_path(remote)
|
29
|
+
else
|
30
|
+
remote.run "cp -a #{release_path(remote, current_release)} #{release_path(remote)}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def rsync_to_remote remote
|
35
|
+
resp = remote.rsync_to_remote local_path(remote), release_path(remote)
|
36
|
+
unless resp.success?
|
37
|
+
abort()
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def symlink_release remote, release=nil
|
42
|
+
remote.run "ln -nfs #{release_path(remote, release)} #{public_path(remote)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def prune_releases remote
|
46
|
+
remove_untracked_releases remote
|
47
|
+
remove_releases_beyond_release_count remote
|
48
|
+
end
|
49
|
+
|
50
|
+
def list_releases remote
|
51
|
+
manifest = new_manifest remote
|
52
|
+
manifest.data.keep_if do |rel|
|
53
|
+
rel.has_key?(:release)
|
54
|
+
end.sort_by do |rel|
|
55
|
+
rel[:release]
|
56
|
+
end.reverse
|
57
|
+
end
|
58
|
+
|
59
|
+
# merge of manifest & log data (if a log)
|
60
|
+
def current_release_data remote
|
61
|
+
release_data = new_manifest(remote).data.last
|
62
|
+
|
63
|
+
if remote.config.log_file_path
|
64
|
+
release_data.merge! log_file(remote).last_entry
|
65
|
+
end
|
66
|
+
|
67
|
+
release_data
|
68
|
+
end
|
69
|
+
|
70
|
+
def rollback_release remote
|
71
|
+
manifest = new_manifest remote
|
72
|
+
releases = tracked_releases remote, manifest
|
73
|
+
|
74
|
+
unless releases.length > 1
|
75
|
+
return Log.error "There is only one release, best not to remove it"
|
76
|
+
end
|
77
|
+
|
78
|
+
symlink_release remote, releases[1]
|
79
|
+
remove_release releases[0], remote, manifest
|
80
|
+
manifest.save!
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_release_to_manifest remote, build_data={}
|
84
|
+
manifest = new_manifest remote
|
85
|
+
manifest.push build_data.merge(release: release_name)
|
86
|
+
manifest.save!
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def new_manifest remote
|
92
|
+
Deployment::Manifest.new remote.config.remote_dir, remote
|
93
|
+
end
|
94
|
+
|
95
|
+
def log_file remote
|
96
|
+
Deployment::LogFile.new remote.config.log_file_path, remote
|
97
|
+
end
|
98
|
+
|
99
|
+
def remove_releases_beyond_release_count remote
|
100
|
+
manifest = new_manifest remote
|
101
|
+
beyond = tracked_releases(remote, manifest)[remote.config.release_count..-1]
|
102
|
+
Array(beyond).each do |beyond|
|
103
|
+
remove_release beyond, remote, manifest
|
104
|
+
end
|
105
|
+
manifest.save!
|
106
|
+
end
|
107
|
+
|
108
|
+
def remove_release release_name, remote, manifest
|
109
|
+
if release_name == current_release(remote)
|
110
|
+
Log.warn "did not remove release '#{release_name}' because it is current"
|
111
|
+
return
|
112
|
+
end
|
113
|
+
|
114
|
+
manifest.remove_if { |r| r[:release] == release_name }
|
115
|
+
remote.run("rm -rf #{File.join(releases_path(remote), release_name)}")
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_untracked_releases remote
|
119
|
+
manifest = new_manifest remote
|
120
|
+
(remote_releases(remote) - tracked_releases(remote)).each do |untracked_release|
|
121
|
+
remove_release untracked_release, remote, manifest
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def current_release remote
|
126
|
+
resp = remote.run("readlink #{public_path(remote)}")
|
127
|
+
resp.stdout.sub( /#{releases_path(remote)}\/?/, '' ).strip
|
128
|
+
end
|
129
|
+
|
130
|
+
def remote_releases remote
|
131
|
+
remote.run("ls -m #{releases_path(remote)}").stdout
|
132
|
+
.split(',').map(&:strip)
|
133
|
+
end
|
134
|
+
|
135
|
+
def tracked_releases remote, manifest=nil
|
136
|
+
manifest ||= new_manifest remote
|
137
|
+
manifest.data.map do |data|
|
138
|
+
data.fetch(:release, nil)
|
139
|
+
end.compact.sort.reverse
|
140
|
+
end
|
141
|
+
|
142
|
+
def local_path remote=nil
|
143
|
+
File.join( Dir.pwd, remote.config.local_dir )
|
144
|
+
end
|
145
|
+
|
146
|
+
def releases_path remote=nil
|
147
|
+
File.join( remote.config.remote_dir, remote.config.release_dir )
|
148
|
+
end
|
149
|
+
|
150
|
+
def release_path remote=nil, release=nil
|
151
|
+
release ||= release_name
|
152
|
+
File.join( releases_path(remote), release )
|
153
|
+
end
|
154
|
+
|
155
|
+
def public_path remote=nil
|
156
|
+
File.join( remote.config.remote_dir, remote.config.public_dir )
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Statistrano
|
2
|
+
module Deployment
|
3
|
+
module Releaser
|
4
|
+
|
5
|
+
class Single
|
6
|
+
|
7
|
+
attr_reader :release_name
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@release_name = Time.now.to_i.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_release remote, build_data={}
|
14
|
+
setup remote
|
15
|
+
rsync_to_remote remote
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup remote
|
19
|
+
Log.info "Setting up the remote"
|
20
|
+
remote.run "mkdir -p #{remote_path(remote)}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def rsync_to_remote remote
|
24
|
+
resp = remote.rsync_to_remote local_path(remote), remote_path(remote)
|
25
|
+
unless resp.success?
|
26
|
+
abort()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def local_path remote
|
33
|
+
File.join( Dir.pwd, remote.config.local_dir )
|
34
|
+
end
|
35
|
+
|
36
|
+
def remote_path remote=nil
|
37
|
+
if remote.config.respond_to?(:public_dir) && remote.config.public_dir
|
38
|
+
return File.join( remote.config.remote_dir, remote.config.public_dir )
|
39
|
+
else
|
40
|
+
return remote.config.remote_dir
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|