ferry 1.3.3 → 2.0.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 +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'))
|