statistrano 1.2.0
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.
- 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
|