pike 0.0.1
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/.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
|