ferry 1.3.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/ferry +4 -4
- data/{doc → img}/ferry_readme_icon.png +0 -0
- data/{doc → img}/ferry_readme_icon_2.png +0 -0
- data/lib/Ferryfile +3 -0
- data/lib/ferry/all.rb +14 -0
- data/lib/ferry/configuration.rb +142 -0
- data/lib/ferry/configuration/filter.rb +56 -0
- data/lib/ferry/configuration/question.rb +53 -0
- data/lib/ferry/configuration/server.rb +131 -0
- data/lib/ferry/configuration/servers.rb +69 -0
- data/lib/ferry/defaults.rb +3 -0
- data/lib/ferry/deploy.rb +3 -0
- data/lib/ferry/dotfile.rb +2 -0
- data/lib/ferry/dsl.rb +64 -0
- data/lib/ferry/dsl/env.rb +81 -0
- data/lib/ferry/dsl/paths.rb +103 -0
- data/lib/ferry/dsl/stages.rb +19 -0
- data/lib/ferry/dsl/task_enhancements.rb +65 -0
- data/lib/ferry/framework.rb +2 -0
- data/lib/ferry/i18n.rb +18 -0
- data/lib/ferry/install.rb +1 -0
- data/lib/ferry/setup.rb +22 -0
- data/lib/ferry/tasks/deploy.rake +226 -0
- data/lib/ferry/tasks/framework.rake +52 -0
- data/lib/ferry/tasks/install.rake +41 -0
- data/lib/ferry/templates/Ferryfile +8 -0
- data/lib/ferry/templates/deploy_ferry.rb.erb +21 -0
- data/lib/ferry/templates/stage.rb.erb +1 -0
- data/lib/ferry/upload_task.rb +9 -0
- data/lib/ferry/utilities.rb +0 -12
- data/lib/ferry/version.rb +1 -1
- metadata +31 -7
- data/doc/ferry_rake_contents.rb +0 -9
- data/lib/ferry/dsl/captain.rb +0 -17
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'ferry/configuration'
|
3
|
+
require 'ferry/configuration/filter'
|
4
|
+
|
5
|
+
module Ferry
|
6
|
+
class Configuration
|
7
|
+
class Servers
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def add_host(host, properties={})
|
11
|
+
new_host = Server[host]
|
12
|
+
if server = servers.find { |s| s.matches? new_host }
|
13
|
+
server.user = new_host.user if new_host.user
|
14
|
+
server.port = new_host.port if new_host.port
|
15
|
+
server.with(properties)
|
16
|
+
else
|
17
|
+
servers << new_host.with(properties)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_role(role, hosts, options={})
|
22
|
+
options_deepcopy = Marshal.dump(options.merge(roles: role))
|
23
|
+
Array(hosts).each { |host| add_host(host, Marshal.load(options_deepcopy)) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def roles_for(names)
|
27
|
+
options = extract_options(names)
|
28
|
+
s = Filter.new(:role, names).filter(servers)
|
29
|
+
s.select { |server| server.select?(options) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def role_properties_for(rolenames)
|
33
|
+
roles = rolenames.to_set
|
34
|
+
rps = Set.new unless block_given?
|
35
|
+
roles_for(rolenames).each do |host|
|
36
|
+
host.roles.intersection(roles).each do |role|
|
37
|
+
[host.properties.fetch(role)].flatten(1).each do |props|
|
38
|
+
if block_given?
|
39
|
+
yield host, role, props
|
40
|
+
else
|
41
|
+
rps << (props || {}).merge( role: role, hostname: host.hostname )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
block_given? ? nil: rps
|
47
|
+
end
|
48
|
+
|
49
|
+
def fetch_primary(role)
|
50
|
+
hosts = roles_for([role])
|
51
|
+
hosts.find(&:primary) || hosts.first
|
52
|
+
end
|
53
|
+
|
54
|
+
def each
|
55
|
+
servers.each { |server| yield server }
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def servers
|
61
|
+
@servers ||= []
|
62
|
+
end
|
63
|
+
|
64
|
+
def extract_options(array)
|
65
|
+
array.last.is_a?(::Hash) ? array.pop : {}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/ferry/deploy.rb
ADDED
data/lib/ferry/dsl.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'etc'
|
2
|
+
require 'ferry/dsl/task_enhancements'
|
3
|
+
require 'ferry/dsl/paths'
|
4
|
+
require 'ferry/dsl/stages'
|
5
|
+
require 'ferry/dsl/env'
|
6
|
+
require 'ferry/configuration/filter'
|
7
|
+
|
8
|
+
module Ferry
|
9
|
+
module DSL
|
10
|
+
include TaskEnhancements
|
11
|
+
include Env
|
12
|
+
include Paths
|
13
|
+
include Stages
|
14
|
+
|
15
|
+
def invoke(task, *args)
|
16
|
+
Rake::Task[task].invoke(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def t(key, options={})
|
20
|
+
I18n.t(key, options.merge(scope: :ferry))
|
21
|
+
end
|
22
|
+
|
23
|
+
def scm
|
24
|
+
fetch(:scm)
|
25
|
+
end
|
26
|
+
|
27
|
+
def sudo(*args)
|
28
|
+
execute :sudo, *args
|
29
|
+
end
|
30
|
+
|
31
|
+
def revision_log_message
|
32
|
+
fetch(:revision_log_message,
|
33
|
+
t(:revision_log_message,
|
34
|
+
branch: fetch(:branch),
|
35
|
+
user: local_user,
|
36
|
+
sha: fetch(:current_revision),
|
37
|
+
release: fetch(:release_timestamp))
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def rollback_log_message
|
42
|
+
t(:rollback_log_message, user: local_user, release: fetch(:rollback_timestamp))
|
43
|
+
end
|
44
|
+
|
45
|
+
def local_user
|
46
|
+
fetch(:local_user)
|
47
|
+
end
|
48
|
+
|
49
|
+
def lock(locked_version)
|
50
|
+
VersionValidator.new(locked_version).verify
|
51
|
+
end
|
52
|
+
|
53
|
+
def on(hosts, options={}, &block)
|
54
|
+
subset_copy = Marshal.dump(Configuration.env.filter(hosts))
|
55
|
+
SSHKit::Coordinator.new(Marshal.load(subset_copy)).each(options, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_locally(&block)
|
59
|
+
SSHKit::Backend::Local.new(&block).run
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self.extend Ferry::DSL
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Ferry
|
2
|
+
module DSL
|
3
|
+
module Env
|
4
|
+
|
5
|
+
def configure_backend
|
6
|
+
env.configure_backend
|
7
|
+
end
|
8
|
+
|
9
|
+
def fetch(key, default=nil, &block)
|
10
|
+
env.fetch(key, default, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def any?(key)
|
14
|
+
value = fetch(key)
|
15
|
+
if value && value.respond_to?(:any?)
|
16
|
+
value.any?
|
17
|
+
else
|
18
|
+
!fetch(key).nil?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(key, value)
|
23
|
+
env.set(key, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_if_empty(key, value)
|
27
|
+
env.set_if_empty(key, value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(key)
|
31
|
+
env.delete(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ask(key, value, options={})
|
35
|
+
env.ask(key, value, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def role(name, servers, options={})
|
39
|
+
env.role(name, servers, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def server(name, properties={})
|
43
|
+
env.server(name, properties)
|
44
|
+
end
|
45
|
+
|
46
|
+
def roles(*names)
|
47
|
+
env.roles_for(names.flatten)
|
48
|
+
end
|
49
|
+
|
50
|
+
def role_properties(*names, &block)
|
51
|
+
env.role_properties_for(names, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def release_roles(*names)
|
55
|
+
if names.last.is_a? Hash
|
56
|
+
names.last.merge!({ :exclude => :no_release })
|
57
|
+
else
|
58
|
+
names << { exclude: :no_release }
|
59
|
+
end
|
60
|
+
roles(*names)
|
61
|
+
end
|
62
|
+
|
63
|
+
def primary(role)
|
64
|
+
env.primary(role)
|
65
|
+
end
|
66
|
+
|
67
|
+
def env
|
68
|
+
Configuration.env
|
69
|
+
end
|
70
|
+
|
71
|
+
def release_timestamp
|
72
|
+
env.timestamp.strftime("%Y%m%d%H%M%S")
|
73
|
+
end
|
74
|
+
|
75
|
+
def asset_timestamp
|
76
|
+
env.timestamp.strftime("%Y%m%d%H%M.%S")
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
module Ferry
|
3
|
+
module DSL
|
4
|
+
module Paths
|
5
|
+
|
6
|
+
def deploy_to
|
7
|
+
fetch(:deploy_to)
|
8
|
+
end
|
9
|
+
|
10
|
+
def deploy_path
|
11
|
+
Pathname.new(deploy_to)
|
12
|
+
end
|
13
|
+
|
14
|
+
def current_path
|
15
|
+
deploy_path.join('current')
|
16
|
+
end
|
17
|
+
|
18
|
+
def releases_path
|
19
|
+
deploy_path.join('releases')
|
20
|
+
end
|
21
|
+
|
22
|
+
def release_path
|
23
|
+
fetch(:release_path, current_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_release_path(timestamp=now)
|
27
|
+
set(:release_timestamp, timestamp)
|
28
|
+
set(:release_path, releases_path.join(timestamp))
|
29
|
+
end
|
30
|
+
|
31
|
+
def stage_config_path
|
32
|
+
Pathname.new fetch(:stage_config_path, 'config/deploy')
|
33
|
+
end
|
34
|
+
|
35
|
+
def deploy_config_path
|
36
|
+
Pathname.new fetch(:deploy_config_path, 'config/deploy.rb')
|
37
|
+
end
|
38
|
+
|
39
|
+
def repo_url
|
40
|
+
require 'cgi'
|
41
|
+
require 'uri'
|
42
|
+
if fetch(:git_http_username) and fetch(:git_http_password)
|
43
|
+
URI.parse(fetch(:repo_url)).tap do |repo_uri|
|
44
|
+
repo_uri.user = fetch(:git_http_username)
|
45
|
+
repo_uri.password = CGI.escape(fetch(:git_http_password))
|
46
|
+
end.to_s
|
47
|
+
elsif fetch(:git_http_username)
|
48
|
+
URI.parse(fetch(:repo_url)).tap do |repo_uri|
|
49
|
+
repo_uri.user = fetch(:git_http_username)
|
50
|
+
end.to_s
|
51
|
+
else
|
52
|
+
fetch(:repo_url)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def repo_path
|
57
|
+
Pathname.new(fetch(:repo_path, ->(){deploy_path.join('repo')}))
|
58
|
+
end
|
59
|
+
|
60
|
+
def shared_path
|
61
|
+
deploy_path.join('shared')
|
62
|
+
end
|
63
|
+
|
64
|
+
def revision_log
|
65
|
+
deploy_path.join('revisions.log')
|
66
|
+
end
|
67
|
+
|
68
|
+
def now
|
69
|
+
env.timestamp.strftime("%Y%m%d%H%M%S")
|
70
|
+
end
|
71
|
+
|
72
|
+
def asset_timestamp
|
73
|
+
env.timestamp.strftime("%Y%m%d%H%M.%S")
|
74
|
+
end
|
75
|
+
|
76
|
+
def linked_dirs(parent)
|
77
|
+
paths = fetch(:linked_dirs)
|
78
|
+
join_paths(parent, paths)
|
79
|
+
end
|
80
|
+
|
81
|
+
def linked_files(parent)
|
82
|
+
paths = fetch(:linked_files)
|
83
|
+
join_paths(parent, paths)
|
84
|
+
end
|
85
|
+
|
86
|
+
def linked_file_dirs(parent)
|
87
|
+
map_dirnames(linked_files(parent))
|
88
|
+
end
|
89
|
+
|
90
|
+
def linked_dir_parents(parent)
|
91
|
+
map_dirnames(linked_dirs(parent))
|
92
|
+
end
|
93
|
+
|
94
|
+
def join_paths(parent, paths)
|
95
|
+
paths.map { |path| parent.join(path) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def map_dirnames(paths)
|
99
|
+
paths.map { |path| path.dirname }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ferry
|
2
|
+
module DSL
|
3
|
+
module Stages
|
4
|
+
|
5
|
+
def stages
|
6
|
+
Dir[stage_definitions].map { |f| File.basename(f, '.rb') }
|
7
|
+
end
|
8
|
+
|
9
|
+
def stage_definitions
|
10
|
+
stage_config_path.join('*.rb')
|
11
|
+
end
|
12
|
+
|
13
|
+
def stage_set?
|
14
|
+
!!fetch(:stage, false)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'ferry/upload_task'
|
2
|
+
|
3
|
+
module Ferry
|
4
|
+
module TaskEnhancements
|
5
|
+
def before(task, prerequisite, *args, &block)
|
6
|
+
prerequisite = Rake::Task.define_task(prerequisite, *args, &block) if block_given?
|
7
|
+
Rake::Task[task].enhance [prerequisite]
|
8
|
+
end
|
9
|
+
|
10
|
+
def after(task, post_task, *args, &block)
|
11
|
+
Rake::Task.define_task(post_task, *args, &block) if block_given?
|
12
|
+
Rake::Task[task].enhance do
|
13
|
+
Rake::Task[post_task].invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def remote_file(task)
|
18
|
+
target_roles = task.delete(:roles) { :all }
|
19
|
+
define_remote_file_task(task, target_roles)
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_remote_file_task(task, target_roles)
|
23
|
+
Ferry::UploadTask.define_task(task) do |t|
|
24
|
+
prerequisite_file = t.prerequisites.first
|
25
|
+
file = shared_path.join(t.name)
|
26
|
+
|
27
|
+
on roles(target_roles) do
|
28
|
+
unless test "[ -f #{file.to_s.shellescape} ]"
|
29
|
+
info "Uploading #{prerequisite_file} to #{file}"
|
30
|
+
upload! File.open(prerequisite_file), file
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def ensure_stage
|
38
|
+
Rake::Task.define_task(:ensure_stage) do
|
39
|
+
unless stage_set?
|
40
|
+
puts t(:stage_not_set)
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def tasks_without_stage_dependency
|
47
|
+
stages + default_tasks
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_tasks
|
51
|
+
%w{install}
|
52
|
+
end
|
53
|
+
|
54
|
+
def exit_deploy_because_of_exception(ex)
|
55
|
+
warn t(:deploy_failed, ex: ex.message)
|
56
|
+
invoke 'deploy:failed'
|
57
|
+
exit(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
def deploying?
|
61
|
+
fetch(:deploying, false)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/lib/ferry/i18n.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
en = {
|
4
|
+
starting: 'Starting',
|
5
|
+
installing: 'Installing',
|
6
|
+
set_sail: 'Set Sail!',
|
7
|
+
moving: 'Moving',
|
8
|
+
completed: 'Completed'
|
9
|
+
},
|
10
|
+
error: 'Some error'
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
I18n.backend.store_translations(:en, { ferry: en })
|
15
|
+
|
16
|
+
if I18n.respond_to?(:enforce_available_locales=)
|
17
|
+
I18n.enforce_available_locales = true
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path(File.join(File.dirname(__FILE__),'tasks/install.rake'))
|