bonethug 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +5 -3
- data/Rakefile +2 -1
- data/bin/bonethug +2 -7
- data/lib/bonethug/cli.rb +44 -0
- data/lib/bonethug/installer.rb +202 -0
- data/lib/bonethug/version.rb +1 -1
- data/lib/bonethug.rb +3 -13
- data/lib/tasks/setup.rake +1 -1
- data/skel/base/README.md +2 -2
- data/skel/base/config/{cnf.yml → example.cnf.yml} +47 -8
- data/skel/base/config/{deploy.rb → example.deploy.rb} +23 -3
- data/skel/base/lib/conf.rb +4 -4
- data/skel/base/log/.gitkeep +0 -0
- data/skel/project_types/drupal/.gitignore +10 -21
- data/skel/project_types/drupal/composer.json +2 -28
- data/skel/project_types/drupal/public/sites/default/development.settings.php +259 -0
- data/skel/project_types/drupal/public/sites/default/production.settings.php +259 -0
- data/skel/project_types/drupal/public/sites/default/settings.php +17 -0
- data/skel/project_types/drupal/public/sites/default/staging.settings.php +260 -0
- data/skel/project_types/php/composer.json +2 -28
- data/skel/project_types/silverstripe3/config/example.schedule.rb +58 -0
- data/skel/skel.yml +7 -0
- metadata +15 -8
- data/lib/bonethug/setup.rake +0 -19
- data/skel/base/composer.json +0 -31
- /data/skel/base/config/{backup.rb → example.backup.rb} +0 -0
- /data/skel/base/config/{schedule.rb → example.schedule.rb} +0 -0
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Bonethug
|
2
2
|
|
3
|
-
|
3
|
+
Project Skeleton Manager
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -18,7 +18,9 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
### Commands
|
22
|
+
|
23
|
+
$ bonethug install {rails3|silverstripe3|drupal|php|sinatra}
|
22
24
|
|
23
25
|
## Contributing
|
24
26
|
|
@@ -26,4 +28,4 @@ TODO: Write usage instructions here
|
|
26
28
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
29
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
30
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
31
|
+
5. Create new Pull Request
|
data/Rakefile
CHANGED
data/bin/bonethug
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
|
2
3
|
root_path = File.expand_path(File.dirname(__FILE__)) + '/..'
|
3
|
-
puts root_path
|
4
4
|
|
5
5
|
require 'rubygems' unless Object.const_defined?(:Gem)
|
6
6
|
require root_path +'/lib/bonethug'
|
7
|
-
require 'rake'
|
8
|
-
|
9
|
-
ARGV.each do|a|
|
10
|
-
puts "Argument: #{a}"
|
11
|
-
end
|
12
7
|
|
13
|
-
Bonethug::
|
8
|
+
Bonethug::CLI.handle
|
data/lib/bonethug/cli.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Bonethug
|
2
|
+
class CLI
|
3
|
+
|
4
|
+
def self.handle
|
5
|
+
|
6
|
+
# what are we doing?
|
7
|
+
task = ARGV[0] || 'help'
|
8
|
+
|
9
|
+
case task
|
10
|
+
|
11
|
+
when 'help'
|
12
|
+
|
13
|
+
display_help
|
14
|
+
|
15
|
+
when 'install'
|
16
|
+
|
17
|
+
# handle args
|
18
|
+
type = ARGV[1]
|
19
|
+
location = ARGV[2] || '.'
|
20
|
+
puts 'Usage: bonethug install [location]' if type.empty?
|
21
|
+
|
22
|
+
# run the installer
|
23
|
+
Installer.install type, location
|
24
|
+
|
25
|
+
when 'clean'
|
26
|
+
|
27
|
+
location = ARGV[1] || '.'
|
28
|
+
Installer.clean location
|
29
|
+
|
30
|
+
else
|
31
|
+
|
32
|
+
# We didn't find a task
|
33
|
+
puts 'Task not found'
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.display_help
|
40
|
+
puts 'Usage: bonethug task [argument]...'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../../skel/base/lib/conf'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'find'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Bonethug
|
8
|
+
|
9
|
+
class Installer
|
10
|
+
|
11
|
+
include FileUtils
|
12
|
+
include Digest
|
13
|
+
|
14
|
+
@@skel_dir = File.expand_path(File.dirname(__FILE__)) + '/../../skel'
|
15
|
+
@@conf = Conf.new.add(@@skel_dir + '/skel.yml')
|
16
|
+
@@project_config_files = ['backup.rb','cnf.yml','deploy.rb','schedule.rb']
|
17
|
+
|
18
|
+
def self.install(type, target = '.')
|
19
|
+
|
20
|
+
# @@conf = Conf.new.add(@@skel_dir + '/skel.yml')
|
21
|
+
|
22
|
+
# create full path
|
23
|
+
target = File.expand_path target
|
24
|
+
|
25
|
+
# let the user know we are installing
|
26
|
+
puts 'Installing '+ type + ' to ' + target + '...'
|
27
|
+
|
28
|
+
# load the configuration
|
29
|
+
raise "Unsupported type: " + type.to_s unless @@conf.get('project_types').has_key? type.to_s
|
30
|
+
conf = @@conf.node_merge 'base', 'project_types.' + type
|
31
|
+
|
32
|
+
# set the tmp dir
|
33
|
+
tmp_dir = File.expand_path target + '/.bonethug-tmp'
|
34
|
+
|
35
|
+
# clean up any exisitng install tmp files
|
36
|
+
if File.directory? tmp_dir
|
37
|
+
puts 'Cleaning up old installer temporary files...'
|
38
|
+
FileUtils.rm_rf tmp_dir
|
39
|
+
end
|
40
|
+
|
41
|
+
# create tmp dir
|
42
|
+
puts 'Creating build directory at ' + tmp_dir
|
43
|
+
FileUtils.mkdir tmp_dir
|
44
|
+
FileUtils.mkdir tmp_dir + '/.bonethug'
|
45
|
+
|
46
|
+
# build the file set
|
47
|
+
puts 'Building ' + type + ' skeleton...'
|
48
|
+
FileUtils.cp_r @@skel_dir + '/project_types/' + type + '/.', tmp_dir
|
49
|
+
FileUtils.cp_r @@skel_dir + '/base/.', tmp_dir
|
50
|
+
|
51
|
+
# build the manifest
|
52
|
+
puts 'Creating manifest...'
|
53
|
+
self.build_manifest tmp_dir
|
54
|
+
|
55
|
+
# modify the manifest root
|
56
|
+
manifest_path = tmp_dir + '/.bonethug/manifest'
|
57
|
+
File.open(manifest_path,'w') do |file|
|
58
|
+
file.puts File.read(manifest_path).gsub(/\.bonethug-tmp/,'')
|
59
|
+
end
|
60
|
+
|
61
|
+
# clean up the target dir
|
62
|
+
puts 'Cleaning up install directory...'
|
63
|
+
self.clean target
|
64
|
+
|
65
|
+
# copy the files
|
66
|
+
puts 'Installing build to ' + target + '...'
|
67
|
+
FileUtils.cp_r tmp_dir + '/.', target
|
68
|
+
|
69
|
+
# try to update the configuration files
|
70
|
+
puts 'Updating configs...'
|
71
|
+
self.update_configuration_files(target)
|
72
|
+
|
73
|
+
# try to update the configuration files
|
74
|
+
puts 'Updating build informtation...'
|
75
|
+
self.save_project_meta_data(target)
|
76
|
+
|
77
|
+
# clean up any exisitng install tmp files
|
78
|
+
puts 'Cleaning up temporary files...'
|
79
|
+
FileUtils.rm_rf tmp_dir
|
80
|
+
|
81
|
+
puts "Installation Complete"
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.clean(target)
|
86
|
+
|
87
|
+
manifest_path = target + '/.bonethug/manifest'
|
88
|
+
|
89
|
+
if File.exists? manifest_path
|
90
|
+
|
91
|
+
puts 'Reading manifest...'
|
92
|
+
manifest = File.read(manifest_path).split("\n")
|
93
|
+
|
94
|
+
puts 'Cleaning up ' + manifest.count.to_s + ' files'
|
95
|
+
not_removed = []
|
96
|
+
manifest.each do |file|
|
97
|
+
not_removed.push file unless self.try_delete file
|
98
|
+
end
|
99
|
+
|
100
|
+
if not_removed.count > 0
|
101
|
+
|
102
|
+
puts 'Retrying removal of ' + not_removed.count.to_s + ' files'
|
103
|
+
failed = []
|
104
|
+
not_removed.each do |file|
|
105
|
+
failed.push file unless self.try_delete file
|
106
|
+
end
|
107
|
+
|
108
|
+
puts 'Removal of the following' + failed.count.to_s + ' files failed'
|
109
|
+
puts failed.join("\n")
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
else
|
114
|
+
puts 'Nothing to do'
|
115
|
+
end
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
def self.try_delete(file)
|
122
|
+
if (File.directory?(file) and Find.find(file).empty?) or File.file?(file)
|
123
|
+
rm_rf file
|
124
|
+
return false if File.exists? file
|
125
|
+
return true
|
126
|
+
else
|
127
|
+
return false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.build_manifest(dir)
|
132
|
+
dir_contents = Find.find(dir).map { |p| File.expand_path(p) }
|
133
|
+
manifest = dir_contents - ((@@conf.get('exlcuded_paths') || []).map { |p| File.expand_path(p) })
|
134
|
+
File.open(dir + '/.bonethug/manifest','w') { |file| file.puts manifest.join("\n") }
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.update_configuration_files(target)
|
139
|
+
|
140
|
+
# load the existing project's datafile if present
|
141
|
+
meta_data = self.get_project_meta_data target
|
142
|
+
|
143
|
+
@@project_config_files.each do |config|
|
144
|
+
|
145
|
+
do_copy = true
|
146
|
+
example_file = target + '/config/example.' + config
|
147
|
+
target_file = target + '/config/' + config
|
148
|
+
|
149
|
+
# analyse the config file + build data file
|
150
|
+
file_exists = File.exist?(target_file)
|
151
|
+
contents_not_modified = false
|
152
|
+
contents_not_modified = true if file_exists and meta_data and meta_data['config_digests'] and meta_data['config_digests']['example.' + config] == self.contents_md5(target_file)
|
153
|
+
|
154
|
+
# meta_data_is_hash = meta_data_exists and meta_data.class.name == 'Hash' and meta_data['config_digests'].class.name == 'Hash'
|
155
|
+
# config_digests_found = meta_data_is_hash and meta_data['config_digests'].methods.include?('has_key?') and meta_data['config_digests'].has_key?('example.' + config)
|
156
|
+
# contents_not_modified = config_digests_found and meta_data['config_digests']['example.' + config] == self.contents_md5(target_file)
|
157
|
+
|
158
|
+
# don't copy if the file exists...
|
159
|
+
do_copy = false if file_exists
|
160
|
+
|
161
|
+
# unless it hasn't been modified, i.e. probably not conf.yml, but possibly some of the other ones
|
162
|
+
|
163
|
+
do_copy = true if contents_not_modified
|
164
|
+
|
165
|
+
# Copy if that's ok
|
166
|
+
FileUtils.cp example_file, target_file if do_copy
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
# return self for chaining
|
171
|
+
self
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.contents_md5(file)
|
176
|
+
return false unless File.exist?(file)
|
177
|
+
MD5.digest File.read(file)
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.save_project_meta_data(base_dir)
|
181
|
+
|
182
|
+
meta_data = {'config_digests' => {}}
|
183
|
+
@@project_config_files.each do |file|
|
184
|
+
meta_data['config_digests']['example.' + file] = self.contents_md5(base_dir + '/config/example.' + file)
|
185
|
+
end
|
186
|
+
File.open(base_dir + '/.bonethug/data','w') { |file| file.puts meta_data.to_yaml }
|
187
|
+
|
188
|
+
# return self for chaining
|
189
|
+
self
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.get_project_meta_data(base_dir)
|
194
|
+
|
195
|
+
data_file = base_dir + '/.bonethug/data'
|
196
|
+
return YAML.load_file data_file if File.exists? data_file
|
197
|
+
return false
|
198
|
+
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
data/lib/bonethug/version.rb
CHANGED
data/lib/bonethug.rb
CHANGED
@@ -1,17 +1,7 @@
|
|
1
1
|
require "bonethug/version"
|
2
|
+
require "bonethug/installer"
|
3
|
+
require "bonethug/cli"
|
2
4
|
|
3
5
|
module Bonethug
|
4
6
|
|
5
|
-
|
6
|
-
def self.call_rake(arguments)
|
7
|
-
if RUBY_PLATFORM =~ /mswin/
|
8
|
-
rake_cmd = "rake.bat" #very important because windows will break with just "rake"
|
9
|
-
else
|
10
|
-
rake_cmd = "rake"
|
11
|
-
end
|
12
|
-
puts "calling #{rake_cmd} " + arguments
|
13
|
-
puts system("#{rake_cmd} " + arguments)
|
14
|
-
puts $?
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
7
|
+
end
|
data/lib/tasks/setup.rake
CHANGED
data/skel/base/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
deploy:
|
2
2
|
common:
|
3
|
-
project_type:
|
3
|
+
project_type: rails3 | silverstripe3 | drupal | php | sinatra
|
4
4
|
base_dir: /var/www
|
5
5
|
repository: git@gitlab.....
|
6
6
|
project_slug: tradespot
|
@@ -12,13 +12,27 @@ deploy:
|
|
12
12
|
development:
|
13
13
|
staging:
|
14
14
|
domain: staging.domain.com
|
15
|
+
default_branch: master
|
15
16
|
production:
|
16
|
-
domain: production.
|
17
|
+
domain: production.domain.com
|
18
|
+
default_branch: stable
|
17
19
|
dbs:
|
18
20
|
default:
|
19
21
|
development:
|
22
|
+
user: root
|
23
|
+
pass:
|
24
|
+
host: localhost
|
25
|
+
port: 3306
|
20
26
|
staging:
|
27
|
+
user: staging_db
|
28
|
+
pass: passw0rd
|
29
|
+
host: localhost
|
30
|
+
port: 3306
|
21
31
|
production:
|
32
|
+
user: production_db
|
33
|
+
pass: passw0rd
|
34
|
+
host: localhost
|
35
|
+
port: 3306
|
22
36
|
backup:
|
23
37
|
local:
|
24
38
|
keep:2
|
@@ -27,6 +41,16 @@ backup:
|
|
27
41
|
host: backup-host.com
|
28
42
|
user: remote_backup
|
29
43
|
pass: passw0rd
|
44
|
+
sftp:
|
45
|
+
keep: 10
|
46
|
+
host: backup-host.com
|
47
|
+
user: remote_backup
|
48
|
+
pass: passw0rd
|
49
|
+
s3:
|
50
|
+
keep: 10
|
51
|
+
key: key
|
52
|
+
secret: secret
|
53
|
+
bucket: bucket
|
30
54
|
apache:
|
31
55
|
development:
|
32
56
|
staging:
|
@@ -46,14 +70,29 @@ apache:
|
|
46
70
|
SS_ENVIRONMENT_TYPE: live
|
47
71
|
RAILS_ENV: production
|
48
72
|
APPLICATION_ENV: production
|
49
|
-
|
50
|
-
permissions:
|
73
|
+
chown:
|
51
74
|
development:
|
52
75
|
staging:
|
53
|
-
www_executable:
|
54
|
-
- vendor/bin
|
55
76
|
production:
|
56
|
-
|
57
|
-
|
77
|
+
-
|
78
|
+
path: public/uploads
|
79
|
+
user: www-data
|
80
|
+
chmod:
|
81
|
+
development:
|
82
|
+
staging:
|
83
|
+
production:
|
84
|
+
-
|
85
|
+
path: public/uploads
|
86
|
+
mode: 775
|
87
|
+
chgrp:
|
88
|
+
development:
|
89
|
+
staging:
|
90
|
+
production:
|
91
|
+
-
|
92
|
+
path: public/uploads
|
93
|
+
group: www-data
|
94
|
+
resources:
|
95
|
+
- public/assets
|
96
|
+
- public/uploads
|
58
97
|
log_dirs:
|
59
98
|
- log
|
@@ -197,9 +197,29 @@ task :deploy => :environment do
|
|
197
197
|
queue! %[cd #{deploy_to}/current/public && chown -R www-data:www-data . && chmod -R 775 .]
|
198
198
|
queue! %[cd #{deploy_to}/shared/tmp && chown -R www-data:www-data . && chmod -R 775 .]
|
199
199
|
queue! %[touch #{deploy_to}/current/tmp/restart.txt]
|
200
|
-
|
201
|
-
|
202
|
-
|
200
|
+
|
201
|
+
# apply defined permissions
|
202
|
+
chowns = conf.get('chown.'+env)
|
203
|
+
if chowns
|
204
|
+
chowns.each do |index, chown|
|
205
|
+
queue! %[cd #{deploy_to}/current/#{chown.get('path')} && chown -R chown.get('user') .]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# apply defined permissions
|
210
|
+
chgrps = conf.get('chgrp.'+env)
|
211
|
+
if chgrps
|
212
|
+
chgrps.each do |index, chgrp|
|
213
|
+
queue! %[cd #{deploy_to}/current/#{chgrp.get('path')} && chgrp -R chgrp.get('group') .]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# apply defined permissions
|
218
|
+
chmods = conf.get('chmod.'+env)
|
219
|
+
if chmods
|
220
|
+
chmods.each do |index, chmod|
|
221
|
+
queue! %[cd #{deploy_to}/current/#{chmod.get('path')} && chmod -R chmod.get('mode') .]
|
222
|
+
end
|
203
223
|
end
|
204
224
|
|
205
225
|
queue! %[a2ensite "#{vhost}"]
|
data/skel/base/lib/conf.rb
CHANGED
@@ -14,7 +14,7 @@ class Conf
|
|
14
14
|
|
15
15
|
def initialize(new_hash = nil, options = {})
|
16
16
|
raise "New hash must be of type Hash" if new_hash && new_hash.class.name != 'Hash'
|
17
|
-
@options = {use_fallbacks: true}.merge
|
17
|
+
@options = {use_fallbacks: true}.merge options
|
18
18
|
@loaded_paths = []
|
19
19
|
@paths = {}
|
20
20
|
@config_hashes = {}
|
@@ -29,7 +29,7 @@ class Conf
|
|
29
29
|
else
|
30
30
|
raise "add_path only accepts stings or hashes"
|
31
31
|
end
|
32
|
-
@paths.merge
|
32
|
+
@paths = @paths.merge path_hash
|
33
33
|
self
|
34
34
|
end
|
35
35
|
|
@@ -57,7 +57,7 @@ class Conf
|
|
57
57
|
# create the other nodes
|
58
58
|
if options and options.has_key? :root
|
59
59
|
fragment = fragment_base
|
60
|
-
nodes = options[:root].split
|
60
|
+
nodes = options[:root].split '.'
|
61
61
|
nodes.each_with_index do |node,i|
|
62
62
|
fragment[node] = i == nodes.length-1 ? @config_hashes[path] : {}
|
63
63
|
fragment = fragment[node]
|
@@ -67,7 +67,7 @@ class Conf
|
|
67
67
|
end
|
68
68
|
|
69
69
|
# output
|
70
|
-
out = out.merge
|
70
|
+
out = out.merge fragment_base
|
71
71
|
|
72
72
|
end
|
73
73
|
@compiled_hash = out
|
File without changes
|
@@ -1,22 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
db_dumps
|
8
|
-
tmp/*
|
9
|
-
composer.phar
|
1
|
+
/.bundle
|
2
|
+
/vendor
|
3
|
+
/bin
|
4
|
+
/logs/*
|
5
|
+
/backups/*
|
6
|
+
/db_dumps
|
10
7
|
|
11
|
-
#
|
12
|
-
public/
|
13
|
-
public/
|
14
|
-
public/
|
15
|
-
public/assets/*
|
16
|
-
public/bootstrap_forms
|
17
|
-
public/cms
|
18
|
-
public/framework
|
19
|
-
public/html5
|
20
|
-
public/widgets
|
21
|
-
public/compass
|
22
|
-
composer.phar
|
8
|
+
# project ignores - might need review
|
9
|
+
/public/sites/*/files
|
10
|
+
/public/sites/*/private
|
11
|
+
/public/sites/all/modules/filemanager/files
|
@@ -1,31 +1,5 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
"symfony/yaml" : "2.3.*@dev",
|
5
|
-
"silverstripe/framework" : "3.1.*@dev",
|
6
|
-
"silverstripe/cms" : "3.1.*@dev",
|
7
|
-
"silverstripe-themes/simple" : "dev-master",
|
8
|
-
"silverstripe/installer" : "3.1.*@dev",
|
9
|
-
"silverstripe/bootstrap-forms" : "dev-master",
|
10
|
-
"silverstripe/html5" : "dev-master",
|
11
|
-
"silverstripe/widgets" : "dev-master",
|
12
|
-
"silverstripe/compass" : "dev-master"
|
13
|
-
},
|
14
|
-
"extra": {
|
15
|
-
"installer-paths": {
|
16
|
-
"public/vendor/{$name}": [
|
17
|
-
],
|
18
|
-
"public/themes/{$name}": [
|
19
|
-
"silverstripe-themes/simple"
|
20
|
-
],
|
21
|
-
"public/{$name}": [
|
22
|
-
"silverstripe/framework",
|
23
|
-
"silverstripe/cms",
|
24
|
-
"silverstripe/bootstrap-forms",
|
25
|
-
"silverstripe/html5",
|
26
|
-
"silverstripe/widgets",
|
27
|
-
"silverstripe/compass"
|
28
|
-
]
|
2
|
+
"require": {
|
3
|
+
"symfony/yaml" : "2.3.*@dev"
|
29
4
|
}
|
30
|
-
}
|
31
5
|
}
|