shenzhen 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +19 -0
- data/README.md +59 -0
- data/Rakefile +10 -0
- data/bin/ipa +20 -0
- data/lib/shenzhen.rb +6 -0
- data/lib/shenzhen/agvtool.rb +17 -0
- data/lib/shenzhen/commands.rb +7 -0
- data/lib/shenzhen/commands/build.rb +101 -0
- data/lib/shenzhen/commands/distribute.rb +1 -0
- data/lib/shenzhen/plugins/testflight.rb +104 -0
- data/lib/shenzhen/xcodebuild.rb +63 -0
- data/shenzhen.gemspec +27 -0
- metadata +131 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
shenzhen (0.0.1)
|
5
|
+
commander (~> 4.1.2)
|
6
|
+
faraday (~> 0.8.0)
|
7
|
+
faraday_middleware (~> 0.8.7)
|
8
|
+
json (~> 1.7.3)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
commander (4.1.2)
|
14
|
+
highline (~> 1.6.11)
|
15
|
+
faraday (0.8.1)
|
16
|
+
multipart-post (~> 1.1)
|
17
|
+
faraday_middleware (0.8.7)
|
18
|
+
faraday (>= 0.7.4, < 0.9)
|
19
|
+
highline (1.6.15)
|
20
|
+
json (1.7.5)
|
21
|
+
multipart-post (1.1.5)
|
22
|
+
rake (0.9.2.2)
|
23
|
+
rspec (0.6.4)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
rake (~> 0.9.2)
|
30
|
+
rspec (~> 0.6.1)
|
31
|
+
shenzhen!
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012 Mattt Thompson (http://mattt.me/)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Shenzhen
|
2
|
+
**CLI for Building & Distributing iOS Apps (.ipa Files)**
|
3
|
+
|
4
|
+
Create `.ipa` files and then distribute them to TestFlight, all from the command line!
|
5
|
+
|
6
|
+
Less cumbersome than clicking around in Xcode, and less hassle than rolling your own build script--Shenzhen radically improves the process of getting new builds out to testers and enterprises.
|
7
|
+
|
8
|
+
This project is starting with TestFlight, but will move to support other popular distribution methods, such as S3, CloudApp, and /or Dropbox. Suggestions (and pull requests) are very welcome.
|
9
|
+
|
10
|
+
> `shenzhen` is named for [深圳](http://en.wikipedia.org/wiki/Shenzhen), the Chinese city famous for its role as the center of manufacturing for a majority of consumer electronics, including iPhones and iPads. Its [sister project](https://github.com/mattt/cupertino)'s namesake, [Cupertino, CA](http://en.wikipedia.org/wiki/Cupertino,_California), is home to Apple, Inc.'s world headquarters.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem install shenzhen
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Shenzhen adds the `ipa` command to your PATH,
|
21
|
+
|
22
|
+
```
|
23
|
+
$ ipa
|
24
|
+
|
25
|
+
Build and distribute iOS apps (.ipa files)
|
26
|
+
|
27
|
+
Commands:
|
28
|
+
build Create a new .ipa file for your app
|
29
|
+
distribute:testflight Distribute an .ipa file over testflight
|
30
|
+
help Display global or [command] help documentation.
|
31
|
+
|
32
|
+
Aliases:
|
33
|
+
distribute distribute:testflight
|
34
|
+
|
35
|
+
Global Options:
|
36
|
+
-h, --help Display help documentation
|
37
|
+
-v, --version Display version information
|
38
|
+
-t, --trace Display backtrace when an error occurs
|
39
|
+
```
|
40
|
+
|
41
|
+
### Building & Distribution
|
42
|
+
|
43
|
+
```
|
44
|
+
$ cd /path/to/iOS Project/
|
45
|
+
$ ipa build
|
46
|
+
$ ipa distribute
|
47
|
+
```
|
48
|
+
|
49
|
+
## Contact
|
50
|
+
|
51
|
+
Mattt Thompson
|
52
|
+
|
53
|
+
- http://github.com/mattt
|
54
|
+
- http://twitter.com/mattt
|
55
|
+
- m@mattt.me
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
Shenzhen is available under the MIT license. See the LICENSE file for more info.
|
data/Rakefile
ADDED
data/bin/ipa
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'commander/import'
|
4
|
+
|
5
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
6
|
+
require 'shenzhen'
|
7
|
+
|
8
|
+
HighLine.track_eof = false # Fix for built-in Ruby
|
9
|
+
|
10
|
+
program :version, Shenzhen::VERSION
|
11
|
+
program :description, 'Build and distribute iOS apps (.ipa files)'
|
12
|
+
|
13
|
+
program :help, 'Author', 'Mattt Thompson <m@mattt.me>'
|
14
|
+
program :help, 'Website', 'http://mattt.me'
|
15
|
+
program :help_formatter, :compact
|
16
|
+
|
17
|
+
# global_option '--verbose'
|
18
|
+
default_command :help
|
19
|
+
|
20
|
+
require 'shenzhen/commands'
|
data/lib/shenzhen.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Shenzhen::Agvtool
|
2
|
+
class << self
|
3
|
+
def what_version
|
4
|
+
output = `agvtool what-version -terse`
|
5
|
+
output.length > 0 ? output : nil
|
6
|
+
end
|
7
|
+
|
8
|
+
alias :vers :what_version
|
9
|
+
|
10
|
+
def what_marketing_version
|
11
|
+
output = `agvtool what-marketing-version -terse`
|
12
|
+
output.scan(/\=(.+)$/).flatten.first
|
13
|
+
end
|
14
|
+
|
15
|
+
alias :mvers :what_marketing_version
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
command :build do |c|
|
2
|
+
c.syntax = 'ipa build [options] [output]'
|
3
|
+
c.summary = 'Create a new .ipa file for your app'
|
4
|
+
c.description = ''
|
5
|
+
|
6
|
+
c.example 'description', 'ipa release 478 --tag 3.7.2 --scheme MyApp'
|
7
|
+
c.option '-w', '--workspace WORKSPACE', 'Workspace (.xcworkspace) file to use to build app (automatically detected in current directory)'
|
8
|
+
c.option '-p', '--project PROJECT', 'Project (.xcodeproj) file to use to build app (automatically detected in current directory, overridden by --workspace option, if passed)'
|
9
|
+
c.option '-c', '--configuration CONFIGURATION', 'Configuration used to build'
|
10
|
+
c.option '-s', '--scheme SCHEME', 'Scheme used to build app'
|
11
|
+
c.option '-q', '--quiet', 'Silence warning and success messages'
|
12
|
+
|
13
|
+
c.action do |args, options|
|
14
|
+
validate_xcode_version!
|
15
|
+
|
16
|
+
@xcodebuild_info = Shenzhen::XcodeBuild.info
|
17
|
+
|
18
|
+
@workspace = options.workspace
|
19
|
+
@project = options.project
|
20
|
+
@scheme = options.scheme
|
21
|
+
@configuration = options.configuration
|
22
|
+
|
23
|
+
determine_workspace_or_project! unless @workspace || @project
|
24
|
+
|
25
|
+
determine_configuration! unless @configuration
|
26
|
+
say_error "Configuration #{@configuration} not found" and abort unless @xcodebuild_info.build_configurations.include?(@configuration)
|
27
|
+
|
28
|
+
determine_scheme! unless @scheme
|
29
|
+
say_error "Scheme #{@scheme} not found" and abort unless @xcodebuild_info.schemes.include?(@scheme)
|
30
|
+
|
31
|
+
say_warning "Building \"#{@workspace || @project}\" with Scheme \"#{@scheme}\" and Configuration \"#{@configuration}\"\n" unless options.quiet
|
32
|
+
|
33
|
+
log "xcodebuild", (@workspace || @project)
|
34
|
+
|
35
|
+
flags = []
|
36
|
+
flags << "-sdk iphoneos"
|
37
|
+
flags << "-workspace '#{@workspace}'" if @workspace
|
38
|
+
flags << "-project '#{@project}'" if @project
|
39
|
+
flags << "-scheme '#{@scheme}'" if @scheme
|
40
|
+
flags << "-configuration Release"
|
41
|
+
|
42
|
+
ENV['CC'] = nil # Fix for RVM
|
43
|
+
abort unless system "xcodebuild #{flags.join(' ')} clean build 1> /dev/null"
|
44
|
+
|
45
|
+
log "xcrun", "PackageApplication"
|
46
|
+
|
47
|
+
@xcodebuild_settings = Shenzhen::XcodeBuild.settings(flags)
|
48
|
+
|
49
|
+
@app_path = File.join(@xcodebuild_settings['BUILT_PRODUCTS_DIR'], @xcodebuild_settings['PRODUCT_NAME']) + ".app"
|
50
|
+
@dsym_path = @app_path + ".dSYM"
|
51
|
+
@ipa_path = File.join(Dir.pwd, @xcodebuild_settings['PRODUCT_NAME']) + ".ipa"
|
52
|
+
abort unless system %{xcrun -sdk iphoneos PackageApplication -v "#{@app_path}" -o "#{@ipa_path}" --embed "#{@dsym_path}" 1> /dev/null}
|
53
|
+
|
54
|
+
say_ok "#{File.basename(@ipa_path)} successfully built" unless options.quiet
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def validate_xcode_version!
|
60
|
+
version = Shenzhen::XcodeBuild.version
|
61
|
+
say_error "Shenzhen requires Xcode 4 (found #{version}). Please install or switch to the latest Xcode." and abort if version < "4.0.0"
|
62
|
+
end
|
63
|
+
|
64
|
+
def determine_workspace_or_project!
|
65
|
+
workspaces, projects = Dir["*.xcworkspace"], Dir["*.xcodeproj"]
|
66
|
+
|
67
|
+
if workspaces.empty?
|
68
|
+
if projects.empty?
|
69
|
+
say_error "No Xcode projects or workspaces found in current directory" and abort
|
70
|
+
else
|
71
|
+
if projects.length == 1
|
72
|
+
@project = projects.first
|
73
|
+
else
|
74
|
+
@project = choose "Select a project:", *projects
|
75
|
+
end
|
76
|
+
end
|
77
|
+
else
|
78
|
+
if workspaces.length == 1
|
79
|
+
@workspace = workspaces.first
|
80
|
+
else
|
81
|
+
@workspace = choose "Select a workspace:", *workspaces
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def determine_scheme!
|
87
|
+
if @xcodebuild_info.schemes.length == 1
|
88
|
+
@scheme = @xcodebuild_info.schemes.first
|
89
|
+
else
|
90
|
+
@scheme = choose "Select a scheme:", *@xcodebuild_info.schemes
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def determine_configuration!
|
95
|
+
if @xcodebuild_info.build_configurations.length == 1
|
96
|
+
@configuration = @xcodebuild_info.build_configurations.first
|
97
|
+
else
|
98
|
+
@configuration = choose "Select a configuration:", *@xcodebuild_info.build_configurations
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
alias_command :distribute, :'distribute:testflight'
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
module Shenzhen::Plugins
|
6
|
+
module TestFlight
|
7
|
+
class Client
|
8
|
+
HOSTNAME = 'testflightapp.com'
|
9
|
+
|
10
|
+
def initialize(api_token, team_token)
|
11
|
+
@api_token, @team_token = api_token, team_token
|
12
|
+
@connection = Faraday.new(:url => "http://#{HOSTNAME}") do |builder|
|
13
|
+
builder.request :multipart
|
14
|
+
builder.request :json
|
15
|
+
builder.response :json, :content_type => /\bjson$/
|
16
|
+
builder.use FaradayMiddleware::FollowRedirects
|
17
|
+
builder.adapter :net_http
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload_build(ipa, options)
|
22
|
+
options.update({
|
23
|
+
:api_token => @api_token,
|
24
|
+
:team_token => @team_token,
|
25
|
+
:file => Faraday::UploadIO.new(ipa, 'application/octet-stream')
|
26
|
+
})
|
27
|
+
|
28
|
+
@connection.post("/api/builds.json", options).on_complete do |env|
|
29
|
+
yield env[:status], env[:body] if block_given?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
command :'distribute:testflight' do |c|
|
37
|
+
c.syntax = "ipa distribute:testflight [options]"
|
38
|
+
c.summary = "Distribute an .ipa file over testflight"
|
39
|
+
c.description = ""
|
40
|
+
c.option '-f', '--file FILE', ".ipa file for the build"
|
41
|
+
c.option '-t', '--api_token TOKEN', "API Token. Available at https://testflightapp.com/account/#api-token"
|
42
|
+
c.option '-T', '--team_token TOKEN', "Team Token. Available at https://testflightapp.com/dashboard/team/edit/"
|
43
|
+
c.option '-m', '--notes NOTES', "Release notes for the build"
|
44
|
+
c.option '-l', '--lists LISTS', "Comma separated distribution list names which will receive access to the build"
|
45
|
+
c.option '--notify', "Notify permitted teammates to install the build"
|
46
|
+
c.option '--replace', "Replace binary for an existing build if one is found with the same name/bundle version"
|
47
|
+
c.option '-q', '--quiet', "Silence warning and success messages"
|
48
|
+
|
49
|
+
c.action do |args, options|
|
50
|
+
determine_file! unless @file = options.file
|
51
|
+
say_error "Missing or unspecified .ipa file" and abort unless @file and File.exist?(@file)
|
52
|
+
|
53
|
+
determine_api_token! unless @api_token = options.api_token
|
54
|
+
say_error "Missing API Token" and abort unless @api_token
|
55
|
+
|
56
|
+
determine_team_token! unless @team_token = options.team_token
|
57
|
+
|
58
|
+
determine_notes! unless @notes = options.notes
|
59
|
+
say_error "Missing release notes" and abort unless @notes
|
60
|
+
|
61
|
+
parameters = {}
|
62
|
+
parameters[:file] = @file
|
63
|
+
parameters[:notes] = @notes
|
64
|
+
parameters[:notify] = "true" if options.notify
|
65
|
+
parameters[:replace] = "true" if options.replace
|
66
|
+
parameters[:distribution_lists] = options.lists if options.lists
|
67
|
+
|
68
|
+
client = Shenzhen::Plugins::TestFlight::Client.new(@api_token, @team_token)
|
69
|
+
response = client.upload_build(@file, parameters)
|
70
|
+
case response.status
|
71
|
+
when 200...300
|
72
|
+
say_ok "Build successfully uploaded to TestFlight"
|
73
|
+
else
|
74
|
+
say_error "Error uploading to TestFlight: #{response.body}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def determine_api_token!
|
81
|
+
@api_token ||= ask "API Token:"
|
82
|
+
end
|
83
|
+
|
84
|
+
def determine_team_token!
|
85
|
+
@team_token ||= ask "Team Token:"
|
86
|
+
end
|
87
|
+
|
88
|
+
def determine_file!
|
89
|
+
files = Dir['*.ipa']
|
90
|
+
@file ||= case files.length
|
91
|
+
when 0 then nil
|
92
|
+
when 1 then files.first
|
93
|
+
else
|
94
|
+
@file = choose "Select an .ipa File:", *files
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def determine_notes!
|
99
|
+
placeholder = %{What's new in this release: }
|
100
|
+
|
101
|
+
@notes = ask_editor placeholder
|
102
|
+
@notes = nil if @notes == placeholder
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Shenzhen::XcodeBuild
|
4
|
+
class Info < OpenStruct; end
|
5
|
+
|
6
|
+
class Error < StandardError; end
|
7
|
+
class NilOutputError < Error; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def info
|
11
|
+
output = `xcodebuild -list 2> /dev/null`
|
12
|
+
raise Error.new $1 if /^xcodebuild\: error\: (.+)$/ === output
|
13
|
+
raise NilOutputError unless /\S/ === output
|
14
|
+
|
15
|
+
lines = output.split(/\n/)
|
16
|
+
hash = {}
|
17
|
+
group = nil
|
18
|
+
|
19
|
+
hash[:project] = lines.shift.match(/\"(.+)\"\:/)[1]
|
20
|
+
|
21
|
+
lines.each do |line|
|
22
|
+
if /\:$/ === line
|
23
|
+
group = line.strip[0...-1].downcase.gsub(/\s+/, '_')
|
24
|
+
hash[group] = []
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
unless group.nil? or /\.$/ === line
|
29
|
+
hash[group] << line.strip
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
hash.each do |group, values|
|
34
|
+
next unless Array === values
|
35
|
+
values.delete("") and values.uniq!
|
36
|
+
end
|
37
|
+
|
38
|
+
Info.new(hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
def settings(flags = [])
|
42
|
+
output = `xcodebuild #{flags.join(' ')} -showBuildSettings 2> /dev/null`
|
43
|
+
raise Error.new $1 if /^xcodebuild\: error\: (.+)$/ === output
|
44
|
+
raise NilOutputError unless /\S/ === output
|
45
|
+
|
46
|
+
lines = output.split(/\n/)
|
47
|
+
lines.shift
|
48
|
+
|
49
|
+
hash = {}
|
50
|
+
lines.each do |line|
|
51
|
+
key, value = line.split(/\=/).collect(&:strip)
|
52
|
+
hash[key] = value
|
53
|
+
end
|
54
|
+
|
55
|
+
hash
|
56
|
+
end
|
57
|
+
|
58
|
+
def version
|
59
|
+
output = `xcodebuild -version`
|
60
|
+
output.scan(/([\d\.?]+)/).flatten.first rescue nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/shenzhen.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "shenzhen"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "shenzhen"
|
7
|
+
s.authors = ["Mattt Thompson"]
|
8
|
+
s.email = "m@mattt.me"
|
9
|
+
s.homepage = "http://github.com/mattt/shenzhen"
|
10
|
+
s.version = Shenzhen::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.summary = "Shenzhen"
|
13
|
+
s.description = "CLI for Building & Distributing iOS Apps (.ipa Files)"
|
14
|
+
|
15
|
+
s.add_development_dependency "rspec", "~> 0.6.1"
|
16
|
+
s.add_development_dependency "rake", "~> 0.9.2"
|
17
|
+
|
18
|
+
s.add_dependency "commander", "~> 4.1.2"
|
19
|
+
s.add_dependency "json", "~> 1.7.3"
|
20
|
+
s.add_dependency "faraday", "~> 0.8.0"
|
21
|
+
s.add_dependency "faraday_middleware", "~> 0.8.7"
|
22
|
+
|
23
|
+
s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shenzhen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mattt Thompson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-28 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70338229563260 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.6.1
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70338229563260
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70338229562040 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.2
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70338229562040
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: commander
|
38
|
+
requirement: &70338229560720 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 4.1.2
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70338229560720
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: json
|
49
|
+
requirement: &70338229557880 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.7.3
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70338229557880
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: faraday
|
60
|
+
requirement: &70338229546680 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.8.0
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70338229546680
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday_middleware
|
71
|
+
requirement: &70338229545900 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.8.7
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70338229545900
|
80
|
+
description: CLI for Building & Distributing iOS Apps (.ipa Files)
|
81
|
+
email: m@mattt.me
|
82
|
+
executables:
|
83
|
+
- ipa
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- ./Gemfile
|
88
|
+
- ./Gemfile.lock
|
89
|
+
- ./lib/shenzhen/agvtool.rb
|
90
|
+
- ./lib/shenzhen/commands/build.rb
|
91
|
+
- ./lib/shenzhen/commands/distribute.rb
|
92
|
+
- ./lib/shenzhen/commands.rb
|
93
|
+
- ./lib/shenzhen/plugins/testflight.rb
|
94
|
+
- ./lib/shenzhen/xcodebuild.rb
|
95
|
+
- ./lib/shenzhen.rb
|
96
|
+
- ./LICENSE
|
97
|
+
- ./Rakefile
|
98
|
+
- ./README.md
|
99
|
+
- ./shenzhen.gemspec
|
100
|
+
- bin/ipa
|
101
|
+
homepage: http://github.com/mattt/shenzhen
|
102
|
+
licenses: []
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
hash: 522475160615829235
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
hash: 522475160615829235
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 1.8.15
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: Shenzhen
|
131
|
+
test_files: []
|