rigup 0.0.2
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 +4 -0
- data/Gemfile +2 -0
- data/README.md +1 -0
- data/Rakefile +6 -0
- data/bin/rigup +5 -0
- data/example deploy.thor +32 -0
- data/lib/rigup/cli.rb +159 -0
- data/lib/rigup/config.rb +22 -0
- data/lib/rigup/context.rb +59 -0
- data/lib/rigup/deploy_base.rb +33 -0
- data/lib/rigup/git_repo.rb +148 -0
- data/lib/rigup/install_utils.rb +94 -0
- data/lib/rigup/runability.rb +32 -0
- data/lib/rigup/svn.rb +80 -0
- data/lib/rigup/version.rb +3 -0
- data/lib/rigup.rb +14 -0
- data/notes.txt +19 -0
- data/rigup.gemspec +47 -0
- data/rigup.iml +28 -0
- data/spec/new_spec.rb +94 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_utils.rb +0 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 074cf53541cc8dda276109cd786eed5e4c013455
|
4
|
+
data.tar.gz: ba808e6dd94614a4f0cc179fe3dccd29f1c1f517
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d9ab780149ca55a6dca8bf1067bd723c00c532219e39196bcd8b5429c556a0bbccb790230c504c5fad0d638db0eb773436853df67dd5738d5b55f91dbd774127
|
7
|
+
data.tar.gz: a28e3901c130731e5792aa0683d11ec45534bd39840f4e4883b3861a88c33b545418c8cd2a4f1e711bbadb12f493181fc0fb227347f2375ca2376176f1be3876
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Toolset for deployment
|
data/Rakefile
ADDED
data/bin/rigup
ADDED
data/example deploy.thor
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rigup'
|
2
|
+
|
3
|
+
# This file will be called deploy.thor and lives in the root of the project repositiory, so it is version controlled
|
4
|
+
# and can be freely modified to suit the project requirements
|
5
|
+
class Deploy < Rigup::DeployBase # from gem, sets context and loads rigup.yml into config from site_dir
|
6
|
+
|
7
|
+
# You are free to modify these two tasks to suit your requirements
|
8
|
+
|
9
|
+
desc 'install','install the freshly delivered files'
|
10
|
+
def install
|
11
|
+
|
12
|
+
# select_suffixed_file("/config/database.yml")
|
13
|
+
# select_suffixed_file("/yore.config.xml")
|
14
|
+
# select_suffixed_file("/config/app_config.xml")
|
15
|
+
# select_suffixed_file("/system/apache.site")
|
16
|
+
#make_public_cache_dir("/public/cache")
|
17
|
+
|
18
|
+
# ensure_link("/log","/log")
|
19
|
+
# ensure_link("/pids","/tmp/pids")
|
20
|
+
# ensure_link("/uploads","/tmp/uploads")
|
21
|
+
# ensure_link("/system","/public/system")
|
22
|
+
|
23
|
+
#run "touch /log/production.log && chown : /log/production.log && chmod 666 /log/production.log"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'restart','restart the web server'
|
27
|
+
def restart
|
28
|
+
# run "touch " + File.join("current/tmp/restart.txt",@site_dir) # && chown user:group current/tmp/restart.txt"
|
29
|
+
# run "/etc/init.d/apache2 restart --force-reload"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/rigup/cli.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
module Rigup
|
2
|
+
class Cli < Thor
|
3
|
+
|
4
|
+
include Rigup::Runability
|
5
|
+
include Rigup::InstallUtils
|
6
|
+
|
7
|
+
attr_reader :context, :release_path
|
8
|
+
|
9
|
+
no_commands do
|
10
|
+
|
11
|
+
def init(aPath=nil,aConfig={})
|
12
|
+
return if @initialised
|
13
|
+
@initialised = true
|
14
|
+
aPath ||= aConfig[:site_dir] || Dir.pwd
|
15
|
+
@site_dir = Buzztools::File.real_path(aPath) rescue File.expand_path(aPath)
|
16
|
+
@releases_path = File.join(@site_dir,'releases')
|
17
|
+
if File.exists?(f=File.join(@site_dir,'rigup.yml'))
|
18
|
+
file_config = YAML.load(String.from_file(f))
|
19
|
+
aConfig.merge!(file_config)
|
20
|
+
end
|
21
|
+
config = Rigup::Config.new(aConfig.merge(site_dir: @site_dir))
|
22
|
+
@context = Rigup::Context.new(
|
23
|
+
config: config,
|
24
|
+
logger: ::Logger.new(STDOUT),
|
25
|
+
pwd: Dir.pwd
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def site_dir
|
30
|
+
@site_dir
|
31
|
+
end
|
32
|
+
|
33
|
+
def cache_dir
|
34
|
+
File.join(@site_dir,'shared','cached-copy')
|
35
|
+
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
@context.config
|
39
|
+
end
|
40
|
+
|
41
|
+
def repo
|
42
|
+
@repo ||= GitRepo.new(@context)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prepares repo in cache dir for site
|
46
|
+
# requires params: repo_url,site
|
47
|
+
def prepare_cache # {:url=>'git://github.com/ddssda', :branch=>'master', :commit=>'ad452bcd'}
|
48
|
+
url = config[:git_url]
|
49
|
+
wd = cache_dir
|
50
|
+
|
51
|
+
suitable = if File.exists?(wd)
|
52
|
+
repo.open wd
|
53
|
+
repo.origin.url==url
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
if suitable
|
59
|
+
repo.fetch
|
60
|
+
else
|
61
|
+
if File.exists? wd
|
62
|
+
#raise RuntimeError.new('almost did bad delete') if !@core.cache_dir || @core.cache_dir.length<3 || !wd.begins_with?(@core.cache_dir)
|
63
|
+
FileUtils.rm_rf wd
|
64
|
+
end
|
65
|
+
repo.clone(url, wd)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Switches @repo to given branch and/or commit
|
70
|
+
# Should call prepare_cache first to create @repo
|
71
|
+
# requires params: branch and/or commit
|
72
|
+
def checkout_branch_commit
|
73
|
+
branch = config[:branch] || 'master'
|
74
|
+
commit = config[:commit]
|
75
|
+
repo.open(cache_dir)
|
76
|
+
repo.checkout(commit,branch)
|
77
|
+
#perhaps use reset --hard here
|
78
|
+
if (commit)
|
79
|
+
repo.merge(commit,['--ff-only'])
|
80
|
+
else
|
81
|
+
repo.merge('origin/'+branch,['--ff-only'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_cache(aPath=nil)
|
86
|
+
prepare_cache
|
87
|
+
checkout_branch_commit
|
88
|
+
end
|
89
|
+
|
90
|
+
def release
|
91
|
+
release = Time.now.strftime('%Y%m%d%H%M%S')
|
92
|
+
@release_path = File.expand_path(release,@releases_path)
|
93
|
+
repo.open(cache_dir)
|
94
|
+
repo.export(@release_path)
|
95
|
+
release_config = context.config.to_hash
|
96
|
+
release_config[:commit] = repo.head.sha
|
97
|
+
release_config[:branch] = repo.branch
|
98
|
+
release_config.to_yaml.to_file(File.join(@release_path,'rigup.yml'))
|
99
|
+
return @release_path
|
100
|
+
end
|
101
|
+
|
102
|
+
def link_live
|
103
|
+
ensure_link(@release_path,File.expand_path(File.join(site_dir,'current')))
|
104
|
+
end
|
105
|
+
|
106
|
+
def cleanup
|
107
|
+
@releases = run("ls -x #{@releases_path}").split.sort
|
108
|
+
count = (@keep_releases || 3).to_i
|
109
|
+
if count >= @releases.length
|
110
|
+
@context.logger.info "no old releases to clean up"
|
111
|
+
else
|
112
|
+
@context.logger.info "keeping #{count} of #{@releases.length} deployed releases"
|
113
|
+
|
114
|
+
directories = (@releases - @releases.last(count)).map { |r|
|
115
|
+
File.join(@releases_path, r)
|
116
|
+
}.join(" ")
|
117
|
+
|
118
|
+
run "rm -rf #{directories}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def call_release_command(aCommand)
|
123
|
+
return unless cmdline = config["#{aCommand}_command".to_sym].to_s.strip.to_nil
|
124
|
+
run cmdline, @release_path
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
public
|
130
|
+
|
131
|
+
desc "new GIT_URL [PATH]", "setup new site"
|
132
|
+
def new(aGitUrl,aPath=nil)
|
133
|
+
aPath ||= File.basename(aGitUrl,'.git')
|
134
|
+
init(
|
135
|
+
aPath,
|
136
|
+
git_url: aGitUrl
|
137
|
+
)
|
138
|
+
FileUtils.mkdir_p(site_dir)
|
139
|
+
FileUtils.mkdir_p(File.join(site_dir,'releases'))
|
140
|
+
FileUtils.mkdir_p(File.join(site_dir,'shared'))
|
141
|
+
|
142
|
+
#+ create rigup.yml if doesn't exist, including option values
|
143
|
+
context.config.to_hash.filter_exclude(:site_dir).to_yaml.to_file(File.join(site_dir,'rigup.yml'))
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "deploy [PATH]", "deploy the given site"
|
147
|
+
def deploy(aPath=nil)
|
148
|
+
init(aPath)
|
149
|
+
update_cache
|
150
|
+
release
|
151
|
+
call_release_command(:install) # call install_command if defined eg. defaults to "thor deploy:install" eg. make changes to files
|
152
|
+
call_release_command(:block)
|
153
|
+
link_live
|
154
|
+
call_release_command(:restart) # call restart_command, defaults to "thor deploy:restart" eg. restart passenger
|
155
|
+
call_release_command(:unblock)
|
156
|
+
cleanup
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/rigup/config.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rigup
|
2
|
+
|
3
|
+
class Config < Buzztools::Config
|
4
|
+
|
5
|
+
DEFAULTS = {
|
6
|
+
site_dir: String,
|
7
|
+
git_url: String,
|
8
|
+
branch: String,
|
9
|
+
commit: String,
|
10
|
+
stage: 'live', # or 'staging' or 'development'
|
11
|
+
block_command: nil,
|
12
|
+
install_command: 'thor deploy:install',
|
13
|
+
restart_command: 'thor deploy:restart',
|
14
|
+
unblock_command: nil,
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(aValues=nil)
|
18
|
+
super(DEFAULTS,aValues)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rigup
|
2
|
+
class Context
|
3
|
+
|
4
|
+
attr_reader :config, :options, :argv, :env, :stdout, :stdin, :stderr, :key_chain, :credentials, :logger, :pwd, :variant
|
5
|
+
attr_writer :pwd
|
6
|
+
|
7
|
+
def sudo
|
8
|
+
''
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(aValues=nil)
|
12
|
+
return if !aValues
|
13
|
+
|
14
|
+
#is_client = !!(aValues[:key_chain] || aValues[:global_options] || aValues[:options])
|
15
|
+
@config = aValues[:config]
|
16
|
+
@pwd = Buzztools::File.real_path(aValues[:pwd] || (@config && @config[:folder]) || Dir.pwd)
|
17
|
+
@options = aValues[:options]
|
18
|
+
@argv = aValues[:argv]
|
19
|
+
@env = aValues[:env]
|
20
|
+
@stdout = aValues[:stdout]
|
21
|
+
@stdin = aValues[:stdin]
|
22
|
+
@stderr = aValues[:stderr]
|
23
|
+
@key_chain = aValues[:key_chain]
|
24
|
+
@credentials = aValues[:credentials]
|
25
|
+
@logger = aValues[:logger]
|
26
|
+
@variant = aValues[:variant]
|
27
|
+
end
|
28
|
+
|
29
|
+
def git_root
|
30
|
+
@git_root ||= find_git_root
|
31
|
+
end
|
32
|
+
|
33
|
+
# http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/
|
34
|
+
#class SimpleSemParserTest < Test::Unit::TestCase
|
35
|
+
# def test_set_stmt_write
|
36
|
+
# out = capture_stdout do
|
37
|
+
# parser = SimpleSemParser.new
|
38
|
+
# parser.parse('set write, "Hello World!"').execute
|
39
|
+
# end
|
40
|
+
# assert_equal "Hello World!\n", out.string
|
41
|
+
# end
|
42
|
+
#end
|
43
|
+
def capture_stdout
|
44
|
+
stdout_before = @stdout
|
45
|
+
out = StringIO.new
|
46
|
+
@stdout = out
|
47
|
+
yield
|
48
|
+
return out.string
|
49
|
+
ensure
|
50
|
+
@stdout = stdout_before
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_git_root
|
54
|
+
git_folder = BuzzTools::File.find_upwards(@pwd,'.git')
|
55
|
+
return git_folder && git_folder.chomp('/.git')
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rigup
|
2
|
+
|
3
|
+
class DeployBase < Thor
|
4
|
+
|
5
|
+
include Rigup::Runability
|
6
|
+
include Rigup::InstallUtils
|
7
|
+
|
8
|
+
no_commands do
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
@release_path = Dir.pwd
|
12
|
+
@site_dir = File.expand_path('../..')
|
13
|
+
@shared_path = File.expand_path('shared',@site_dir)
|
14
|
+
config = {}
|
15
|
+
if File.exists?(f=File.join(@release_path,'rigup.yml'))
|
16
|
+
file_config = YAML.load(String.from_file(f))
|
17
|
+
config.merge!(file_config)
|
18
|
+
end
|
19
|
+
@context = Rigup::Context.new(
|
20
|
+
config: Rigup::Config.new(config),
|
21
|
+
logger: ::Logger.new(STDOUT),
|
22
|
+
pwd: Dir.pwd,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def config
|
27
|
+
@context.config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module Rigup
|
4
|
+
class GitRepo
|
5
|
+
|
6
|
+
include Rigup::Runability
|
7
|
+
|
8
|
+
attr_reader :git,:configured
|
9
|
+
|
10
|
+
GIT_METHODS = [:commit,:add,:reset_hard,:path,:clone,:log,:size,:branches,:status,:remotes,:pull,:fetch,:push,:merge]
|
11
|
+
|
12
|
+
def initialize(aContext=nil)
|
13
|
+
@context = (aContext || Rigup::Context.new)
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(sym, *args, &block)
|
17
|
+
if @git && GIT_METHODS.include?(sym)
|
18
|
+
@git.send sym, *args, &block
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def open(aPath)
|
25
|
+
@git = ::Git.open(aPath)
|
26
|
+
end
|
27
|
+
|
28
|
+
def init(*args)
|
29
|
+
@git = ::Git.init(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clone(aUrl,aPath)
|
33
|
+
@git = ::Git::clone(aUrl,aPath)
|
34
|
+
end
|
35
|
+
|
36
|
+
def open?
|
37
|
+
!!@git
|
38
|
+
end
|
39
|
+
|
40
|
+
def empty?
|
41
|
+
!@git.branches[0]
|
42
|
+
end
|
43
|
+
|
44
|
+
def status
|
45
|
+
result = @git.lib.command_lines('status',['--porcelain'])
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def changes?
|
50
|
+
raise RuntimeError.new('Repository must be open') unless open?
|
51
|
+
status.length > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit_all(*args)
|
55
|
+
result = begin
|
56
|
+
@git.commit_all(*args)
|
57
|
+
rescue ::Git::GitExecuteError => e
|
58
|
+
if e.message.index("nothing to commit (working directory clean)")
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
raise e
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result = commitFromString(result)
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
# "[master (root-commit) 6bdd9e1] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file1.txt"
|
69
|
+
def commitFromString(aString)
|
70
|
+
return nil if !aString || aString.empty?
|
71
|
+
sha = aString.scan(/ ([a-f0-9]+)\]/).flatten.first
|
72
|
+
@git.gcommit(sha)
|
73
|
+
end
|
74
|
+
|
75
|
+
def path
|
76
|
+
@git.dir.path
|
77
|
+
end
|
78
|
+
|
79
|
+
def origin
|
80
|
+
@git.remotes.find {|r| r.name=='origin'}
|
81
|
+
end
|
82
|
+
|
83
|
+
def url
|
84
|
+
(o = origin) && o.url
|
85
|
+
end
|
86
|
+
|
87
|
+
def checkout(commit=nil,branch=nil)
|
88
|
+
specific_commit = !!commit && !commit.index('HEAD')
|
89
|
+
if specific_commit
|
90
|
+
@git.checkout commit
|
91
|
+
else
|
92
|
+
branch ||= 'master'
|
93
|
+
@git.checkout(branch)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# http://stackoverflow.com/questions/2866358/git-checkout-only-files-without-repository
|
98
|
+
# http://www.clientcide.com/best-practices/exporting-files-from-git-similar-to-svn-export/
|
99
|
+
def export(aDest)
|
100
|
+
#rsync --exclude=.git /source/directory/ user@remote-server.com:/target-directory
|
101
|
+
FileUtils.cp_r(path,aDest)
|
102
|
+
FileUtils.rm_rf(File.expand_path('.git',aDest))
|
103
|
+
end
|
104
|
+
|
105
|
+
def branch
|
106
|
+
@git.current_branch
|
107
|
+
end
|
108
|
+
|
109
|
+
def sha
|
110
|
+
head.sha
|
111
|
+
end
|
112
|
+
|
113
|
+
def head
|
114
|
+
@git.log.first
|
115
|
+
end
|
116
|
+
|
117
|
+
# ::Git --no-pager diff --name-status 26bb87c3981 191d64820f2b
|
118
|
+
# result is array of paths prefixed with status letter then a tab
|
119
|
+
# see http://git-scm.com/docs/git-diff under --diff-filter=
|
120
|
+
# Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
|
121
|
+
def changesBetweenCommits(aFromCommit, aToCommit)
|
122
|
+
@git.lib.command_lines('diff',['--name-status',aFromCommit,aToCommit])
|
123
|
+
end
|
124
|
+
|
125
|
+
# Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
|
126
|
+
def self.convertChangesToUploadsDeletes(changes)
|
127
|
+
uploads = []
|
128
|
+
deletes = []
|
129
|
+
changes.each do |line|
|
130
|
+
continue if line==""
|
131
|
+
tabi = line.index("\t")
|
132
|
+
status = line[0,tabi]
|
133
|
+
path = line[tabi+1..-1]
|
134
|
+
if status.index('D')
|
135
|
+
deletes << path
|
136
|
+
else
|
137
|
+
uploads << path
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return uploads,deletes
|
141
|
+
end
|
142
|
+
|
143
|
+
def get_file_content(aPath,aCommitOrBranch=nil)
|
144
|
+
@git.lib.command('show',[[aCommitOrBranch||'master',aPath].join(':')]) rescue nil
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Rigup
|
2
|
+
module InstallUtils
|
3
|
+
|
4
|
+
def select_suffixed_file(aFile,aExtendedExtension=false)
|
5
|
+
ext = Buzztools::File.extension(aFile,aExtendedExtension)
|
6
|
+
no_ext = Buzztools::File.no_extension(aFile,aExtendedExtension)
|
7
|
+
dir = File.dirname(aFile)
|
8
|
+
run "#{@context.sudo} mv -f #{no_ext}.#{@context.config[:stage]}.#{ext} #{aFile}"
|
9
|
+
run "#{@context.sudo} rm -f #{no_ext}.*.#{ext}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Especially for modifiying behaviour eg. of FCKEditor without upsetting the standard files
|
13
|
+
# eg. create a public_override folder that duplicates the same structure as public,
|
14
|
+
# and contains the modified files. On deployment call
|
15
|
+
# override_folder("#{@release_path}/public") # equiv to override_folder("#{@release_path}/public", "#{@release_path}/public_override")
|
16
|
+
# and the files in public_override will be copied over public, then public_override removed
|
17
|
+
def override_folder(aFolder,aOverrideFolder=nil,aRemove=true)
|
18
|
+
aFolder = aFolder.desuffix('/')
|
19
|
+
aOverrideFolder ||= (aFolder+'_override')
|
20
|
+
run "#{@context.sudo} cp -vrf #{aOverrideFolder}/* #{aFolder}/"
|
21
|
+
run "#{@context.sudo} rm -rf #{aOverrideFolder}" if aRemove
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# set standard permissions for web sites - readonly for apache user
|
26
|
+
def permissions_for_web(aPath,aUser=nil,aGroup=nil,aHideScm=nil)
|
27
|
+
aUser ||= @user
|
28
|
+
aGroup ||= @group
|
29
|
+
|
30
|
+
run "#{@context.sudo} chown -R #{aUser}:#{aGroup} #{aPath.ensure_suffix('/')}"
|
31
|
+
run_for_all("chmod 755",aPath,:dirs) # !!! perhaps reduce other permissions
|
32
|
+
run_for_all("chmod 644",aPath,:files)
|
33
|
+
run_for_all("chmod g+s",aPath,:dirs)
|
34
|
+
case aHideScm
|
35
|
+
when :svn then run_for_all("chmod -R 700",aPath,:dirs,"*/.svn")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# run this after permissions_for_web() on dirs that need to be writable by group (apache)
|
40
|
+
def permissions_for_web_writable(aPath)
|
41
|
+
run "chmod -R g+w #{aPath.ensure_suffix('/')}"
|
42
|
+
run_for_all("chmod -R 700",aPath,:dirs,"*/.svn")
|
43
|
+
end
|
44
|
+
|
45
|
+
def internal_permissions(aPath,aKind)
|
46
|
+
case aKind
|
47
|
+
when 'rails' then
|
48
|
+
permissions_for_web(aPath,@user,@group,true)
|
49
|
+
|
50
|
+
run_for_all("chmod +x",File.join(aPath,'script'),:files)
|
51
|
+
|
52
|
+
|
53
|
+
uploads = @shared_path+'/uploads'
|
54
|
+
make_public_cache_dir(uploads)
|
55
|
+
#if File.exists?(uploads)
|
56
|
+
# permissions_for_web(uploads,@user,@group,true)
|
57
|
+
# permissions_for_web_writable(uploads)
|
58
|
+
#end
|
59
|
+
#permissions_for_web_writable("#{aPath}/tmp")
|
60
|
+
make_public_cache_dir("#{aPath}/tmp")
|
61
|
+
|
62
|
+
run "#{@context.sudo} chown #{@apache_user} #{aPath}/config/environment.rb" unless DEV_MODE # very important for passenger, which uses the owner of this file to run as
|
63
|
+
|
64
|
+
when 'spree' then
|
65
|
+
internal_permissions(aPath,'rails')
|
66
|
+
when 'browsercms' then
|
67
|
+
internal_permissions(aPath,'rails')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def apply_permissions(aPath=nil,aKind=nil)
|
72
|
+
aPath ||= @release_path
|
73
|
+
aKind ||= @kind || 'rails'
|
74
|
+
internal_permissions(aPath, aKind)
|
75
|
+
end
|
76
|
+
|
77
|
+
def ensure_link(aTo,aFrom) #,aDir=nil,aUserGroup=nil,aSudo='')
|
78
|
+
raise "Must supply from" if !aFrom
|
79
|
+
cmd = []
|
80
|
+
#cmd << "cd #{aDir}" if aDir
|
81
|
+
cmd << "#{@context.sudo} rm -rf #{aFrom}"
|
82
|
+
cmd << "#{@context.sudo} ln -sf #{aTo} #{aFrom}"
|
83
|
+
#cmd << "#{@context.sudo} chown -h #{aUserGroup} #{aFrom}" if aUserGroup
|
84
|
+
run cmd.join(' && ')
|
85
|
+
end
|
86
|
+
|
87
|
+
def make_public_cache_dir(aStartPath)
|
88
|
+
run "#{@context.sudo} mkdir -p #{aStartPath}"
|
89
|
+
permissions_for_web(aStartPath)
|
90
|
+
permissions_for_web_writable(aStartPath)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rigup
|
2
|
+
module Runability
|
3
|
+
|
4
|
+
def run(aCommand,aDir=nil)
|
5
|
+
@context.logger.debug aCommand
|
6
|
+
response = ::POpen4::shell(aCommand,aDir || @context.pwd)
|
7
|
+
raise Error, "Command Failed" unless (response && response[:exitcode]==0)
|
8
|
+
return response[:stdout]
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_for_all(aCommand,aPath,aFilesOrDirs,aPattern=nil,aInvertPattern=false,aSudo=false)
|
12
|
+
#run "#{sudo} find . -wholename '*/.svn' -prune -o -type d -print0 |xargs -0 #{sudo} chmod 750"
|
13
|
+
#sudo find . -type f -exec echo {} \;
|
14
|
+
cmd = []
|
15
|
+
cmd << "sudo" if aSudo
|
16
|
+
cmd << "find #{aPath.ensure_suffix('/')}"
|
17
|
+
cmd << "-wholename '#{aPattern}'" if aPattern
|
18
|
+
cmd << "-prune -o" if aInvertPattern
|
19
|
+
cmd << case aFilesOrDirs.to_s[0,1]
|
20
|
+
when 'f' then '-type f'
|
21
|
+
when 'd' then '-type d'
|
22
|
+
else ''
|
23
|
+
end
|
24
|
+
cmd << "-exec"
|
25
|
+
cmd << aCommand
|
26
|
+
cmd << "'{}' \\;"
|
27
|
+
cmd = cmd.join(' ')
|
28
|
+
run cmd
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/rigup/svn.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Rigup
|
2
|
+
module Svn
|
3
|
+
|
4
|
+
def svnInfo(aPath)
|
5
|
+
cmdresult = run "svn info \"#{aPath}\""
|
6
|
+
cmdresult = cmdresult.split("\n")
|
7
|
+
result = {}
|
8
|
+
cmdresult.each do |line|
|
9
|
+
parts = line.split(': ')
|
10
|
+
next if parts.length!=2 || !parts[0] || !parts[1]
|
11
|
+
result[parts[0]] = parts[1]
|
12
|
+
end
|
13
|
+
|
14
|
+
if (url = result['URL']) && (root = result['Repository Root']) && url.start_with?(root)
|
15
|
+
result['Short URL'] = url[root.length]
|
16
|
+
end
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def svnCmd(aCommand,aSourceServer,aSourceUrl,aDestPath,aOptions = null)
|
21
|
+
"svn #{aCommand} \"#{aSourceServer ? File.join(aSourceServer,aSourceUrl) : aSourceUrl}\" \"#{aDestPath}\" #{aOptions || ''}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def svnCheckoutCmd(aConfig,aCommmand='checkout',aOptions=nil)
|
25
|
+
options = []
|
26
|
+
options << aOptions if aOptions
|
27
|
+
options << '--username '+aConfig['vcs_username'] if aConfig['vcs_username']
|
28
|
+
options << '--password '+aConfig['vcs_password'] if aConfig['vcs_password']
|
29
|
+
options << '--revision '+aConfig['revision'] if aConfig['revision']
|
30
|
+
options = options.join ' '
|
31
|
+
|
32
|
+
rep = aConfig['repository'].to_s.chomp('/').to_nil
|
33
|
+
if rep && (branch = aConfig['branch'])
|
34
|
+
branch = '/'+branch unless branch.start_with? '/'
|
35
|
+
url = File.join(branch,aConfig['source'].to_s) if aConfig['source']
|
36
|
+
else
|
37
|
+
url = aConfig['source']
|
38
|
+
end
|
39
|
+
url = url.chomp('/')
|
40
|
+
|
41
|
+
svnCmd(aCommmand,rep,url,aConfig['destination'],options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def createSvnConfig(aMergeOptions = nil)
|
45
|
+
result = {
|
46
|
+
'repository' => @repository,
|
47
|
+
'source' => @vcs_app_path,
|
48
|
+
'branch' => @branch,
|
49
|
+
'destination' => @release_path,
|
50
|
+
'revision' => @revision
|
51
|
+
}
|
52
|
+
result.merge!(aMergeOptions) if aMergeOptions
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def folderIsSvn(aPath)
|
57
|
+
return false unless File.exists?(aPath)
|
58
|
+
info = svnInfo(aPath)
|
59
|
+
return !!(info && info['URL'])
|
60
|
+
end
|
61
|
+
|
62
|
+
# ensure cache_path is an svn repo and is up to date. Checkout if not
|
63
|
+
def ensureSvnCacheUpdate(cache_path,svnConfig)
|
64
|
+
svnConfig = svnConfig.merge('destination' => cache_path)
|
65
|
+
if File.exists?(cache_path)
|
66
|
+
raise Error('Dir exists but not a svn folder') unless folderIsSvn(cache_path)
|
67
|
+
run "svn revert --non-interactive --recursive \"#{cache_path}\""
|
68
|
+
run svnCheckoutCmd(
|
69
|
+
svnConfig,
|
70
|
+
'switch',
|
71
|
+
'--non-interactive'
|
72
|
+
)
|
73
|
+
else
|
74
|
+
MiscUtils.mkdir?(MiscUtils.path_parent(cache_path))
|
75
|
+
run svnCheckoutCmd(svnConfig,'checkout','--non-interactive')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/rigup.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'buzztools'
|
3
|
+
require 'logger'
|
4
|
+
require 'yaml'
|
5
|
+
require 'buzztools/extras/shell_extras'
|
6
|
+
|
7
|
+
require_relative "rigup/version"
|
8
|
+
require_relative "rigup/config"
|
9
|
+
require_relative "rigup/context"
|
10
|
+
require_relative "rigup/runability"
|
11
|
+
require_relative "rigup/install_utils"
|
12
|
+
require_relative "rigup/git_repo"
|
13
|
+
require_relative "rigup/cli"
|
14
|
+
require_relative "rigup/deploy_base"
|
data/notes.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
From site root :
|
2
|
+
|
3
|
+
> cd /var/www
|
4
|
+
> rigup new repo_url mysite
|
5
|
+
+ make dir mysite
|
6
|
+
+ create rigup.yml if doesn't exist, including option values
|
7
|
+
+ make dir mysite/releases
|
8
|
+
+ make dir mysite/shared
|
9
|
+
|
10
|
+
> rigup deploy mysite
|
11
|
+
|
12
|
+
+ git clone repo_url mysite/releases/20140328234123
|
13
|
+
+ installing
|
14
|
+
|
15
|
+
|
16
|
+
> cd mysite
|
17
|
+
> rigup update
|
18
|
+
+ using plan rigup.yml
|
19
|
+
|
data/rigup.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rigup/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rigup"
|
7
|
+
s.version = Rigup::VERSION
|
8
|
+
s.authors = ["Gary McGhee"]
|
9
|
+
s.email = ["contact@buzzware.com.au"]
|
10
|
+
s.homepage = "http://github.com/buzzware/rigup"
|
11
|
+
s.summary = "Toolset for deployment"
|
12
|
+
s.description = s.summary
|
13
|
+
|
14
|
+
ignores = File.readlines(".gitignore").grep(/\S+/).map {|line| line.chomp }
|
15
|
+
dotfiles = [".gitignore"]
|
16
|
+
s.files = Dir["**/*"].reject {|f| File.directory?(f) || ignores.any? {|i| File.fnmatch(i, f) } } + dotfiles
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
+
|
21
|
+
s.add_dependency 'bundler', '~>1.5.3'
|
22
|
+
s.add_dependency 'thor', '~> 0.19.1'
|
23
|
+
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec', '~>2.14.0'
|
26
|
+
#s.add_development_dependency('rspec')
|
27
|
+
|
28
|
+
s.add_development_dependency('rake')
|
29
|
+
#s.add_development_dependency('rspec-core')
|
30
|
+
#s.add_development_dependency('rdoc')
|
31
|
+
#s.add_development_dependency('aruba')
|
32
|
+
#s.add_development_dependency('debugger')
|
33
|
+
#s.add_runtime_dependency('gli','2.5.0')
|
34
|
+
#s.add_runtime_dependency('termios')
|
35
|
+
#s.add_runtime_dependency('highline')
|
36
|
+
s.add_runtime_dependency('git')
|
37
|
+
#s.add_runtime_dependency('middleman')
|
38
|
+
s.add_runtime_dependency('buzztools')
|
39
|
+
s.add_runtime_dependency('POpen4')
|
40
|
+
# https://github.com/geemus/formatador
|
41
|
+
#s.add_runtime_dependency('bitbucket_rest_api')
|
42
|
+
#s.add_runtime_dependency('osx_keychain')
|
43
|
+
#s.add_runtime_dependency('json')
|
44
|
+
#s.add_runtime_dependency('net_dav')
|
45
|
+
#s.add_runtime_dependency('net-ssh')
|
46
|
+
#s.add_runtime_dependency('system_timer')
|
47
|
+
end
|
data/rigup.iml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="DBNavigator.Module.ConnectionManager">
|
4
|
+
<connections />
|
5
|
+
</component>
|
6
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
7
|
+
<exclude-output />
|
8
|
+
<content url="file://$MODULE_DIR$">
|
9
|
+
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
10
|
+
</content>
|
11
|
+
<orderEntry type="inheritedJdk" />
|
12
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
13
|
+
<orderEntry type="library" scope="PROVIDED" name="POpen4 (v0.1.4, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
14
|
+
<orderEntry type="library" scope="PROVIDED" name="Platform (v0.4.0, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
15
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.5.3, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="buzztools (v0.0.4, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="git (v1.2.6, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="open4 (v1.3.3, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.2.0, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v2.14.1, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v2.14.8, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v2.14.5, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v2.14.6, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="thor (v0.19.1, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
26
|
+
</component>
|
27
|
+
</module>
|
28
|
+
|
data/spec/new_spec.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
#require 'file_utils'
|
3
|
+
|
4
|
+
describe 'rigup' do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@old_dir = Dir.pwd
|
8
|
+
Dir.chdir(@dir = Dir.mktmpdir("new_spec"))
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
Dir.chdir(@old_dir)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_site_process(aGitUrl)
|
16
|
+
@script = Rigup::Cli.new
|
17
|
+
@script.invoke(:new, [aGitUrl, 'mysite'])
|
18
|
+
Dir.exists?('mysite/releases').should be
|
19
|
+
Dir.exists?('mysite/shared').should be
|
20
|
+
File.exists?('mysite/rigup.yml').should be
|
21
|
+
|
22
|
+
@config = YAML.load_file('mysite/rigup.yml')
|
23
|
+
@config[:git_url].should == aGitUrl
|
24
|
+
end
|
25
|
+
|
26
|
+
def mock_get_repo(aUrl,aPath)
|
27
|
+
basename = File.basename(aUrl,'.git')
|
28
|
+
src = "~/repos/underscore_plus" unless File.exists?(src = "~/repos/#{basename}")
|
29
|
+
FileUtils.cp_r(File.expand_path(src),File.expand_path(aPath))
|
30
|
+
end
|
31
|
+
|
32
|
+
def stub_out_github
|
33
|
+
::Rigup::GitRepo.any_instance.stub(:clone) do |aUrl,aPath|
|
34
|
+
mock_get_repo(aUrl,aPath)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RELEASE_INSTALL = <<-EOS
|
39
|
+
class Deploy < Thor
|
40
|
+
|
41
|
+
desc 'install','install the freshly delivered files'
|
42
|
+
def install
|
43
|
+
puts 'install'
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'restart','restart the web server'
|
47
|
+
def restart
|
48
|
+
puts 'restart'
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
EOS
|
53
|
+
|
54
|
+
describe "Given new project" do
|
55
|
+
|
56
|
+
it "deploy should update_cache, install and link_live" do
|
57
|
+
#Rigup::Cli.any_instance.stub(:restart => true, :install => true)
|
58
|
+
new_site_process('https://github.com/buzzware/underscore_plus.git')
|
59
|
+
::Rigup::GitRepo.any_instance.stub(:clone) do |aUrl,aPath|
|
60
|
+
mock_get_repo(aUrl,aPath)
|
61
|
+
RELEASE_INSTALL.to_file(File.join(aPath,'deploy.thor'))
|
62
|
+
end
|
63
|
+
|
64
|
+
@script2 = Rigup::Cli.new
|
65
|
+
@script2.invoke(:deploy, ['mysite'])
|
66
|
+
|
67
|
+
Dir.exists?('mysite/shared/cached-copy').should be
|
68
|
+
Dir.exists?('mysite/shared/cached-copy/.git').should be
|
69
|
+
Dir.exists?('mysite/shared/cached-copy/.git').should be
|
70
|
+
|
71
|
+
Dir.exists?('mysite/current').should be
|
72
|
+
|
73
|
+
entries = Dir.entries('mysite/releases')
|
74
|
+
entries.length.should == 3
|
75
|
+
release_path = entries.last
|
76
|
+
release_path.should =~ /#{Time.now.strftime('%Y%m%d%H')}/
|
77
|
+
|
78
|
+
# Release method should write a rigup.yml including branch, commit, stage etc (should not be in repo)
|
79
|
+
# Rigup::DeployBase then reads this and makes it accessible to install and restart methods
|
80
|
+
# Then we can do things like displaying git commit hash on page as the site knows its own full identity
|
81
|
+
release_config = YAML.load_file("mysite/releases/#{release_path}/rigup.yml")
|
82
|
+
release_config.should be_a Hash
|
83
|
+
|
84
|
+
cache_repo = ::Rigup::GitRepo.new(Rigup::Context.new)
|
85
|
+
cache_repo.open('mysite/shared/cached-copy')
|
86
|
+
|
87
|
+
release_config[:branch].should be
|
88
|
+
release_config[:branch].should == cache_repo.branch
|
89
|
+
release_config[:commit].should be
|
90
|
+
release_config[:commit].should == cache_repo.sha
|
91
|
+
release_config[:stage].should == 'live'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'rspec'
|
4
|
+
require 'rigup'
|
5
|
+
require_relative 'spec_utils'
|
6
|
+
|
7
|
+
include Rigup
|
8
|
+
|
9
|
+
#RSpec.configure do |config|
|
10
|
+
# def config.escaped_path(*parts)
|
11
|
+
# Regexp.compile(parts.join('[\\\/]'))
|
12
|
+
# end unless config.respond_to? :escaped_path
|
13
|
+
#end
|
14
|
+
|
15
|
+
# Include support files.
|
16
|
+
#Dir["#{File.expand_path('../', __FILE__)}/support/**/*.rb"].each { |f| require f }
|
data/spec/spec_utils.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rigup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gary McGhee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.19.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.19.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: git
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: buzztools
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: POpen4
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Toolset for deployment
|
112
|
+
email:
|
113
|
+
- contact@buzzware.com.au
|
114
|
+
executables:
|
115
|
+
- rigup
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- bin/rigup
|
120
|
+
- example deploy.thor
|
121
|
+
- Gemfile
|
122
|
+
- lib/rigup/cli.rb
|
123
|
+
- lib/rigup/config.rb
|
124
|
+
- lib/rigup/context.rb
|
125
|
+
- lib/rigup/deploy_base.rb
|
126
|
+
- lib/rigup/git_repo.rb
|
127
|
+
- lib/rigup/install_utils.rb
|
128
|
+
- lib/rigup/runability.rb
|
129
|
+
- lib/rigup/svn.rb
|
130
|
+
- lib/rigup/version.rb
|
131
|
+
- lib/rigup.rb
|
132
|
+
- notes.txt
|
133
|
+
- Rakefile
|
134
|
+
- README.md
|
135
|
+
- rigup.gemspec
|
136
|
+
- rigup.iml
|
137
|
+
- spec/new_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/spec_utils.rb
|
140
|
+
- .gitignore
|
141
|
+
homepage: http://github.com/buzzware/rigup
|
142
|
+
licenses: []
|
143
|
+
metadata: {}
|
144
|
+
post_install_message:
|
145
|
+
rdoc_options: []
|
146
|
+
require_paths:
|
147
|
+
- lib
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 2.1.5
|
161
|
+
signing_key:
|
162
|
+
specification_version: 4
|
163
|
+
summary: Toolset for deployment
|
164
|
+
test_files:
|
165
|
+
- spec/new_spec.rb
|
166
|
+
- spec/spec_helper.rb
|
167
|
+
- spec/spec_utils.rb
|