platinum-deployer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exe/platinum +434 -0
- data/exe/platinum-appicon +90 -0
- data/exe/platinum-ios-simulate.js +48 -0
- data/lib/platinum/deployer/version.rb +5 -0
- data/lib/platinum/deployer.rb +7 -0
- data/platinum-deployer.gemspec +51 -0
- metadata +231 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1d93c0ff746f86415591668c7d73e2b9a364eb08
|
4
|
+
data.tar.gz: 4a5e0a74f37e8709bc47438562206d15321c927a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19c142c1128870beda5c0cccf98296ec774daa2137a6b79111d45d684a677b80acde872041da6b4e276241c084a41e2a3c7d4169c6bbe44399180def40509924
|
7
|
+
data.tar.gz: a7b6f6bb412f5b96c4618cf527e6c87e7eecec524e64e1bfd16d19d0e56bd1b2bf70cac091d29651a8f6b0e9cf9b99abfad1ab1d44a381300be975d2831cd14c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 MacKinley Smith
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Platinum::Deployer
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/platinum/deployer`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'platinum-deployer'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install platinum-deployer
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/platinum-deployer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
36
|
+
|
37
|
+
|
38
|
+
## License
|
39
|
+
|
40
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "platinum/deployer"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/exe/platinum
ADDED
@@ -0,0 +1,434 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'haml'
|
4
|
+
require 'yaml'
|
5
|
+
require 'json'
|
6
|
+
require 'deep_merge'
|
7
|
+
require 'open3'
|
8
|
+
require 'open4'
|
9
|
+
require 'git'
|
10
|
+
require 'awesome_print'
|
11
|
+
require 'colorize'
|
12
|
+
require 'pty'
|
13
|
+
require 'expect'
|
14
|
+
require 'highline/import'
|
15
|
+
|
16
|
+
@base_command = File.basename $0
|
17
|
+
help_banner = <<-HELP
|
18
|
+
Compiles CoffeeScript/HAML in ./app_src to JS/XML in ./app.
|
19
|
+
Developed by MacKinley Smith
|
20
|
+
|
21
|
+
Usage: #{@base_command} command
|
22
|
+
|
23
|
+
Commands:
|
24
|
+
|
25
|
+
#{@base_command} compile Compiles app_src files only.
|
26
|
+
#{@base_command} build Compiles app_src files and builds Titanium project.
|
27
|
+
#{@base_command} deploy Compiles and builds Titanium project, then deploys.
|
28
|
+
|
29
|
+
HELP
|
30
|
+
if ARGV.empty? or ARGV.include? '-h' or ARGV.include? '--help'
|
31
|
+
puts help_banner
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
@command = ARGV.shift
|
36
|
+
|
37
|
+
DEFAULT_OPTIONS = {
|
38
|
+
:app_name => 'CHANGEME',
|
39
|
+
:skip_compile => false,
|
40
|
+
:skip_build => false,
|
41
|
+
:titanium_command => {
|
42
|
+
:target => 'device',
|
43
|
+
:platform => 'android',
|
44
|
+
:output_dir => './dist'
|
45
|
+
},
|
46
|
+
:ios_credentials => {
|
47
|
+
:development => {
|
48
|
+
:provisioning_profile => nil,
|
49
|
+
:developer_certificate => nil
|
50
|
+
},
|
51
|
+
:production => {
|
52
|
+
:provisioning_profile => nil,
|
53
|
+
:developer_certificate => nil
|
54
|
+
}
|
55
|
+
},
|
56
|
+
:ios_simulator => {
|
57
|
+
:udid => nil
|
58
|
+
},
|
59
|
+
:testfairy => {
|
60
|
+
:api_key => nil,
|
61
|
+
:upload_url => 'http://app.testfairy.com/api/upload'
|
62
|
+
}
|
63
|
+
}
|
64
|
+
DEPLOYMENT_PLATFORMS = %w(ios android)
|
65
|
+
DEPLOYMENT_TARGETS =
|
66
|
+
%w( device emulator simulator dist-appstore dist-adhoc dist-playstore )
|
67
|
+
|
68
|
+
#
|
69
|
+
# Logging Methods
|
70
|
+
#
|
71
|
+
|
72
|
+
def fatal(msg)
|
73
|
+
$stderr.puts msg.red; $stderr.puts; exit 1 end
|
74
|
+
def warn(msg, nest_level=0)
|
75
|
+
$stderr.puts "#{' ' * nest_level * 2}> #{msg}".yellow end
|
76
|
+
def log_info(msg, nest_level=0)
|
77
|
+
$stdout.puts "#{' ' * nest_level * 2}> #{msg}".blue end
|
78
|
+
def log_success(msg, nest_level=0)
|
79
|
+
$stdout.puts "#{' ' * nest_level * 2}> #{msg}".green end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Helper Methods
|
83
|
+
#
|
84
|
+
|
85
|
+
def run_deploy_cmd(cmd)
|
86
|
+
# exit_status = nil
|
87
|
+
PTY.spawn(cmd) do |reader, writer|
|
88
|
+
Signal.trap('INT') do
|
89
|
+
puts; puts
|
90
|
+
warn 'Shutdown signal received.'
|
91
|
+
warn 'Shutting down ios-deploy...'
|
92
|
+
writer.puts 'kill'
|
93
|
+
writer.puts 'safequit'
|
94
|
+
sleep 3
|
95
|
+
fatal 'Process Interrupted'
|
96
|
+
end
|
97
|
+
while (line=reader.gets)
|
98
|
+
puts line
|
99
|
+
end
|
100
|
+
end
|
101
|
+
# exit_status = io.value
|
102
|
+
# exit_status.success?
|
103
|
+
true
|
104
|
+
rescue => e; warn e.message; false end
|
105
|
+
|
106
|
+
def run_titanium_cmd(cmd)
|
107
|
+
exit_status = nil
|
108
|
+
Open3.popen2e(cmd) do |i, oe, thread|
|
109
|
+
oe.each {|line| puts line }
|
110
|
+
exit_status = thread.value
|
111
|
+
end
|
112
|
+
exit_status.success?
|
113
|
+
rescue => e; warn e.message; false end
|
114
|
+
|
115
|
+
def bundle_path
|
116
|
+
path = File.join Dir.pwd, 'build'
|
117
|
+
case build_cmd_opts[:platform]
|
118
|
+
when 'ios'
|
119
|
+
path = File.join path, 'iphone', 'build'
|
120
|
+
debug_dir = case build_cmd_opts[:target]
|
121
|
+
when 'emulator', 'simulator' then 'Debug-iphonesimulator'
|
122
|
+
when 'device' then 'Debug-iphoneos'
|
123
|
+
end
|
124
|
+
path = File.join path, debug_dir, "#{@options[:app_name]}.app"
|
125
|
+
end
|
126
|
+
File.expand_path path
|
127
|
+
end
|
128
|
+
|
129
|
+
def deep_symbolize(obj)
|
130
|
+
return obj.inject({}){|memo, (k,v)|
|
131
|
+
memo[k.to_sym] = deep_symbolize(v); memo } if obj.is_a? Hash
|
132
|
+
return obj.inject([]){|memo, v|
|
133
|
+
memo << deep_symbolize(v); memo } if obj.is_a? Array
|
134
|
+
obj
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Option parsing
|
139
|
+
#
|
140
|
+
|
141
|
+
# Load config from a YAML file in the project root if available.
|
142
|
+
@config_filepath = File.join(Dir.pwd, 'compile_config.yml')
|
143
|
+
@defaults = DEFAULT_OPTIONS.dup
|
144
|
+
if File.exists? @config_filepath
|
145
|
+
loaded_config = deep_symbolize YAML::load_file(@config_filepath)
|
146
|
+
@defaults.deep_merge! loaded_config
|
147
|
+
end
|
148
|
+
|
149
|
+
# Parse options given to the command.
|
150
|
+
parsed_options = @defaults.dup
|
151
|
+
OptionParser.new do |opts|
|
152
|
+
opts.banner = help_banner
|
153
|
+
|
154
|
+
# platform_opts = DEPLOYMENT_PLATFORMS.join '|'
|
155
|
+
opts.on("-p", "--platform=platform",
|
156
|
+
'Deployment Platform') do |v|
|
157
|
+
if DEPLOYMENT_PLATFORMS.include?(v)
|
158
|
+
parsed_options[:titanium_command][:platform] = v
|
159
|
+
else fatal "Platform \"#{v}\" not recognized." end
|
160
|
+
end
|
161
|
+
|
162
|
+
# target_opts = DEPLOYMENT_TARGETS.join '|'
|
163
|
+
opts.on("-T", "--target=target",
|
164
|
+
'Deployment Target') do |v|
|
165
|
+
if DEPLOYMENT_TARGETS.include? v
|
166
|
+
platform = parsed_options[:titanium_command][:platform]
|
167
|
+
if v == 'emulator' && platform == 'ios' then v = 'simulator'
|
168
|
+
elsif v == 'simulator' && platform == 'android' then v = 'emulator' end
|
169
|
+
parsed_options[:titanium_command][:target] = v
|
170
|
+
else fatal "Target \"#{v}\" not recognized." end
|
171
|
+
end
|
172
|
+
|
173
|
+
opts.on('-O', '--output-dir=dir', 'Output Directory') do |v|
|
174
|
+
parsed_options[:titanium_command][:output_dir] = v
|
175
|
+
end
|
176
|
+
|
177
|
+
opts.on('-V', '--developer-certificate=certificate',
|
178
|
+
'iOS Developer Certificate') do |v|
|
179
|
+
parsed_options[:ios_credentials][:development][:developer_certificate] = v
|
180
|
+
parsed_options[:ios_credentials][:production][:developer_certificate] = v
|
181
|
+
end
|
182
|
+
|
183
|
+
opts.on('-P', '--provisioning-profile=profile',
|
184
|
+
'iOS Provisioning Profile') do |v|
|
185
|
+
parsed_options[:ios_credentials][:development][:provisioning_profile] = v
|
186
|
+
parsed_options[:ios_credentials][:production][:provisioning_profile] = v
|
187
|
+
end
|
188
|
+
|
189
|
+
opts.on('-U', '--simulator-udid=udid', 'iOS Simulator UDID') do |v|
|
190
|
+
parsed_options[:ios_simulator][:udid] = v
|
191
|
+
end
|
192
|
+
|
193
|
+
opts.on('--skip-compile', 'Skip Source Compilation') do
|
194
|
+
parsed_options[:skip_compile] = true end
|
195
|
+
opts.on('--skip-build', 'Skip Titanium Build') do
|
196
|
+
parsed_options[:skip_build] = true end
|
197
|
+
|
198
|
+
opts.on('--help', 'Prints this help') do
|
199
|
+
puts opts.banner
|
200
|
+
exit
|
201
|
+
end
|
202
|
+
end.parse!
|
203
|
+
@options = parsed_options
|
204
|
+
|
205
|
+
#
|
206
|
+
# Compilation Methods
|
207
|
+
#
|
208
|
+
|
209
|
+
def compile_source!
|
210
|
+
if @options[:skip_compile]; log_info 'Skipping compilation.'; return true end
|
211
|
+
puts; log_info 'Compiling project source...'
|
212
|
+
return false unless compile_coffeescript_files! && compile_haml_files!
|
213
|
+
log_success 'Compilation complete!'; true
|
214
|
+
end
|
215
|
+
def compile_coffeescript_files!
|
216
|
+
log_info 'Compiling CoffeeScript files...', 1
|
217
|
+
output = `coffee --output app --compile app_src 2>&1`.strip
|
218
|
+
if $? && output.length == 0
|
219
|
+
Dir.glob 'app/**/*.js' do |file|
|
220
|
+
output_path = file.dup
|
221
|
+
lines = File.readlines file
|
222
|
+
if file =~ /\.tss\.js$/
|
223
|
+
output_path = file.gsub(/.js$/, '')
|
224
|
+
File.unlink(file)
|
225
|
+
lines = lines[3..-4].map{|l| l[4..-1] }
|
226
|
+
elsif lines[0] =~ /^\/\/ Generated/
|
227
|
+
lines = lines[2..-3].map{|l| l[2..-1] }
|
228
|
+
if file =~ /^app\/controllers\// && !(file =~ /\/app\.js$/)
|
229
|
+
bc_line = lines.find{|l| l =~ /^exports\.baseController = / }
|
230
|
+
lines.unshift "exports.baseController = 'app';\n\n" if bc_line.nil?
|
231
|
+
end
|
232
|
+
else next end
|
233
|
+
File.open(output_path, 'w') {|f| f.write lines.join }
|
234
|
+
end
|
235
|
+
log_success 'CoffeeScript files compiled successfully!', 1; true
|
236
|
+
else
|
237
|
+
warn output, 1; fatal 'CoffeeScript compilation failed!'
|
238
|
+
end
|
239
|
+
rescue => e
|
240
|
+
warn e.message, 1; fatal 'CoffeeScript compilation failed!'; false
|
241
|
+
end
|
242
|
+
def compile_haml_files!
|
243
|
+
log_info 'Compiling HAML files...', 1
|
244
|
+
Dir.glob 'app_src/**/*.haml' do |file|
|
245
|
+
contents = File.read file
|
246
|
+
doc = Haml::Engine.new(contents)
|
247
|
+
output_path = file.gsub(/^app_src/, 'app').gsub(/haml$/, 'xml')
|
248
|
+
File.open(output_path, 'w') {|f| f.write doc.render }
|
249
|
+
end
|
250
|
+
log_success 'HAML files compiled successfully!', 1; true
|
251
|
+
rescue => e
|
252
|
+
warn e.message, 1; fatal 'HAML compilation failed!'; false
|
253
|
+
end
|
254
|
+
|
255
|
+
#
|
256
|
+
# Build Methods
|
257
|
+
#
|
258
|
+
|
259
|
+
def build!
|
260
|
+
if @options[:skip_compile]; log_info 'Skipping build.'; return true end
|
261
|
+
puts; log_info 'Building Titanium project...'; puts
|
262
|
+
build_success = case build_cmd_opts[:target]
|
263
|
+
when 'device' then build_for_device!
|
264
|
+
when 'emulator', 'simulator' then build_for_emulator!
|
265
|
+
when 'dist-appstore', 'dist-adhoc' then build_for_production!
|
266
|
+
else fatal "Unknown build target: #{@options[:titanium_command][:target]}"
|
267
|
+
end
|
268
|
+
puts
|
269
|
+
fatal('Failed to build Titanium project!') unless build_success
|
270
|
+
log_success 'Titanium project built successfully!'; puts; true
|
271
|
+
end
|
272
|
+
def build_for_emulator!
|
273
|
+
run_titanium_cmd "#{base_build_cmd} -T #{build_cmd_opts[:target]}"; end
|
274
|
+
def build_for_device!
|
275
|
+
cmd = "#{base_build_cmd} -T device"
|
276
|
+
case build_cmd_opts[:platform]
|
277
|
+
when 'ios'
|
278
|
+
creds = @options[:ios_credentials][:development]
|
279
|
+
unless creds[:developer_certificate].nil?
|
280
|
+
cmd << " -V \"#{creds[:developer_certificate]}\""; end
|
281
|
+
unless creds[:provisioning_profile].nil?
|
282
|
+
cmd << " -P \"#{creds[:provisioning_profile]}\""; end
|
283
|
+
end
|
284
|
+
run_titanium_cmd cmd
|
285
|
+
end
|
286
|
+
def build_for_production!
|
287
|
+
cmd = "#{base_build_cmd} -T #{build_cmd_opts[:target]}"
|
288
|
+
case build_cmd_opts[:platform]
|
289
|
+
when 'ios'
|
290
|
+
cmd << " -O #{build_cmd_opts[:output_dir]}"
|
291
|
+
creds = @options[:ios_credentials][:production]
|
292
|
+
unless creds[:developer_certificate].nil?
|
293
|
+
cmd << " -R \"#{creds[:developer_certificate]}\""; end
|
294
|
+
unless creds[:provisioning_profile].nil?
|
295
|
+
cmd << " -P \"#{creds[:provisioning_profile]}\""; end
|
296
|
+
end
|
297
|
+
run_titanium_cmd cmd
|
298
|
+
end
|
299
|
+
def build_cmd_opts; @options[:titanium_command]; end
|
300
|
+
def base_build_cmd
|
301
|
+
'titanium build --build-only --log-level warn' +
|
302
|
+
" --platform #{build_cmd_opts[:platform]}"
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# Deployment Methods
|
307
|
+
#
|
308
|
+
|
309
|
+
def deploy!
|
310
|
+
puts; log_info 'Deploying application...'; puts
|
311
|
+
deploy_success = case build_cmd_opts[:target]
|
312
|
+
when 'device' then deploy_to_device!
|
313
|
+
when 'emulator', 'simulator' then deploy_to_emulator!
|
314
|
+
when 'dist-adhoc' then deploy_to_testfairy!
|
315
|
+
when 'dist-appstore' then build_for_production!
|
316
|
+
else fatal "Unknown deploy target: #{@options[:titanium_command][:target]}"
|
317
|
+
end
|
318
|
+
puts
|
319
|
+
fatal('Failed to deploy application!') unless deploy_success
|
320
|
+
log_success 'Application deployed successfully!'; puts; true
|
321
|
+
end
|
322
|
+
def deploy_to_emulator!
|
323
|
+
sim_opts = @options[:ios_simulator]
|
324
|
+
path_to_sim_script = File.expand_path(
|
325
|
+
File.join(__dir__, 'platinum-ios-simulate.js'))
|
326
|
+
base_cmd = "node #{path_to_sim_script}"
|
327
|
+
if sim_opts[:udid].nil?
|
328
|
+
json_sim_list = `#{base_cmd} command=list 2>&1`.strip
|
329
|
+
begin sim_list = JSON.parse json_sim_list
|
330
|
+
rescue => e; fatal e.message; end
|
331
|
+
# ap sim_list; puts
|
332
|
+
sim_choices = {}
|
333
|
+
sim_list.each {|ios_version, simulators|
|
334
|
+
simulators.each {|s|
|
335
|
+
sim_choices[s['udid']] = "#{s['name']} running iOS #{ios_version}" } }
|
336
|
+
if sim_choices.keys.any?
|
337
|
+
choose do |menu|
|
338
|
+
menu.header = "Installed iOS Simulators"
|
339
|
+
menu.prompt = "Please choose a simulator to deploy to: "
|
340
|
+
|
341
|
+
sim_choices.each {|udid, name|
|
342
|
+
menu.choice(name) {|choice| sim_opts[:udid] = udid } }
|
343
|
+
end
|
344
|
+
else
|
345
|
+
fatal 'You have no iOS simulators installed.'
|
346
|
+
end
|
347
|
+
end
|
348
|
+
cmd = "#{base_cmd} command=launch appPath=#{bundle_path}"
|
349
|
+
cmd << " simUDID=#{sim_opts[:udid]}"
|
350
|
+
system cmd
|
351
|
+
end
|
352
|
+
def deploy_to_device!
|
353
|
+
cmd = "ios-deploy --debug --bundle #{bundle_path}"
|
354
|
+
# system cmd
|
355
|
+
# run_titanium_cmd cmd
|
356
|
+
run_deploy_cmd cmd
|
357
|
+
end
|
358
|
+
|
359
|
+
# Testfairy integration
|
360
|
+
def deploy_to_testfairy!
|
361
|
+
puts; log_info 'Preparing to upload to TestFairy...'
|
362
|
+
exit_status = nil; str_output = ''
|
363
|
+
curl_options = ['curl', '-sSf', "#{@options[:testfairy][:upload_url]}"]
|
364
|
+
form_fields = testfairy_form_data.flat_map { |k, v| ['-F', "#{k}=#{v}"] }
|
365
|
+
log_info 'Uploading IPA to TestFairy...'
|
366
|
+
Open3.popen2e(*(curl_options + form_fields)) do |stdin, stdout_err, wait_thr|
|
367
|
+
while line = stdout_err.gets; str_output << line end
|
368
|
+
exit_status = wait_thr.value
|
369
|
+
end
|
370
|
+
log_success 'Upload completed!'
|
371
|
+
json_output = JSON.parse str_output
|
372
|
+
puts; ap json_output
|
373
|
+
return unless exit_status.success? && json_output['status'] == 'ok'
|
374
|
+
invite_url = json_output['invite_testers_url']
|
375
|
+
`open -a /Applications/Google\\ Chrome.app #{invite_url}`
|
376
|
+
true
|
377
|
+
rescue => e
|
378
|
+
warn e.message; false
|
379
|
+
end
|
380
|
+
def testfairy_form_data
|
381
|
+
tf_opts = @options[:testfairy]
|
382
|
+
fatal('TestFairy API Key required!') unless tf_opts[:api_key]
|
383
|
+
file = File.join 'dist', "#{@options[:app_name]}.ipa"
|
384
|
+
fatal("File #{file} does not exist!") unless File.exists? file
|
385
|
+
{}.tap do |fields|
|
386
|
+
fields[:file] = "@#{file}" if file
|
387
|
+
fields[:api_key] = tf_opts[:api_key]
|
388
|
+
fields[:comment] = if tf_opts[:comment] then tf_opts[:comment]
|
389
|
+
else attach_tf_comment_from_git end
|
390
|
+
|
391
|
+
# Optional stuff we aren't using... yet.
|
392
|
+
fields[:symbols_file] = tf_opts[:symbols_file] if tf_opts[:symbols_file]
|
393
|
+
fields[:testers_groups] = tf_opts[:testers_groups] if tf_opts[:testers_groups]
|
394
|
+
fields[:metrics] = tf_opts[:metrics] if tf_opts[:metrics]
|
395
|
+
fields[:"max-duration"] = tf_opts[:max_duration] if tf_opts[:max_duration]
|
396
|
+
fields[:video] = tf_opts[:video] if tf_opts[:video]
|
397
|
+
fields[:"video-quality"] = tf_opts[:video_quality] if tf_opts[:video_quality]
|
398
|
+
fields[:"video-rate"] = tf_opts[:video_rate] if tf_opts[:video_rate]
|
399
|
+
fields[:"icon-watermark"] = tf_opts[:icon_watermark] if tf_opts[:icon_watermark]
|
400
|
+
fields[:"auto-update"] = tf_opts[:auto_update] if tf_opts[:auto_update]
|
401
|
+
fields[:notify] = tf_opts[:notify] if tf_opts[:notify]
|
402
|
+
end
|
403
|
+
end
|
404
|
+
def attach_tf_comment_from_git
|
405
|
+
git = Git.open '.'
|
406
|
+
git.log.first.message
|
407
|
+
end
|
408
|
+
def force_git_commit!
|
409
|
+
git = Git.open '.'
|
410
|
+
status = git.status
|
411
|
+
change_count = status.changed.count + status.added.count +
|
412
|
+
status.deleted.count + status.untracked.count
|
413
|
+
if change_count > 0
|
414
|
+
# Force a commit
|
415
|
+
puts
|
416
|
+
unless system 'git add .; git commit'
|
417
|
+
fatal('You must commit your work before deploying to TestFairy.') end
|
418
|
+
puts
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
if @command
|
423
|
+
case @command
|
424
|
+
when 'compile' then compile_source!
|
425
|
+
when 'build' then build! if compile_source!
|
426
|
+
when 'deploy'
|
427
|
+
force_git_commit! if build_cmd_opts[:target] =~ /^dist/
|
428
|
+
deploy! if compile_source! && build!
|
429
|
+
else fatal "Command not recognized: #{@command}"
|
430
|
+
end
|
431
|
+
exit 0
|
432
|
+
end
|
433
|
+
|
434
|
+
fatal 'You must specify a command.'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'colorize'
|
5
|
+
require 'awesome_print'
|
6
|
+
require 'highline/import'
|
7
|
+
|
8
|
+
@base_command = File.basename $0
|
9
|
+
help_banner = <<-HELP
|
10
|
+
Renames icons generated by Michael Flarup's App Icon Template for use with
|
11
|
+
Appcelerator Titanium.
|
12
|
+
Developed by MacKinley Smith
|
13
|
+
|
14
|
+
Usage: #{@base_command}
|
15
|
+
|
16
|
+
HELP
|
17
|
+
|
18
|
+
DEFAULT_OPTIONS = {
|
19
|
+
:working_dir => 'app/assets/iphone',
|
20
|
+
:dry_run => false
|
21
|
+
}
|
22
|
+
@defaults = DEFAULT_OPTIONS.dup
|
23
|
+
parsed_options = @defaults.dup
|
24
|
+
OptionParser.new do |opts|
|
25
|
+
opts.banner = help_banner
|
26
|
+
|
27
|
+
opts.on('--dry-run', 'Dry run') { parsed_options[:dry_run] = true }
|
28
|
+
opts.on('--help', 'Prints this help') do
|
29
|
+
puts opts.banner
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
@options = parsed_options
|
34
|
+
|
35
|
+
#
|
36
|
+
# Logging Methods
|
37
|
+
#
|
38
|
+
|
39
|
+
def fatal(msg)
|
40
|
+
$stderr.puts msg.red; $stderr.puts; exit 1 end
|
41
|
+
def warn(msg, nest_level=0)
|
42
|
+
$stderr.puts "#{' ' * nest_level * 2}> #{msg}".yellow end
|
43
|
+
def log_info(msg, nest_level=0)
|
44
|
+
$stdout.puts "#{' ' * nest_level * 2}> #{msg}".blue end
|
45
|
+
def log_success(msg, nest_level=0)
|
46
|
+
$stdout.puts "#{' ' * nest_level * 2}> #{msg}".green end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Helper Methods
|
50
|
+
#
|
51
|
+
|
52
|
+
def escape_glob(path); path.gsub(/([\[\]\{\}\*\?\\])/, '\\\\\1') end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Main App
|
56
|
+
#
|
57
|
+
|
58
|
+
dest_dir = File.expand_path File.join( __dir__, @options[:working_dir] )
|
59
|
+
output_dir = false
|
60
|
+
dir_matcher = File.expand_path File.join( __dir__,
|
61
|
+
@options[:working_dir], 'App\ Icon\ \[*' )
|
62
|
+
matching_dirs = Dir.glob dir_matcher
|
63
|
+
case matching_dirs.length
|
64
|
+
when 0
|
65
|
+
fatal "No app icon export directories found in #{@options[:working_dir]}!"
|
66
|
+
when 1 then output_dir = matching_dirs[0]
|
67
|
+
else
|
68
|
+
warn "Multiple app icon export directories found in #{@options[:working_dir]}!"
|
69
|
+
choose do |menu|
|
70
|
+
menu.prompt = "Please choose one: "
|
71
|
+
matching_dirs.each {|d| menu.choice(d) {|choice| output_dir = choice } }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
output_dir_glob = escape_glob output_dir
|
75
|
+
|
76
|
+
generated_images = Dir.glob File.join(output_dir_glob, '*.png')
|
77
|
+
generated_images.each_with_index do |f, i|
|
78
|
+
name = File.basename f
|
79
|
+
next unless name =~ /^Icon/
|
80
|
+
new_name = 'appi' + name[1..-1]
|
81
|
+
new_path = f.gsub name, new_name
|
82
|
+
if @options[:dry_run] then log_info "#{name} would be renamed to #{new_name}"
|
83
|
+
else File.rename(f, new_path) end
|
84
|
+
generated_images[i] = new_path
|
85
|
+
end
|
86
|
+
|
87
|
+
unless @options[:dry_run]
|
88
|
+
FileUtils.move generated_images, dest_dir, verbose: true
|
89
|
+
FileUtils.rm_rf output_dir, verbose: true
|
90
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
module.paths.push('/usr/local/lib/node_modules');
|
4
|
+
var ioslib = require('ioslib');
|
5
|
+
|
6
|
+
var command = 'list',
|
7
|
+
simUDID = null, // string or null to pick a simulator
|
8
|
+
appPath = null;
|
9
|
+
|
10
|
+
process.argv.slice(2).forEach(function(val, index, array) {
|
11
|
+
if (val.indexOf('=')>-1) {
|
12
|
+
var split_val = val.split('=');
|
13
|
+
var k = split_val[0], v = split_val[1];
|
14
|
+
if (k == 'command') command = v;
|
15
|
+
else if (k == 'simUDID') simUDID = v;
|
16
|
+
else if (k == 'appPath') appPath = v;
|
17
|
+
}
|
18
|
+
});
|
19
|
+
|
20
|
+
if (command == 'list') {
|
21
|
+
ioslib.detect(function(err, info){
|
22
|
+
if (err) {
|
23
|
+
console.error(err);
|
24
|
+
process.exit(1);
|
25
|
+
} else console.log(JSON.stringify(info.simulators.ios));
|
26
|
+
});
|
27
|
+
} else if (command == 'launch') {
|
28
|
+
if (appPath == null) {
|
29
|
+
console.error('You must specify a path to an app bundle!');
|
30
|
+
process.exit(1);
|
31
|
+
} else {
|
32
|
+
ioslib.simulator.launch(simUDID, {
|
33
|
+
appPath: appPath
|
34
|
+
}).on('launched', function (msg) {
|
35
|
+
console.log('Simulator has launched');
|
36
|
+
}).on('appStarted', function (msg) {
|
37
|
+
console.log('App has started');
|
38
|
+
}).on('log', function (msg) {
|
39
|
+
console.log('[LOG] ' + msg);
|
40
|
+
}).on('error', function (err) {
|
41
|
+
console.error(err);
|
42
|
+
process.exit(1);
|
43
|
+
});
|
44
|
+
}
|
45
|
+
} else {
|
46
|
+
console.error("Command \"" + command + "\" not recognized.");
|
47
|
+
process.exit(1);
|
48
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'platinum/deployer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "platinum-deployer"
|
8
|
+
spec.version = Platinum::Deployer::VERSION
|
9
|
+
spec.authors = ["MacKinley Smith"]
|
10
|
+
spec.email = ["smithmackinley@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = 'Platinum Deployer'
|
13
|
+
spec.description = 'Deploys Platinum projects to simulators, devices, and more.'
|
14
|
+
# spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
15
|
+
spec.homepage = 'http://rubygems.org/gems/platinum-deployer'
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
19
|
+
# delete this section to allow pushing this gem to any host.
|
20
|
+
# if spec.respond_to?(:metadata)
|
21
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
22
|
+
# else
|
23
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
24
|
+
# end
|
25
|
+
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
# spec.files = Dir["lib/**/*", "spec/**/*", "bin/*"]
|
28
|
+
spec.bindir = "exe"
|
29
|
+
# spec.bindir = "bin"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
35
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
36
|
+
spec.add_development_dependency "rspec"
|
37
|
+
|
38
|
+
# spec.add_dependency 'optparse'
|
39
|
+
spec.add_dependency 'haml'
|
40
|
+
# spec.add_dependency 'yaml'
|
41
|
+
spec.add_dependency 'json'
|
42
|
+
spec.add_dependency 'deep_merge'
|
43
|
+
# spec.add_dependency 'open3'
|
44
|
+
spec.add_dependency 'open4'
|
45
|
+
spec.add_dependency 'git'
|
46
|
+
spec.add_dependency 'awesome_print'
|
47
|
+
spec.add_dependency 'colorize'
|
48
|
+
# spec.add_dependency 'pty'
|
49
|
+
spec.add_dependency 'expect'
|
50
|
+
spec.add_dependency 'highline'
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: platinum-deployer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MacKinley Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-07 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.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: haml
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
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: json
|
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: deep_merge
|
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: open4
|
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
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: git
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: awesome_print
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: colorize
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: expect
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: highline
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
description: Deploys Platinum projects to simulators, devices, and more.
|
182
|
+
email:
|
183
|
+
- smithmackinley@gmail.com
|
184
|
+
executables:
|
185
|
+
- platinum
|
186
|
+
- platinum-appicon
|
187
|
+
- platinum-ios-simulate.js
|
188
|
+
extensions: []
|
189
|
+
extra_rdoc_files: []
|
190
|
+
files:
|
191
|
+
- ".gitignore"
|
192
|
+
- ".rspec"
|
193
|
+
- ".travis.yml"
|
194
|
+
- CODE_OF_CONDUCT.md
|
195
|
+
- Gemfile
|
196
|
+
- LICENSE.txt
|
197
|
+
- README.md
|
198
|
+
- Rakefile
|
199
|
+
- bin/console
|
200
|
+
- bin/setup
|
201
|
+
- exe/platinum
|
202
|
+
- exe/platinum-appicon
|
203
|
+
- exe/platinum-ios-simulate.js
|
204
|
+
- lib/platinum/deployer.rb
|
205
|
+
- lib/platinum/deployer/version.rb
|
206
|
+
- platinum-deployer.gemspec
|
207
|
+
homepage: http://rubygems.org/gems/platinum-deployer
|
208
|
+
licenses:
|
209
|
+
- MIT
|
210
|
+
metadata: {}
|
211
|
+
post_install_message:
|
212
|
+
rdoc_options: []
|
213
|
+
require_paths:
|
214
|
+
- lib
|
215
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ">="
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '0'
|
225
|
+
requirements: []
|
226
|
+
rubyforge_project:
|
227
|
+
rubygems_version: 2.4.8
|
228
|
+
signing_key:
|
229
|
+
specification_version: 4
|
230
|
+
summary: Platinum Deployer
|
231
|
+
test_files: []
|