pike 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +12 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +52 -0
- data/LICENSE +20 -0
- data/Pikefile.example +103 -0
- data/README.md +139 -0
- data/Rakefile +1 -0
- data/bin/pike +3 -0
- data/lib/pike/dsl/environment.rb +56 -0
- data/lib/pike/dsl/pikefile.rb +51 -0
- data/lib/pike/dsl/task.rb +101 -0
- data/lib/pike/env.rb +129 -0
- data/lib/pike/logger.rb +86 -0
- data/lib/pike/main.rb +275 -0
- data/lib/pike/rba/builder.rb +60 -0
- data/lib/pike/ssh/connection.rb +179 -0
- data/lib/pike/ssh/process.rb +34 -0
- data/lib/pike/ssh/runner.rb +115 -0
- data/lib/pike/tasks/command/local.rb +35 -0
- data/lib/pike/tasks/command/remote.rb +31 -0
- data/lib/pike/tasks/command.rb +150 -0
- data/lib/pike/tasks/task.rb +125 -0
- data/lib/pike/tasks/tasks.rb +168 -0
- data/lib/pike/version.rb +3 -0
- data/lib/pike.rb +56 -0
- data/pike.gemspec +33 -0
- data/script/build +7 -0
- data/spec/spec_helper.rb +6 -0
- metadata +160 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module Pike
|
2
|
+
module SSH
|
3
|
+
class Process
|
4
|
+
attr_accessor :stdout
|
5
|
+
attr_accessor :stderr
|
6
|
+
attr_accessor :exit_code
|
7
|
+
attr_accessor :command
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(command)
|
11
|
+
@stdout = ''
|
12
|
+
@stderr = ''
|
13
|
+
@exit_code = 0
|
14
|
+
@command = command
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_exit_status(channel, data)
|
18
|
+
@exit_code = data.read_long
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_stderr(channel, type, data)
|
22
|
+
@stderr << data
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_stdout(channel, data)
|
26
|
+
@stdout << data
|
27
|
+
end
|
28
|
+
|
29
|
+
def success?
|
30
|
+
exit_code == 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'pike/ssh/process'
|
2
|
+
|
3
|
+
module Pike
|
4
|
+
module SSH
|
5
|
+
class Runner
|
6
|
+
SUDO_PATTERN = /\[sudo\] password for .+:\s*$/
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
## Constructor
|
11
|
+
##
|
12
|
+
|
13
|
+
def initialize(connection, cmd)
|
14
|
+
@cmd = cmd
|
15
|
+
@process = SSH::Process.new(@cmd)
|
16
|
+
@connection = connection
|
17
|
+
@state = :init
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
##
|
22
|
+
## Executes the process of the current Runner instance
|
23
|
+
##
|
24
|
+
|
25
|
+
def run!
|
26
|
+
@connection.open_channel &method(:run)
|
27
|
+
@connection.wait!
|
28
|
+
|
29
|
+
return @process
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
##
|
34
|
+
## Simple method to run commands on a connection
|
35
|
+
##
|
36
|
+
|
37
|
+
def self.run(connection, cmd)
|
38
|
+
ins = self.new connection, cmd
|
39
|
+
ins.run!
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
##
|
47
|
+
## Get's called if a channel is opened and executes the command
|
48
|
+
##
|
49
|
+
|
50
|
+
def run(channel)
|
51
|
+
channel.request_pty
|
52
|
+
|
53
|
+
channel.exec("cd #{@connection.cwd} && (#{@cmd})") do |ch, success|
|
54
|
+
Main.error("Could not run command #{@cmd}") unless success
|
55
|
+
|
56
|
+
channel.on_request("exit-status", &@process.method(:on_exit_status))
|
57
|
+
channel.on_extended_data(&@process.method(:on_stderr))
|
58
|
+
channel.on_data(&method(:on_data))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
##
|
64
|
+
## Wrapper method to catch sudo password prompt and handle it
|
65
|
+
##
|
66
|
+
|
67
|
+
def on_data(channel, data)
|
68
|
+
handle_sudo_response(channel, data) if @state == :try_sudo
|
69
|
+
|
70
|
+
if data =~ SUDO_PATTERN
|
71
|
+
handle_sudo(channel, data)
|
72
|
+
else
|
73
|
+
@state = :sudo_successful
|
74
|
+
@process.on_stdout(channel, data)
|
75
|
+
channel.on_data(&@process.method(:on_stdout))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
##
|
81
|
+
## Handles the response of the sudo command
|
82
|
+
##
|
83
|
+
|
84
|
+
def handle_sudo_response(channel, data)
|
85
|
+
if data == 'ok'
|
86
|
+
@state = :sudo_successful
|
87
|
+
elsif data =~ /^\s+$/
|
88
|
+
@connection.wait!
|
89
|
+
elsif data =~ /incorrect password attempts\s*$/
|
90
|
+
Main.error("Too much incorrect password attempts")
|
91
|
+
elsif data =~ SUDO_PATTERN
|
92
|
+
# Wrong sudo password
|
93
|
+
@connection.sudo_password = nil
|
94
|
+
handle_sudo(channel, data)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
##
|
100
|
+
## Handles a sudo password prompt by sending the password
|
101
|
+
##
|
102
|
+
|
103
|
+
def handle_sudo(channel, data, wrong = false)
|
104
|
+
@state = :try_sudo
|
105
|
+
|
106
|
+
unless @connection.sudo_password
|
107
|
+
text = wrong ? "Wrong password. Please try again:" : "Please enter sudo password:"
|
108
|
+
@connection.sudo_password = retrieve(text) { |q| q.echo = false }
|
109
|
+
end
|
110
|
+
|
111
|
+
channel.send_data "#{@connection.sudo_password}\n"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Pike
|
2
|
+
module Tasks
|
3
|
+
class Command
|
4
|
+
class Local
|
5
|
+
def initialize(task)
|
6
|
+
@task = task
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(cmd)
|
10
|
+
re = `#{cmd} 2>&1`
|
11
|
+
|
12
|
+
Logger.log re
|
13
|
+
|
14
|
+
if $? != 0
|
15
|
+
Main.error(re)
|
16
|
+
end
|
17
|
+
|
18
|
+
re
|
19
|
+
end
|
20
|
+
|
21
|
+
def cd(new_cwd)
|
22
|
+
begin
|
23
|
+
return Dir.chdir new_cwd
|
24
|
+
rescue Exception => e
|
25
|
+
Main.error(e)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def bundler(cmd, var_string, do_not_use)
|
30
|
+
run("#{var_string} bundle #{cmd}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pike
|
2
|
+
module Tasks
|
3
|
+
class Command
|
4
|
+
class Remote
|
5
|
+
def initialize(task)
|
6
|
+
@task = task
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(cmd)
|
10
|
+
prc = Pike::SSH::Connection.run(cmd)
|
11
|
+
|
12
|
+
if prc.success?
|
13
|
+
Logger.log prc.stdout
|
14
|
+
Logger.log prc.stderr
|
15
|
+
return prc.stdout + prc.stderr
|
16
|
+
else
|
17
|
+
Main.error("Error while executing #{cmd}: " + prc.stdout + prc.stderr)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def cd(new_cwd)
|
22
|
+
return Pike::SSH::Connection.cd(new_cwd)
|
23
|
+
end
|
24
|
+
|
25
|
+
def bundler(cmd, var_string, sudo = false)
|
26
|
+
run("#{@task.current_env.bundler_prefix} #{sudo ? 'sudo ' : ''} #{var_string} bundle #{cmd}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'pike/tasks/command/local'
|
2
|
+
require 'pike/tasks/command/remote'
|
3
|
+
|
4
|
+
module Pike
|
5
|
+
module Tasks
|
6
|
+
class Command
|
7
|
+
attr_reader \
|
8
|
+
:where, # :local || :remote - Determines on which machine to run the command
|
9
|
+
:cmd, # The command string
|
10
|
+
:mode # :cd, :cmd, :bundler, :scp, :build_rba # TODO move those? polymorphism?
|
11
|
+
:vars # Hash of vars
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
## Constructor
|
16
|
+
##
|
17
|
+
|
18
|
+
def initialize(task, where, cmd, vars = {})
|
19
|
+
@task = task
|
20
|
+
@where = where
|
21
|
+
@vars = vars
|
22
|
+
|
23
|
+
case cmd.split(' ').first
|
24
|
+
when 'cd'
|
25
|
+
@mode = :cd
|
26
|
+
@cd_to = cmd.gsub('cd ', '')
|
27
|
+
|
28
|
+
when 'bundle'
|
29
|
+
@mode = :bundler
|
30
|
+
@cmd = cmd.gsub('bundle ', '')
|
31
|
+
|
32
|
+
when '!BUILD_RBA'
|
33
|
+
@mode = :build_rba
|
34
|
+
@cmd = nil
|
35
|
+
|
36
|
+
when '!SCP'
|
37
|
+
@mode = :scp
|
38
|
+
|
39
|
+
splitted = cmd.gsub('!SCP ', '').split(' ')
|
40
|
+
@local = splitted[0]
|
41
|
+
@remote = splitted[1]
|
42
|
+
|
43
|
+
else
|
44
|
+
@mode = :cmd
|
45
|
+
@cmd = cmd
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
##
|
51
|
+
## The cmd prefix for the log. Looks like a bash prompt
|
52
|
+
##
|
53
|
+
|
54
|
+
def get_cmd_prefix
|
55
|
+
"\n" + (where == :local ? Dir.pwd : SSH::Connection.cwd) + " (#{where})$ #{to_s}"
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
##
|
60
|
+
## Runs the command
|
61
|
+
##
|
62
|
+
|
63
|
+
def run(env)
|
64
|
+
# Log command
|
65
|
+
Logger.log get_cmd_prefix
|
66
|
+
report("#{where == :remote ? '>' : '<'} #{to_s}") if Main.verbose
|
67
|
+
|
68
|
+
# Determine target environment
|
69
|
+
target = (where == :local ? Local.new(@task) : Remote.new(@task))
|
70
|
+
|
71
|
+
unless Main.dry_run
|
72
|
+
# Mode depending routines
|
73
|
+
case @mode
|
74
|
+
when :cmd
|
75
|
+
return target.run("#{var_string} #{sudo}#{@cmd}")
|
76
|
+
|
77
|
+
when :cd
|
78
|
+
return target.cd(@cd_to)
|
79
|
+
|
80
|
+
when :bundler
|
81
|
+
return target.bundler(@cmd, var_string, sudo?)
|
82
|
+
|
83
|
+
when :build_rba
|
84
|
+
return build_rba
|
85
|
+
|
86
|
+
when :scp
|
87
|
+
SSH::Connection.scp(@local, @remote, env.get_var(:host))
|
88
|
+
|
89
|
+
else
|
90
|
+
Main.error("Unkown command mode #{@mode}")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
##
|
97
|
+
## Generates the vars for the shell command
|
98
|
+
##
|
99
|
+
|
100
|
+
def var_string
|
101
|
+
re = ''
|
102
|
+
@vars.each do |key, value|
|
103
|
+
re << "#{key.to_s.upcase.strip}=#{value} "
|
104
|
+
end
|
105
|
+
re
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
##
|
110
|
+
## Starts the build process for .rba file
|
111
|
+
##
|
112
|
+
|
113
|
+
def build_rba
|
114
|
+
target_file = '../' + Main.get_var(:name) + '.rba'
|
115
|
+
Logger.log "Building RBA file: #{target_file} ..."
|
116
|
+
RBA::Builder.build(target_file)
|
117
|
+
target_file
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
##
|
122
|
+
## Converts command to string. Depending on the mode, the result may differ
|
123
|
+
##
|
124
|
+
|
125
|
+
def to_s
|
126
|
+
case @mode
|
127
|
+
when :cmd
|
128
|
+
"#{sudo}#{var_string}#{@cmd}"
|
129
|
+
when :bundler
|
130
|
+
"#{sudo}#{var_string}bundle #{@cmd}"
|
131
|
+
when :cd
|
132
|
+
"cd #{@cd_to}"
|
133
|
+
when :scp
|
134
|
+
"scp #{@local} #{@remote}"
|
135
|
+
when :build_rba
|
136
|
+
"build .rba file"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def sudo
|
142
|
+
sudo? ? 'sudo ' : ''
|
143
|
+
end
|
144
|
+
|
145
|
+
def sudo?
|
146
|
+
where == :remote && @task.current_env.get_var(:use_sudo) && !@cmd.strip.start_with?('source ')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Pike
|
2
|
+
class Task
|
3
|
+
attr_accessor :current_env
|
4
|
+
|
5
|
+
##
|
6
|
+
## Constructor
|
7
|
+
##
|
8
|
+
|
9
|
+
def initialize(name, &block)
|
10
|
+
@block = block
|
11
|
+
@current_env = nil
|
12
|
+
@current_params = {}
|
13
|
+
@name = name
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
## Call run that task
|
19
|
+
##
|
20
|
+
|
21
|
+
def run(env, params)
|
22
|
+
log_header
|
23
|
+
|
24
|
+
# Setting @current_params and @current_env
|
25
|
+
set_current_params params
|
26
|
+
@current_env = env
|
27
|
+
|
28
|
+
# Parse the task block
|
29
|
+
DSL::Task.load(self, &@block)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
##
|
34
|
+
## Called from the DSL to run another task
|
35
|
+
##
|
36
|
+
|
37
|
+
def run_task(task)
|
38
|
+
@current_env.run_task(task)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
## Called from the DSL to get the value of a varaible
|
44
|
+
##
|
45
|
+
|
46
|
+
def get_var(key, default = nil)
|
47
|
+
return @current_env.get_var(key) if var_given?(key)
|
48
|
+
return default if default
|
49
|
+
undef_error(:variable, key)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
##
|
55
|
+
## Called from the DSL to get the value of a param
|
56
|
+
##
|
57
|
+
|
58
|
+
|
59
|
+
def get_param(key, default = nil)
|
60
|
+
return @current_params[key] if param_given?(key)
|
61
|
+
return default if default
|
62
|
+
undef_error(:param, key)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
##
|
67
|
+
## Checks if a param with the given key is defined
|
68
|
+
##
|
69
|
+
|
70
|
+
def param_given?(key)
|
71
|
+
@current_params.include?(key)
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
##
|
76
|
+
## Checks if a variable with the given key is defined
|
77
|
+
##
|
78
|
+
|
79
|
+
def var_given?(key)
|
80
|
+
(@current_env.get_var(key) != nil)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
|
88
|
+
##
|
89
|
+
## Log header for that task
|
90
|
+
##
|
91
|
+
|
92
|
+
def log_header
|
93
|
+
Logger.log
|
94
|
+
Logger.log
|
95
|
+
Logger.log " Run Task: #{@name}"
|
96
|
+
Logger.log "==============" + @name.length.times.collect { '=' }.join
|
97
|
+
Logger.log
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
##
|
102
|
+
## Iterates over all params, adds them to @current_params and logs them
|
103
|
+
##
|
104
|
+
|
105
|
+
def set_current_params(params)
|
106
|
+
@current_params = params
|
107
|
+
|
108
|
+
@current_params.keys.each do |key|
|
109
|
+
Logger.log "Option '#{key}': #{@current_params[key]}"
|
110
|
+
end
|
111
|
+
|
112
|
+
Logger.log
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
##
|
118
|
+
## Throw error if param or variable is not defined
|
119
|
+
##
|
120
|
+
|
121
|
+
def undef_error(type, key)
|
122
|
+
Main.error("Require the #{type} #{key} for the task #{@name} but it's not defined.")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# TODO the order of the tasks may vary. So make sure every tasks cds in his required directory
|
2
|
+
|
3
|
+
task :clone do
|
4
|
+
local "rm -rf #{get :build_dir}"
|
5
|
+
|
6
|
+
branch = param(:branch, 'master')
|
7
|
+
depth = param(:depth, 1)
|
8
|
+
|
9
|
+
local "git clone --depth=#{depth} -b #{branch} #{param :repository} #{get :build_dir}"
|
10
|
+
local "cd #{get :build_dir}"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :submodules do
|
14
|
+
local "cd #{get :build_dir}"
|
15
|
+
local "git submodule update --init"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :reduce do
|
19
|
+
local "cd #{get :build_dir}"
|
20
|
+
local 'rm -rf ' + param(:clean).join(' ')
|
21
|
+
end
|
22
|
+
|
23
|
+
task :bundle do
|
24
|
+
local "cd #{get :build_dir}"
|
25
|
+
without = param_given?(:without) ? '--without ' + param(:without).join(' ') : ''
|
26
|
+
local "bundle install #{without}"
|
27
|
+
end
|
28
|
+
|
29
|
+
task :rspec do
|
30
|
+
local "cd #{get :build_dir}"
|
31
|
+
local "bundle exec rspec"
|
32
|
+
end
|
33
|
+
|
34
|
+
task :assets do
|
35
|
+
local "cd #{get :build_dir}"
|
36
|
+
vars = { RAILS_ENV: param(:rails_env, 'development') }
|
37
|
+
vars[:RAILS_GROUPS] = param(:rails_group) if param_given?(:rails_group)
|
38
|
+
|
39
|
+
local "bundle exec rake assets:precompile", vars
|
40
|
+
end
|
41
|
+
|
42
|
+
task :build do
|
43
|
+
local "cd #{get :build_dir}"
|
44
|
+
local build_rba
|
45
|
+
local "cd #{get :root_dir}"
|
46
|
+
|
47
|
+
unless param_given?(:keep_build_dir) && param(:keep_build_dir) == true
|
48
|
+
local "rm -rf #{get :build_dir}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Directory sturcture:
|
54
|
+
# - /opt/jarvis
|
55
|
+
# - config/
|
56
|
+
# - config.yml
|
57
|
+
# - db/
|
58
|
+
# - jarvis.sqlite3
|
59
|
+
# - config.ru
|
60
|
+
# - .pike
|
61
|
+
# - releases/
|
62
|
+
# - 123/
|
63
|
+
# - app
|
64
|
+
# - config/
|
65
|
+
# - (s) config.yml -> ../../../../config/config.yml
|
66
|
+
# - db/
|
67
|
+
# - (s) jarvis.sqlite3 -> ../../../../db/jarvis.sqlite3
|
68
|
+
# - (s) current -> releases/123
|
69
|
+
# - (s) assets -> current/public/assets
|
70
|
+
# - (s) index.html -> current/public/index.html
|
71
|
+
|
72
|
+
task :deploy do
|
73
|
+
name = get(:name)
|
74
|
+
deploy_to = get(:deploy_to)
|
75
|
+
target_dir = get(:release_path)
|
76
|
+
|
77
|
+
local "cd #{get :root_dir}"
|
78
|
+
|
79
|
+
# Copy the rba file to the server in the /tmp directory
|
80
|
+
upload "#{name}.rba", "/tmp/#{name}.rba"
|
81
|
+
|
82
|
+
# Create dir /path/to/deploy/.rba/releases/timestamp/
|
83
|
+
remote "mkdir -pv #{target_dir}"
|
84
|
+
|
85
|
+
# Move the .rba file to the release directory
|
86
|
+
remote "mv -vf /tmp/#{name}.rba #{target_dir}"
|
87
|
+
|
88
|
+
# CD into the release directory
|
89
|
+
remote "cd #{target_dir}"
|
90
|
+
|
91
|
+
# Extract the rba file
|
92
|
+
remote "tar -xzvf #{name}.rba"
|
93
|
+
|
94
|
+
# Remove the rba file
|
95
|
+
remote "rm -vf #{name}.rba"
|
96
|
+
|
97
|
+
# Make sure tmp/pids exists
|
98
|
+
remote "mkdir -pv tmp/pids"
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
task :symlink_shared do
|
103
|
+
remote "cd #{get :deploy_to}"
|
104
|
+
|
105
|
+
param(:files).each do |file|
|
106
|
+
remote "ln -nfvs #{get :deploy_to}#{file} #{get :release_path}#{file}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
task :symlinks do
|
111
|
+
remote "cd #{get :deploy_to}"
|
112
|
+
|
113
|
+
# Current release link
|
114
|
+
remote "ln -nfvs #{get :release_path} #{get :deploy_to}.pike/current"
|
115
|
+
|
116
|
+
# public/ files
|
117
|
+
files = remote "ls -lAh #{get :release_path}public | awk -F ' ' '{print $9}'"
|
118
|
+
|
119
|
+
files.split("\n").each do |file|
|
120
|
+
file.strip!
|
121
|
+
if file != ''
|
122
|
+
remote "ln -nfvs #{get :deploy_to}.pike/current/public/#{file} #{get :deploy_to}.pike/#{file}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
task :bundle_deployment do
|
128
|
+
remote "cd #{get :release_path}"
|
129
|
+
without = param_given?(:without) ? '--without ' + param(:without).join(' ') : ''
|
130
|
+
no_cache = param_given?(:no_cache) && param(:no_cache) == true ? '--no-cache' : ''
|
131
|
+
remote "bundle install --deployment #{without} #{no_cache}"
|
132
|
+
end
|
133
|
+
|
134
|
+
task :migrate do
|
135
|
+
remote "cd #{get :release_path}"
|
136
|
+
remote "bundle exec rake db:migrate", RAILS_ENV: get(:rails_env)
|
137
|
+
end
|
138
|
+
|
139
|
+
task :cleanup do
|
140
|
+
remote "cd #{get :release_path}"
|
141
|
+
|
142
|
+
releases = remote "ls -lAh #{get :deploy_to}.pike/releases/ | awk -F ' ' '{print $9}'"
|
143
|
+
releases = releases.split("\n").find_all { |r| r.strip =~ /^\d+$/ }.map { |r| r.strip }
|
144
|
+
|
145
|
+
i = 0
|
146
|
+
delete = releases.length - param(:keep_releases).to_i
|
147
|
+
|
148
|
+
releases.each do |release|
|
149
|
+
i += 1
|
150
|
+
remote "rm -rf #{get :deploy_to}.pike/releases/#{release}" if i < delete
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
task :chown do
|
155
|
+
remote "chown -R #{param :user}:#{param :group} #{get :deploy_to}"
|
156
|
+
end
|
157
|
+
|
158
|
+
task :restart do
|
159
|
+
if param(:server) == :passenger
|
160
|
+
remote "touch #{get :release_path}tmp/restart.txt"
|
161
|
+
else
|
162
|
+
raise "Unsupported server type #{param :server}. Feel free to contribute and add support for that server! :)"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
task :setup do
|
167
|
+
remote "mkdir -p #{get :deploy_to}/.pike/releases"
|
168
|
+
end
|
data/lib/pike/version.rb
ADDED
data/lib/pike.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'optparse'
|
3
|
+
require 'steps'
|
4
|
+
require 'pike/main'
|
5
|
+
|
6
|
+
|
7
|
+
# Command line options
|
8
|
+
options = {
|
9
|
+
debug: false,
|
10
|
+
dry_run: false,
|
11
|
+
verbose: false
|
12
|
+
}
|
13
|
+
|
14
|
+
opt_parser = OptionParser.new do |opt|
|
15
|
+
opt.banner = 'Usage: pike [OPTIONS] [ENVIRONMENT] [TASK]'
|
16
|
+
opt.separator ''
|
17
|
+
opt.separator 'Options'
|
18
|
+
|
19
|
+
opt.on('-d', '--debug', 'Enable stacktrace output.') do
|
20
|
+
options[:debug] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
opt.on('-v', '--verbose', 'Enable verbosity: Executed command will be display.') do
|
24
|
+
options[:verbose] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
opt.on('-s', '--simulate', 'Dry run: Simulate and don\'t really execute the commands.') do
|
28
|
+
options[:dry_run] = true
|
29
|
+
end
|
30
|
+
|
31
|
+
opt.on('-h', '--help', 'Displays help text') do
|
32
|
+
puts opt_parser
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
opt.on('-V', '--version', 'Displays version') do
|
37
|
+
puts Pike::VERSION.to_s
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
opt_parser.parse!
|
43
|
+
|
44
|
+
|
45
|
+
# Check for environment and set default
|
46
|
+
unless ARGV[0]
|
47
|
+
ARGV.push('production')
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Initialize pike
|
52
|
+
Pike::Main.init options
|
53
|
+
|
54
|
+
|
55
|
+
# Start the magic!
|
56
|
+
Pike::Main.run
|