deployman 1.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.
- 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: []
|