deployman 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/deployman +20 -0
- data/lib/deployman.rb +4 -0
- data/lib/deployman/app.rb +40 -0
- data/lib/deployman/app/configuration.rb +27 -0
- data/lib/deployman/app/install.rb +128 -0
- data/lib/deployman/app/optionparser.rb +88 -0
- data/lib/deployman/app/postsetup.rb +92 -0
- data/lib/deployman/component.rb +3 -0
- data/lib/deployman/component/downloader.rb +100 -0
- data/lib/deployman/component/output.rb +53 -0
- data/lib/deployman/component/spinningclock.rb +33 -0
- data/lib/deployman/extractor.rb +3 -0
- data/lib/deployman/extractor/zip.rb +56 -0
- data/lib/deployman/net.rb +3 -0
- data/lib/deployman/net/post.rb +28 -0
- metadata +93 -0
data/bin/deployman
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# ruby -Ilib bin/deployman -i repoOwner,repoName,v3.0.0,https://api.github.com/repos/repoOwner/repoName/zipball/v3.0.0,/sandbox/liveserver/customerName/software/repoOwner/repoName/releases/v3.0.0 --auth github_user,password --config customer,customerName
|
4
|
+
|
5
|
+
require 'deployman'
|
6
|
+
require 'deployman/app'
|
7
|
+
require 'deployman/app/install'
|
8
|
+
require 'deployman/app/optionparser'
|
9
|
+
require 'deployman/app/configuration'
|
10
|
+
require 'deployman/app/postsetup'
|
11
|
+
require 'deployman/component'
|
12
|
+
require 'deployman/component/downloader'
|
13
|
+
require 'deployman/component/spinningclock'
|
14
|
+
require 'deployman/component/output'
|
15
|
+
require 'deployman/net'
|
16
|
+
require 'deployman/net/post'
|
17
|
+
require 'deployman/extractor'
|
18
|
+
require 'deployman/extractor/zip'
|
19
|
+
|
20
|
+
Deployman::App.run
|
data/lib/deployman.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Deployman::App
|
2
|
+
|
3
|
+
def self.run (args = nil)
|
4
|
+
args ||= ARGV.dup.map! { |v| v.dup }
|
5
|
+
|
6
|
+
# parse all options of command-line
|
7
|
+
options = Deployman::App::Optionparser.parse args
|
8
|
+
|
9
|
+
if options[:callback]
|
10
|
+
|
11
|
+
# redirect output (stdout, stderr) to tempfiles
|
12
|
+
Deployman::Component::Output.redirect_output
|
13
|
+
|
14
|
+
# deactivate spinningclock for clear output
|
15
|
+
Deployman::Component::Spinningclock.set_active false
|
16
|
+
|
17
|
+
begin
|
18
|
+
# call <Application> (e.g. http://localhost:8000/callback/install)
|
19
|
+
Deployman::Net::Post.send options[:callback], { "status" => "running", "stdout" => nil, "stderr" => nil }
|
20
|
+
# run deploy with parsed options
|
21
|
+
Deployman::App::Install.run options
|
22
|
+
# call <Application>
|
23
|
+
Deployman::Net::Post.send options[:callback], { "status" => "finished", "stdout" => Deployman::Component::Output.get_stdout, "stderr" => Deployman::Component::Output.get_stderr }
|
24
|
+
rescue Exception => e
|
25
|
+
warn "ERROR: #{e.message}"
|
26
|
+
# call <Application>
|
27
|
+
Deployman::Net::Post.send options[:callback], { "status" => "error", "stdout" => Deployman::Component::Output.get_stdout, "stderr" => Deployman::Component::Output.get_stderr }
|
28
|
+
end
|
29
|
+
|
30
|
+
else
|
31
|
+
begin
|
32
|
+
# run deploy with parsed options
|
33
|
+
Deployman::App::Install.run options
|
34
|
+
rescue Exception => e
|
35
|
+
warn "ERROR: #{e.message}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Deployman::App::Configuration
|
4
|
+
|
5
|
+
# create
|
6
|
+
# path = "/sandbox/liveserver/customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
7
|
+
def self.create(path, values)
|
8
|
+
# if exists, file will be overwritten
|
9
|
+
File.open(path + '/deployman.yml', 'wb') do |file|
|
10
|
+
file.write(values.to_yaml)
|
11
|
+
file.close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# delete
|
16
|
+
def self.delete(path)
|
17
|
+
File.delete(path + '/deployman.yml')
|
18
|
+
end
|
19
|
+
|
20
|
+
# get
|
21
|
+
def self.get(path)
|
22
|
+
config = YAML::load_file(path + '/deployman.yml')
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Deployman::App::Install
|
5
|
+
|
6
|
+
DL_DIR = "/tmp/"
|
7
|
+
@@options = {}
|
8
|
+
|
9
|
+
def self.run (options)
|
10
|
+
|
11
|
+
@@options = options
|
12
|
+
|
13
|
+
if options[:install]
|
14
|
+
puts "> Installation started!"
|
15
|
+
install(options[:install][0],options[:install][1],options[:install][2],options[:install][3],options[:install][4],options[:auth])
|
16
|
+
puts "> Installation finished!"
|
17
|
+
elsif options[:uninstall]
|
18
|
+
puts "> Uninstall started!"
|
19
|
+
uninstall(options[:uninstall])
|
20
|
+
puts "> Uninstall finished!"
|
21
|
+
else
|
22
|
+
puts "Unknown command. Type --help for more information!", true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# INSTALL
|
28
|
+
# owner = "repoOwner"
|
29
|
+
# software = "repoName"
|
30
|
+
# release = "v2.2.0"
|
31
|
+
# zip_url = "https://api.github.com/repos/repoOnwer/repoName/zipball/v2.2.0"
|
32
|
+
# dest = "/sandbox/liveserver/customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
33
|
+
#
|
34
|
+
def self.install (owner, software, release, zip_url, dest, auth = false)
|
35
|
+
|
36
|
+
# check if release already installed
|
37
|
+
if !File.directory?(dest)
|
38
|
+
|
39
|
+
zip_path = DL_DIR << owner << "-" << software << "-" << release << ".zip"
|
40
|
+
|
41
|
+
begin
|
42
|
+
|
43
|
+
# download zip file
|
44
|
+
print "> Downloading..."
|
45
|
+
Deployman::Component::Downloader.download_file(zip_url, zip_path, auth)
|
46
|
+
puts "done!"
|
47
|
+
|
48
|
+
# unzip zip file
|
49
|
+
print "> Unzipping..."
|
50
|
+
Deployman::Extractor::Zip.extract_file(zip_path, dest)
|
51
|
+
puts "done!"
|
52
|
+
|
53
|
+
# create configuration file
|
54
|
+
print "> Creating Configfile..."
|
55
|
+
create_configfile(owner, software, release, zip_url, dest)
|
56
|
+
puts "done!"
|
57
|
+
|
58
|
+
# run deploy.rb
|
59
|
+
print "> Deploying..."
|
60
|
+
deployrb(dest)
|
61
|
+
puts "done!"
|
62
|
+
|
63
|
+
# create postsetup.json file
|
64
|
+
print "> Creating Postsetupfile..."
|
65
|
+
Deployman::App::Postsetup.createPostsetupFile dest
|
66
|
+
puts "done!"
|
67
|
+
|
68
|
+
rescue Exception => e
|
69
|
+
warn "ERROR: #{e.message}"
|
70
|
+
raise "Installation failed!"
|
71
|
+
end
|
72
|
+
|
73
|
+
else
|
74
|
+
puts "> Release already installed!"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# UNINSTALL
|
79
|
+
# release_path = "/sandbox/liveserver/customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
80
|
+
#
|
81
|
+
def self.uninstall (release_path)
|
82
|
+
FileUtils.rm_rf(release_path)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.create_configfile (owner, software, release, zip_url, dest)
|
86
|
+
begin
|
87
|
+
config = {
|
88
|
+
"owner" => owner,
|
89
|
+
"software" => software,
|
90
|
+
"version" => release,
|
91
|
+
"installed_at" => DateTime.now.strftime("%b %d, %Y %H:%M"),
|
92
|
+
"zip_url" => zip_url,
|
93
|
+
"dest" => dest
|
94
|
+
}
|
95
|
+
config.merge! @@options[:config]
|
96
|
+
Deployman::App::Configuration.create(dest, config)
|
97
|
+
rescue Exception => e
|
98
|
+
warn "ERROR: #{e.message}"
|
99
|
+
raise "Creating Configfile failed!"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# RUN_DEPLOYRB
|
104
|
+
# dest = "/sandbox/liveserver/customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
105
|
+
#
|
106
|
+
def self.deployrb (dest)
|
107
|
+
begin
|
108
|
+
deployrb_path = dest + "/deploy.rb"
|
109
|
+
|
110
|
+
if File.exist?(deployrb_path)
|
111
|
+
# execute deploy.rb
|
112
|
+
Deployman::Component::Spinningclock.show_clock {
|
113
|
+
# get config
|
114
|
+
$config = Deployman::App::Configuration.get(dest)
|
115
|
+
# change to release dir
|
116
|
+
Dir.chdir dest
|
117
|
+
# run deploy.rb
|
118
|
+
load deployrb_path
|
119
|
+
}
|
120
|
+
else
|
121
|
+
print "(no deploy.rb file)..."
|
122
|
+
end
|
123
|
+
rescue Exception => e
|
124
|
+
warn "ERROR: #{e.message}"
|
125
|
+
raise "Deploying failed!"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'optparse' # OptionParser
|
2
|
+
|
3
|
+
module Deployman::App::Optionparser
|
4
|
+
|
5
|
+
def self.parse (args)
|
6
|
+
|
7
|
+
# This hash will hold all of the options parsed from the command-line by OptionParser.
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
optparse = OptionParser.new do |opts|
|
11
|
+
|
12
|
+
# Set a banner, displayed at the top of the help screen.
|
13
|
+
opts.banner = "Usage: deployman [option1] param1,param2 [optionN] paramN ...\r\n\r\n"
|
14
|
+
|
15
|
+
# install
|
16
|
+
options[:install] = false
|
17
|
+
opts.on('--install OWNER,SOFTWARE,RELEASE,ZIP_URL,DEST', Array, "Install" ) do |setting|
|
18
|
+
argumentLength = 5
|
19
|
+
raise OptionParser::MissingArgument if setting.length < argumentLength
|
20
|
+
raise OptionParser::NeedlessArgument if setting.length > argumentLength
|
21
|
+
options[:install] = setting
|
22
|
+
end
|
23
|
+
|
24
|
+
# uninstall
|
25
|
+
options[:uninstall] = false
|
26
|
+
opts.on('--uninstall PATH', "Uninstall") do |setting|
|
27
|
+
options[:uninstall] = setting
|
28
|
+
end
|
29
|
+
|
30
|
+
# auth
|
31
|
+
options[:auth] = false
|
32
|
+
opts.on('--auth USER,PASS', Array, "HTTP Authentication for Github API (works only in combination with --install)") do |setting|
|
33
|
+
argumentLength = 2
|
34
|
+
raise OptionParser::MissingArgument if setting.length < argumentLength
|
35
|
+
raise OptionParser::NeedlessArgument if setting.length > argumentLength
|
36
|
+
options[:auth] = setting
|
37
|
+
end
|
38
|
+
|
39
|
+
# config
|
40
|
+
options[:config] = {}
|
41
|
+
opts.on('--config VALUES', Array, "add custom config values (works only in combination with --install)") do |setting|
|
42
|
+
raise OptionParser::MissingArgument if setting.length % 2 != 0
|
43
|
+
# create key-value pairs from setting
|
44
|
+
config = {}
|
45
|
+
setting.each_slice(2) do |key, value|
|
46
|
+
config.store(key, value)
|
47
|
+
end
|
48
|
+
options[:config] = config
|
49
|
+
end
|
50
|
+
|
51
|
+
# callback
|
52
|
+
options[:callback] = false
|
53
|
+
opts.on('--callback URL', "callbacks status of installation (running/finished/error), stdout, stderr - as json object") do |setting|
|
54
|
+
options[:callback] = setting
|
55
|
+
end
|
56
|
+
|
57
|
+
# help
|
58
|
+
opts.on( '-h', '--help', 'Display help screen' ) do
|
59
|
+
puts opts
|
60
|
+
puts "\r\n"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
# Parse the command-line. Remember there are two forms
|
67
|
+
# of the parse method. The 'parse' method simply parses
|
68
|
+
# ARGV, while the 'parse!' method parses ARGV and removes
|
69
|
+
# any options found there, as well as any parameters for
|
70
|
+
# the options. What's left is the list of files to resize.
|
71
|
+
begin
|
72
|
+
optparse.parse! args
|
73
|
+
# return the parsed options
|
74
|
+
return options
|
75
|
+
rescue OptionParser::InvalidOption => e
|
76
|
+
warn "Error! #{e}"
|
77
|
+
exit
|
78
|
+
rescue OptionParser::MissingArgument => e
|
79
|
+
warn "Error! #{e}"
|
80
|
+
exit
|
81
|
+
rescue OptionParser::NeedlessArgument => e
|
82
|
+
warn "Error! #{e}"
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
module Deployman::App::Postsetup
|
5
|
+
|
6
|
+
@@tasks = []
|
7
|
+
|
8
|
+
# task class
|
9
|
+
#
|
10
|
+
class Task
|
11
|
+
attr_accessor :title, :desc, :commands
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@title = ""
|
15
|
+
@desc = ""
|
16
|
+
@commands = []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# add new task to tasks
|
21
|
+
#
|
22
|
+
def self.newTask
|
23
|
+
task = Task.new
|
24
|
+
@@tasks.push(task)
|
25
|
+
return task
|
26
|
+
end
|
27
|
+
|
28
|
+
# get array of all tasks
|
29
|
+
#
|
30
|
+
def self.getTasks
|
31
|
+
@@tasks
|
32
|
+
end
|
33
|
+
|
34
|
+
# create postsetup.json file
|
35
|
+
# path = "/sandbox/liveserver/customerName/software/repoOwner/repoName/releases/v2.2.0"
|
36
|
+
#
|
37
|
+
def self.createPostsetupFile (path)
|
38
|
+
if not @@tasks.empty?
|
39
|
+
# if exists, file will be overwritten
|
40
|
+
File.open(path + '/postsetup.json', 'wb') do |file|
|
41
|
+
file.write(Oj::dump @@tasks, :indent => 2)
|
42
|
+
file.close
|
43
|
+
end
|
44
|
+
else
|
45
|
+
print "(no tasks found)..."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# # postsetup tasks
|
52
|
+
# task = newTask
|
53
|
+
# task.title = "database"
|
54
|
+
# task.desc = "do database stuff"
|
55
|
+
# task.commands = [
|
56
|
+
# "php app/console doctrine:database:create",
|
57
|
+
# "php app/console doctrine:schema:update --dump-sql",
|
58
|
+
# "php app/console doctrine:schema:update --force",
|
59
|
+
# "echo 'y' | php app/console doctrine:fixtures:load"
|
60
|
+
# ]
|
61
|
+
|
62
|
+
# task = newTask
|
63
|
+
# task.title = "other stuff"
|
64
|
+
# task.desc = "just do the other stuff"
|
65
|
+
# task.commands = [
|
66
|
+
# "php otherstuff"
|
67
|
+
# ]
|
68
|
+
|
69
|
+
|
70
|
+
# [
|
71
|
+
# {
|
72
|
+
# "^o":"Deployman::App::Postsetup::Task",
|
73
|
+
# "title":"database",
|
74
|
+
# "desc":"do database stuff",
|
75
|
+
# "commands":[
|
76
|
+
# "php app/console doctrine:database:create",
|
77
|
+
# "php app/console doctrine:schema:update --dump-sql",
|
78
|
+
# "php app/console doctrine:schema:update --force",
|
79
|
+
# "echo 'y' | php app/console doctrine:fixtures:load"
|
80
|
+
# ]
|
81
|
+
# },
|
82
|
+
# {
|
83
|
+
# "^o":"Deployman::App::Postsetup::Task",
|
84
|
+
# "title":"other stuff",
|
85
|
+
# "desc":"just do the other stuff",
|
86
|
+
# "commands":[
|
87
|
+
# "php otherstuff"
|
88
|
+
# ]
|
89
|
+
# }
|
90
|
+
# ]
|
91
|
+
|
92
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https' if RUBY_VERSION < '1.9'
|
3
|
+
require 'net/ftp'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
module Deployman::Component::Downloader
|
8
|
+
|
9
|
+
def self.download_file(url, full_path, auth = false)
|
10
|
+
Main.new.download_file(url, full_path, auth)
|
11
|
+
end
|
12
|
+
|
13
|
+
class Main
|
14
|
+
|
15
|
+
def download_file(url, full_path, auth = false, redirects = 3)
|
16
|
+
if File.exist?(full_path)
|
17
|
+
print "(file already exists)..."
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
uri = URI.parse(url)
|
22
|
+
case uri.scheme.downcase
|
23
|
+
when /ftp/
|
24
|
+
puts "ftp not supported yet"
|
25
|
+
return false
|
26
|
+
when /http|https/
|
27
|
+
Main::http_download(url, full_path, auth, redirects)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# download over http, https
|
34
|
+
# redirects = how many redirects to follow
|
35
|
+
#
|
36
|
+
def self.http_download(url, full_path, auth, redirects)
|
37
|
+
|
38
|
+
begin
|
39
|
+
uri = URI.parse(url)
|
40
|
+
|
41
|
+
filename = File.basename(uri.path)
|
42
|
+
|
43
|
+
# http
|
44
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
45
|
+
if uri.scheme.downcase == 'https'
|
46
|
+
http.use_ssl = true
|
47
|
+
end
|
48
|
+
|
49
|
+
# request
|
50
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
51
|
+
request.basic_auth(auth[0], auth[1]) if auth
|
52
|
+
|
53
|
+
# do request
|
54
|
+
http.request(request) do |response|
|
55
|
+
case response
|
56
|
+
when Net::HTTPNotFound
|
57
|
+
# puts "404 - Not Found"
|
58
|
+
# return false
|
59
|
+
raise "404 - Not Found"
|
60
|
+
|
61
|
+
when Net::HTTPClientError
|
62
|
+
# puts "Error: Client Error: #{response.inspect}"
|
63
|
+
# return false
|
64
|
+
raise "Error: Client Error: #{response.inspect}"
|
65
|
+
|
66
|
+
when Net::HTTPRedirection
|
67
|
+
raise "Too many redirections for the original URL, halting." if redirects <= 0
|
68
|
+
url = response["location"]
|
69
|
+
return http_download(url, full_path, auth, redirects - 1)
|
70
|
+
|
71
|
+
when Net::HTTPOK
|
72
|
+
# create Tempfile
|
73
|
+
temp_file = Tempfile.new("download-#{filename}")
|
74
|
+
temp_file.binmode
|
75
|
+
|
76
|
+
# download and write into tempfile
|
77
|
+
Deployman::Component::Spinningclock.show_clock {
|
78
|
+
response.read_body do |chunk|
|
79
|
+
# write in Tempfile
|
80
|
+
temp_file << chunk
|
81
|
+
end
|
82
|
+
}
|
83
|
+
|
84
|
+
# close Tempfile
|
85
|
+
temp_file.close
|
86
|
+
|
87
|
+
# rename Tempfile in destination filename
|
88
|
+
File.unlink full_path if File.exists?(full_path)
|
89
|
+
FileUtils.mkdir_p File.dirname(full_path)
|
90
|
+
FileUtils.mv temp_file.path, full_path, :force => true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
rescue Exception => e
|
94
|
+
File.unlink full_path if File.exists?(full_path)
|
95
|
+
warn "ERROR: #{e.message}"
|
96
|
+
raise "Downloading failed!"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Deployman::Component::Output
|
4
|
+
|
5
|
+
# redirect outputs into tempfiles
|
6
|
+
#
|
7
|
+
def self.redirect_output
|
8
|
+
|
9
|
+
# backup original outputs
|
10
|
+
@@stdout = $stdout.dup
|
11
|
+
@@stderr = $stderr.dup
|
12
|
+
|
13
|
+
# open tempfiles
|
14
|
+
# will create temp files in /tmp/
|
15
|
+
@@stdout_temp = Tempfile.open 'stdout-redirect'
|
16
|
+
@@stderr_temp = Tempfile.open 'stderr-redirect'
|
17
|
+
|
18
|
+
# redirect outputs to tempfiles
|
19
|
+
$stdout.reopen @@stdout_temp.path, 'a'
|
20
|
+
$stderr.reopen @@stderr_temp.path, 'a'
|
21
|
+
end
|
22
|
+
|
23
|
+
# get both outputs from tempfiles
|
24
|
+
# will destroy tempfiles after read
|
25
|
+
#
|
26
|
+
def self.get_output
|
27
|
+
# restore original output (will write all outputs to tempfiles)
|
28
|
+
$stdout.reopen @@stdout
|
29
|
+
$stderr.reopen @@stderr
|
30
|
+
# return tempfile content
|
31
|
+
{'stdout' => @@stdout_temp.read, 'stderr' => @@stderr_temp.read}
|
32
|
+
end
|
33
|
+
|
34
|
+
# get stdout from tempfile
|
35
|
+
# will destroy tempfile after read
|
36
|
+
#
|
37
|
+
def self.get_stdout
|
38
|
+
# restore original output (will write all outputs to tempfiles)
|
39
|
+
$stdout.reopen @@stdout
|
40
|
+
# return tempfile content
|
41
|
+
@@stdout_temp.read
|
42
|
+
end
|
43
|
+
|
44
|
+
# get stderr from tempfile
|
45
|
+
# will destroy tempfile after read
|
46
|
+
#
|
47
|
+
def self.get_stderr
|
48
|
+
# restore original output (will write all outputs to tempfiles)
|
49
|
+
$stderr.reopen @@stderr
|
50
|
+
# return tempfile content
|
51
|
+
@@stderr_temp.read
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Deployman::Component::Spinningclock
|
2
|
+
|
3
|
+
@@active = true;
|
4
|
+
|
5
|
+
def self.show_clock(fps = 10)
|
6
|
+
|
7
|
+
if @@active
|
8
|
+
chars = %w[| / - \\]
|
9
|
+
delay = 1.0/fps
|
10
|
+
iter = 0
|
11
|
+
clock = Thread.new do
|
12
|
+
while iter do # Keep spinning until told otherwise
|
13
|
+
print chars[(iter+=1) % chars.length]
|
14
|
+
sleep delay
|
15
|
+
print "\b"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
yield.tap { # After yielding to the block, save the return value
|
19
|
+
iter = false # Tell the thread to exit, cleaning up after itself…
|
20
|
+
clock.join # …and wait for it to do so.
|
21
|
+
} # Use the block's return value as the method's
|
22
|
+
else
|
23
|
+
# just execute the block
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.set_active(active = true)
|
30
|
+
@@active = active
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'zip'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Deployman::Extractor::Zip
|
5
|
+
|
6
|
+
# extract_file
|
7
|
+
# file: "/tmp/repoOnwer-repoName-v2.2.0-0-gb98bf98.zip"
|
8
|
+
# dest: ".../customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
9
|
+
#
|
10
|
+
def self.extract_file (file, dest)
|
11
|
+
|
12
|
+
# dest = "/sandbox/liveserver/customerName/software/repoOnwer/repoName/releases/v2.2.0"
|
13
|
+
# dest_dir = "v2.2.0"
|
14
|
+
# dest_path = "/sandbox/liveserver/customerName/software/repoOwner/repoName/releases/"
|
15
|
+
dest_dir = dest.split("/").last
|
16
|
+
dest_path = dest.chomp(dest_dir)
|
17
|
+
root_folder = false
|
18
|
+
|
19
|
+
begin
|
20
|
+
|
21
|
+
# get the full path to the real unzipped folder
|
22
|
+
# e.g. "/sandbox/liveserver/.../releases/repoOnwer-repoName-3940226/"
|
23
|
+
root_folder = File.join(dest_path, Zip::File.open(file).first.name)
|
24
|
+
|
25
|
+
# lets create all needed dirs
|
26
|
+
FileUtils.mkdir_p(dest_path)
|
27
|
+
|
28
|
+
# unzip
|
29
|
+
Zip::File.open(file) do |zip_file|
|
30
|
+
|
31
|
+
Deployman::Component::Spinningclock.show_clock {
|
32
|
+
# unzip
|
33
|
+
zip_file.each do |f|
|
34
|
+
f_path=File.join(dest_path, f.name)
|
35
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
36
|
+
zip_file.extract(f, f_path) unless File.exist?(f_path)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# rename the unzipped root folder
|
43
|
+
File.rename(root_folder, dest)
|
44
|
+
|
45
|
+
rescue Exception => e
|
46
|
+
FileUtils.rm_rf(root_folder) if root_folder && File.exists?(root_folder)
|
47
|
+
FileUtils.rm_rf(dest) if File.exists?(dest)
|
48
|
+
warn "ERROR: #{e.message}"
|
49
|
+
raise "Unzipping failed!"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Deployman::Net::Post
|
4
|
+
|
5
|
+
def self.send (url, data)
|
6
|
+
|
7
|
+
# create http object
|
8
|
+
# e.g. url = 'http://localhost:8000/callback/install'
|
9
|
+
uri = URI.parse(url)
|
10
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
11
|
+
|
12
|
+
# create request object
|
13
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
14
|
+
# request.basic_auth(auth[0], auth[1]) if auth
|
15
|
+
|
16
|
+
# set request data
|
17
|
+
# e.g. data = { "mydata" => "funzt" }
|
18
|
+
request.body = JSON.generate(data, quirks_mode: true)
|
19
|
+
|
20
|
+
# do request and get response
|
21
|
+
response = http.request(request)
|
22
|
+
|
23
|
+
# return response data
|
24
|
+
resp_data = JSON.parse(response.body)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deployman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rafael Schmitt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-09-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: oj
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.10'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.10'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rubyzip
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.1'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.1'
|
46
|
+
description: tool to deploy software projects
|
47
|
+
email: rafael.schmitt@gogol-publishing.de
|
48
|
+
executables:
|
49
|
+
- deployman
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/deployman.rb
|
54
|
+
- lib/deployman/net.rb
|
55
|
+
- lib/deployman/component/downloader.rb
|
56
|
+
- lib/deployman/component/spinningclock.rb
|
57
|
+
- lib/deployman/component/output.rb
|
58
|
+
- lib/deployman/app/postsetup.rb
|
59
|
+
- lib/deployman/app/optionparser.rb
|
60
|
+
- lib/deployman/app/configuration.rb
|
61
|
+
- lib/deployman/app/install.rb
|
62
|
+
- lib/deployman/extractor.rb
|
63
|
+
- lib/deployman/component.rb
|
64
|
+
- lib/deployman/extractor/zip.rb
|
65
|
+
- lib/deployman/net/post.rb
|
66
|
+
- lib/deployman/app.rb
|
67
|
+
- bin/deployman
|
68
|
+
homepage: http://rubygems.org/gems/deployman
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.23
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: deployman
|
93
|
+
test_files: []
|