krausefx-shenzhen 0.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +68 -0
- data/LICENSE +19 -0
- data/README.md +198 -0
- data/Rakefile +9 -0
- data/lib/shenzhen.rb +4 -0
- data/lib/shenzhen/agvtool.rb +17 -0
- data/lib/shenzhen/commands.rb +16 -0
- data/lib/shenzhen/commands/build.rb +213 -0
- data/lib/shenzhen/commands/distribute.rb +30 -0
- data/lib/shenzhen/commands/info.rb +94 -0
- data/lib/shenzhen/plistbuddy.rb +9 -0
- data/lib/shenzhen/plugins/crashlytics.rb +82 -0
- data/lib/shenzhen/plugins/deploygate.rb +97 -0
- data/lib/shenzhen/plugins/fir.rb +145 -0
- data/lib/shenzhen/plugins/ftp.rb +181 -0
- data/lib/shenzhen/plugins/hockeyapp.rb +119 -0
- data/lib/shenzhen/plugins/itunesconnect.rb +142 -0
- data/lib/shenzhen/plugins/pgyer.rb +135 -0
- data/lib/shenzhen/plugins/rivierabuild.rb +81 -0
- data/lib/shenzhen/plugins/s3.rb +139 -0
- data/lib/shenzhen/plugins/testfairy.rb +99 -0
- data/lib/shenzhen/version.rb +3 -0
- data/lib/shenzhen/xcodebuild.rb +99 -0
- data/shenzhen.gemspec +37 -0
- metadata +264 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e9dcf3992465f173b3273dd22c4bfd5d71b42dd7
|
4
|
+
data.tar.gz: c526db6c2bcc0fd7f45e9b2612d0a393f11670db
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ae852791af679b572b4e39726a661a4cbcbac2d8dab9bc0c460fe0b7903b4369e83690b63d7eeb4ec244657f9c82e7c998de3e29b0de867de2f2153a4f6fba3d
|
7
|
+
data.tar.gz: f02238a3d2be2e1e02bada918969fe3031a78a50b342e945c42c1db77b82c86df2bd4adc6303a46b1476ba9963239f71e274d8812cd77dd89a484bc0ffc7d0ea
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
krausefx-shenzhen (0.14.1)
|
5
|
+
aws-sdk (~> 1.0)
|
6
|
+
commander (~> 4.3)
|
7
|
+
dotenv (>= 0.7)
|
8
|
+
faraday (~> 0.8.9)
|
9
|
+
faraday_middleware (~> 0.9)
|
10
|
+
highline (>= 1.7.2)
|
11
|
+
json (~> 1.8)
|
12
|
+
net-sftp (~> 2.1.2)
|
13
|
+
plist (~> 3.1.0)
|
14
|
+
rubyzip (~> 1.1)
|
15
|
+
security (~> 0.1.3)
|
16
|
+
terminal-table (~> 1.4.5)
|
17
|
+
|
18
|
+
GEM
|
19
|
+
remote: https://rubygems.org/
|
20
|
+
specs:
|
21
|
+
aws-sdk (1.64.0)
|
22
|
+
aws-sdk-v1 (= 1.64.0)
|
23
|
+
aws-sdk-v1 (1.64.0)
|
24
|
+
json (~> 1.4)
|
25
|
+
nokogiri (>= 1.4.4)
|
26
|
+
commander (4.3.4)
|
27
|
+
highline (~> 1.7.2)
|
28
|
+
diff-lcs (1.2.5)
|
29
|
+
dotenv (2.0.1)
|
30
|
+
faraday (0.8.9)
|
31
|
+
multipart-post (~> 1.2.0)
|
32
|
+
faraday_middleware (0.9.1)
|
33
|
+
faraday (>= 0.7.4, < 0.10)
|
34
|
+
highline (1.7.2)
|
35
|
+
json (1.8.2)
|
36
|
+
mini_portile (0.6.2)
|
37
|
+
multipart-post (1.2.0)
|
38
|
+
net-sftp (2.1.2)
|
39
|
+
net-ssh (>= 2.6.5)
|
40
|
+
net-ssh (2.9.2)
|
41
|
+
nokogiri (1.6.6.2)
|
42
|
+
mini_portile (~> 0.6.0)
|
43
|
+
plist (3.1.0)
|
44
|
+
rake (10.4.2)
|
45
|
+
rspec (3.2.0)
|
46
|
+
rspec-core (~> 3.2.0)
|
47
|
+
rspec-expectations (~> 3.2.0)
|
48
|
+
rspec-mocks (~> 3.2.0)
|
49
|
+
rspec-core (3.2.3)
|
50
|
+
rspec-support (~> 3.2.0)
|
51
|
+
rspec-expectations (3.2.1)
|
52
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
53
|
+
rspec-support (~> 3.2.0)
|
54
|
+
rspec-mocks (3.2.1)
|
55
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
56
|
+
rspec-support (~> 3.2.0)
|
57
|
+
rspec-support (3.2.2)
|
58
|
+
rubyzip (1.1.7)
|
59
|
+
security (0.1.3)
|
60
|
+
terminal-table (1.4.5)
|
61
|
+
|
62
|
+
PLATFORMS
|
63
|
+
ruby
|
64
|
+
|
65
|
+
DEPENDENCIES
|
66
|
+
krausefx-shenzhen!
|
67
|
+
rake
|
68
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012–2015 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,198 @@
|
|
1
|
+
![Shenzhen](https://raw.github.com/nomad/nomad.github.io/assets/shenzhen-banner.png)
|
2
|
+
|
3
|
+
Create `.ipa` files and distribute them from the command line, using any of the following methods:
|
4
|
+
|
5
|
+
- [iTunes Connect](https://itunesconnect.apple.com)
|
6
|
+
- [HockeyApp](http://www.hockeyapp.net)
|
7
|
+
- [Beta by Crashlytics](http://try.crashlytics.com/beta/)
|
8
|
+
- [RivieraBuild](http://rivierabuild.com)
|
9
|
+
- [TestFairy](https://www.testfairy.com/)
|
10
|
+
- [DeployGate](https://deploygate.com)
|
11
|
+
- [Fly It Remotely (FIR.im)](http://fir.im)
|
12
|
+
- [蒲公英 (PGYER)](http://www.pgyer.com)
|
13
|
+
- [Amazon S3](http://aws.amazon.com/s3/)
|
14
|
+
- FTP / SFTP
|
15
|
+
|
16
|
+
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.
|
17
|
+
|
18
|
+
> `shenzhen` is named for [深圳](http://en.wikipedia.org/wiki/Shenzhen), the Chinese city famous for being the center of manufacturing for a majority of consumer electronics, including iPhones and iPads.
|
19
|
+
> It's part of a series of world-class command-line utilities for iOS development, which includes [Cupertino](https://github.com/mattt/cupertino) (Apple Dev Center management), [Houston](https://github.com/mattt/houston) (Push Notifications), [Venice](https://github.com/mattt/venice) (In-App Purchase Receipt Verification), [Dubai](https://github.com/mattt/dubai) (Passbook pass generation), and [Nashville](https://github.com/nomad/nashville) (iTunes Store API).
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
```
|
24
|
+
$ gem install shenzhen
|
25
|
+
```
|
26
|
+
|
27
|
+
### JSON Build Error
|
28
|
+
|
29
|
+
Users running Mac OS X Mavericks with Xcode 5.1 may encounter an error when attempting to install the `json` gem dependency. As per the [Xcode 5.1 Release Notes](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Introduction/Introduction.html):
|
30
|
+
|
31
|
+
> The Apple LLVM compiler in Xcode 5.1 treats unrecognized command-line options as errors. This issue has been seen when building both Python native extensions and Ruby Gems, where some invalid compiler options are currently specified.
|
32
|
+
|
33
|
+
To work around this, install the `json` gem first with the following command:
|
34
|
+
|
35
|
+
```
|
36
|
+
$ ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future gem install json
|
37
|
+
```
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
> For best results, set your environment localization to UTF-8, with `$ export LC_ALL="en_US.UTF-8"`. Otherwise, Shenzhen may return unexpectedly with the error "invalid byte sequence in US-ASCII".
|
42
|
+
|
43
|
+
Shenzhen adds the `ipa` command to your PATH:
|
44
|
+
|
45
|
+
```
|
46
|
+
$ ipa
|
47
|
+
|
48
|
+
Build and distribute iOS apps (.ipa files)
|
49
|
+
|
50
|
+
Commands:
|
51
|
+
build Create a new .ipa file for your app
|
52
|
+
distribute:rivierabuild Distribute an .ipa file over [RivieraBuild](http://rivierabuild.com)
|
53
|
+
distribute:hockeyapp Distribute an .ipa file over HockeyApp
|
54
|
+
distribute:crashlytics Distribute an .ipa file over Crashlytics
|
55
|
+
distribute:deploygate Distribute an .ipa file over deploygate
|
56
|
+
distribute:firim Distribute an .ipa file over fir.im
|
57
|
+
distribute:itunesconnect Upload an .ipa file to iTunes Connect for review
|
58
|
+
distribute:pgyer Distribute an .ipa file over Pgyer
|
59
|
+
distribute:ftp Distribute an .ipa file over FTP
|
60
|
+
distribute:s3 Distribute an .ipa file over Amazon S3
|
61
|
+
distribute:testfairy Distribute an .ipa file over TestFairy
|
62
|
+
info Show mobile provisioning information about an .ipa file
|
63
|
+
help Display global or [command] help documentation.
|
64
|
+
|
65
|
+
Global Options:
|
66
|
+
-h, --help Display help documentation
|
67
|
+
-v, --version Display version information
|
68
|
+
-t, --trace Display backtrace when an error occurs
|
69
|
+
```
|
70
|
+
|
71
|
+
### Building & Distribution
|
72
|
+
|
73
|
+
```
|
74
|
+
$ cd /path/to/iOS Project/
|
75
|
+
$ ipa build
|
76
|
+
$ ipa distribute
|
77
|
+
```
|
78
|
+
|
79
|
+
#### RivieraBuild Distribution
|
80
|
+
|
81
|
+
```
|
82
|
+
$ ipa distribute:rivierabuild -k API_TOKEN -a AVAILABILITY
|
83
|
+
```
|
84
|
+
|
85
|
+
> Shenzhen will load credentials from the environment variable `RIVIERA_API_TOKEN` unless otherwise specified.
|
86
|
+
> To get the list of availability options, visit http://api.rivierabuild.com
|
87
|
+
|
88
|
+
#### HockeyApp Distribution
|
89
|
+
|
90
|
+
```
|
91
|
+
$ ipa distribute:hockeyapp -a API_TOKEN
|
92
|
+
```
|
93
|
+
|
94
|
+
> Shenzhen will load credentials from the environment variable `HOCKEYAPP_API_TOKEN` unless otherwise specified.
|
95
|
+
|
96
|
+
#### TestFairy Distribution
|
97
|
+
|
98
|
+
```
|
99
|
+
$ ipa distribute:testfairy -a API_KEY
|
100
|
+
```
|
101
|
+
|
102
|
+
> Shenzhen will load credentials from the environment variable `TESTFAIRY_API_KEY` unless otherwise specified.
|
103
|
+
|
104
|
+
#### Crashlytics Beta Distribution
|
105
|
+
|
106
|
+
```
|
107
|
+
$ ipa distribute:crashlytics -c /path/to/Crashlytics.framework -a API_TOKEN -s BUILD_SECRET
|
108
|
+
```
|
109
|
+
|
110
|
+
> Shenzhen will load credentials from the environment variables `CRASHLYTICS_API_TOKEN` & `CRASHLYTICS_BUILD_SECRET`, and attempt to run the submit executable `submit` in the path to Crashlytics.framework specified by `CRASHLYTICS_FRAMEWORK_PATH` unless otherwise specified.
|
111
|
+
|
112
|
+
|
113
|
+
#### DeployGate Distribution
|
114
|
+
|
115
|
+
```
|
116
|
+
$ ipa distribute:deploygate -a API_TOKEN -u USER_NAME
|
117
|
+
```
|
118
|
+
|
119
|
+
> Shenzhen will load credentials from the environment variable `DEPLOYGATE_API_TOKEN` and `DEPLOYGATE_USER_NAME` unless otherwise specified.
|
120
|
+
|
121
|
+
#### FTP Distribution
|
122
|
+
|
123
|
+
```
|
124
|
+
$ ipa distribute:ftp --host HOST -u USER -p PASSWORD -P FTP_PATH
|
125
|
+
```
|
126
|
+
|
127
|
+
#### SFTP Distribution
|
128
|
+
|
129
|
+
```
|
130
|
+
$ ipa distribute:sftp --host HOST -u USER -p PASSWORD -P FTP_PATH
|
131
|
+
```
|
132
|
+
|
133
|
+
#### Amazon S3 Distribution
|
134
|
+
|
135
|
+
```
|
136
|
+
$ ipa distribute:s3 -a ACCESS_KEY_ID -s SECRET_ACCESS_KEY -b BUCKET
|
137
|
+
```
|
138
|
+
|
139
|
+
> Shenzhen will load credentials from the environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_REGION` unless otherwise specified.
|
140
|
+
|
141
|
+
#### FIR (Fly it Remotely)
|
142
|
+
|
143
|
+
```
|
144
|
+
$ ipa distribute:fir -u USER_TOKEN -a APP_ID
|
145
|
+
```
|
146
|
+
|
147
|
+
> Shenzhen will load credentials from the environment variables `FIR_USER_TOKEN`, `FIR_APP_ID` unless otherwise specified.
|
148
|
+
|
149
|
+
#### 蒲公英 (PGYER)
|
150
|
+
|
151
|
+
```
|
152
|
+
$ ipa distribute:pgyer -u USER_KEY -a APP_KEY
|
153
|
+
```
|
154
|
+
|
155
|
+
> Shenzhen will load credentials from the environment variables `PGYER_USER_KEY`, `PGYER_API_KEY` unless otherwise specified.
|
156
|
+
|
157
|
+
|
158
|
+
#### iTunes Connect Distribution
|
159
|
+
|
160
|
+
```
|
161
|
+
$ ipa distribute:itunesconnect -a me@email.com -p myitunesconnectpassword -i appleid --upload
|
162
|
+
```
|
163
|
+
|
164
|
+
> Shenzhen will load credentials from the environment variables `ITUNES_CONNECT_ACCOUNT` and `ITUNES_CONNECT_PASSWORD` unless otherwise specified. If only an account is provided, the keychain will be searched for a matching entry.
|
165
|
+
>
|
166
|
+
> The `-i` (or `--apple-id`) flag is "An automatically generated ID assigned to your app". It can be found via iTunes Connect by navigating to:
|
167
|
+
> * My Apps -> [App Name] -> More -> About This App -> Apple ID
|
168
|
+
>
|
169
|
+
> For a fully hands-free upload, in a CI environment for example, ensure your iTunes Connect credentials are stored in your keychain, and that the keychain item has the Validation app in its 'Always allow access' list. Running Shenzhen once with the `--save-keychain` flag, and clicking `Always Allow` on the prompt will set this up for you.
|
170
|
+
|
171
|
+
### Displaying Embedded .mobileprovision Information
|
172
|
+
|
173
|
+
```
|
174
|
+
$ ipa info /path/to/app.ipa
|
175
|
+
|
176
|
+
+-----------------------------+----------------------------------------------------------+
|
177
|
+
| ApplicationIdentifierPrefix | DJ73OPSO53 |
|
178
|
+
| CreationDate | 2014-03-26T02:53:00+00:00 |
|
179
|
+
| Entitlements | application-identifier: DJ73OPSO53.com.nomad.shenzhen |
|
180
|
+
| | aps-environment: production |
|
181
|
+
| | get-task-allow: false |
|
182
|
+
| | keychain-access-groups: ["DJ73OPSO53.*"] |
|
183
|
+
| CreationDate | 2017-03-26T02:53:00+00:00 |
|
184
|
+
| Name | Shenzhen |
|
185
|
+
| TeamIdentifier | S6ZYP4L6TY |
|
186
|
+
| TimeToLive | 172 |
|
187
|
+
| UUID | P7602NR3-4D34-441N-B6C9-R79395PN1OO3 |
|
188
|
+
| Version | 1 |
|
189
|
+
+-----------------------------+----------------------------------------------------------+
|
190
|
+
```
|
191
|
+
|
192
|
+
## Creator
|
193
|
+
|
194
|
+
Mattt Thompson ([@mattt](https://twitter.com/mattt))
|
195
|
+
|
196
|
+
## License
|
197
|
+
|
198
|
+
Shenzhen is released under an MIT license. See LICENSE for more information.
|
data/Rakefile
ADDED
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,16 @@
|
|
1
|
+
$:.push File.expand_path('../', __FILE__)
|
2
|
+
|
3
|
+
require 'plugins/rivierabuild'
|
4
|
+
require 'plugins/hockeyapp'
|
5
|
+
require 'plugins/testfairy'
|
6
|
+
require 'plugins/deploygate'
|
7
|
+
require 'plugins/itunesconnect'
|
8
|
+
require 'plugins/ftp'
|
9
|
+
require 'plugins/s3'
|
10
|
+
require 'plugins/crashlytics'
|
11
|
+
require 'plugins/fir'
|
12
|
+
require 'plugins/pgyer'
|
13
|
+
|
14
|
+
require 'commands/build'
|
15
|
+
require 'commands/distribute'
|
16
|
+
require 'commands/info'
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
command :build do |c|
|
4
|
+
c.syntax = 'ipa build [options]'
|
5
|
+
c.summary = 'Create a new .ipa file for your app'
|
6
|
+
c.description = ''
|
7
|
+
|
8
|
+
c.option '-w', '--workspace WORKSPACE', 'Workspace (.xcworkspace) file to use to build app (automatically detected in current directory)'
|
9
|
+
c.option '-p', '--project PROJECT', 'Project (.xcodeproj) file to use to build app (automatically detected in current directory, overridden by --workspace option, if passed)'
|
10
|
+
c.option '-c', '--configuration CONFIGURATION', 'Configuration used to build'
|
11
|
+
c.option '-s', '--scheme SCHEME', 'Scheme used to build app'
|
12
|
+
c.option '--xcconfig XCCONFIG', 'use an extra XCCONFIG file to build the app'
|
13
|
+
c.option '--xcargs XCARGS', 'pass additional arguments to xcodebuild when building the app. Be sure to quote multiple args.'
|
14
|
+
c.option '--[no-]clean', 'Clean project before building'
|
15
|
+
c.option '--[no-]archive', 'Archive project after building'
|
16
|
+
c.option '-d', '--destination DESTINATION', 'Destination. Defaults to current directory'
|
17
|
+
c.option '-m', '--embed PROVISION', 'Sign .ipa file with .mobileprovision'
|
18
|
+
c.option '-i', '--identity IDENTITY', 'Identity to be used along with --embed'
|
19
|
+
c.option '--sdk SDK', 'use SDK as the name or path of the base SDK when building the project'
|
20
|
+
c.option '--ipa IPA', 'specify the name of the .ipa file to generate (including file extension)'
|
21
|
+
|
22
|
+
c.action do |args, options|
|
23
|
+
validate_xcode_version!
|
24
|
+
|
25
|
+
@workspace = options.workspace
|
26
|
+
@project = options.project unless @workspace
|
27
|
+
|
28
|
+
@xcodebuild_info = Shenzhen::XcodeBuild.info(:workspace => @workspace, :project => @project)
|
29
|
+
|
30
|
+
@scheme = options.scheme
|
31
|
+
@sdk = options.sdk || 'iphoneos'
|
32
|
+
@configuration = options.configuration
|
33
|
+
@xcconfig = options.xcconfig
|
34
|
+
@xcargs = options.xcargs
|
35
|
+
@destination = options.destination || Dir.pwd
|
36
|
+
@ipa_name_override = options.ipa
|
37
|
+
FileUtils.mkdir_p(@destination) unless File.directory?(@destination)
|
38
|
+
|
39
|
+
determine_workspace_or_project! unless @workspace || @project
|
40
|
+
|
41
|
+
if @project
|
42
|
+
determine_configuration! unless @configuration
|
43
|
+
say_error "Configuration #{@configuration} not found" and abort unless (@xcodebuild_info.build_configurations.include?(@configuration) rescue false)
|
44
|
+
end
|
45
|
+
|
46
|
+
determine_scheme! unless @scheme
|
47
|
+
say_error "Scheme #{@scheme} not found" and abort unless (@xcodebuild_info.schemes.include?(@scheme) rescue false)
|
48
|
+
|
49
|
+
@configuration = options.configuration
|
50
|
+
|
51
|
+
flags = []
|
52
|
+
flags << %{-sdk #{@sdk}}
|
53
|
+
flags << %{-workspace "#{@workspace}"} if @workspace
|
54
|
+
flags << %{-project "#{@project}"} if @project
|
55
|
+
flags << %{-scheme "#{@scheme}"} if @scheme
|
56
|
+
flags << %{-configuration "#{@configuration}"} if @configuration
|
57
|
+
flags << %{-xcconfig "#{@xcconfig}"} if @xcconfig
|
58
|
+
flags << @xcargs if @xcargs
|
59
|
+
|
60
|
+
@target, @xcodebuild_settings = Shenzhen::XcodeBuild.settings(*flags).detect{|target, settings| settings['WRAPPER_EXTENSION'] == "app"}
|
61
|
+
say_error "App settings could not be found." and abort unless @xcodebuild_settings
|
62
|
+
|
63
|
+
if !@configuration
|
64
|
+
@configuration = @xcodebuild_settings['CONFIGURATION']
|
65
|
+
flags << "-configuration '#{@configuration}'"
|
66
|
+
end
|
67
|
+
|
68
|
+
say_warning "Building \"#{@workspace || @project}\" with Scheme \"#{@scheme}\" and Configuration \"#{@configuration}\"\n" if $verbose
|
69
|
+
|
70
|
+
log "xcodebuild", (@workspace || @project)
|
71
|
+
|
72
|
+
xcode = `xcode-select --print-path`.strip
|
73
|
+
|
74
|
+
actions = []
|
75
|
+
actions << :clean unless options.clean == false
|
76
|
+
actions << :build
|
77
|
+
actions << :archive unless options.archive == false
|
78
|
+
|
79
|
+
ENV['CC'] = nil # Fix for RVM
|
80
|
+
command = %{xcodebuild #{flags.join(' ')} #{actions.join(' ')} #{'1> /dev/null' unless $verbose}}
|
81
|
+
puts command if $verbose
|
82
|
+
abort unless system command
|
83
|
+
|
84
|
+
@target, @xcodebuild_settings = Shenzhen::XcodeBuild.settings(*flags).detect{|target, settings| settings['WRAPPER_EXTENSION'] == "app"}
|
85
|
+
say_error "App settings could not be found." and abort unless @xcodebuild_settings
|
86
|
+
|
87
|
+
@app_path = File.join(@xcodebuild_settings['BUILT_PRODUCTS_DIR'], @xcodebuild_settings['WRAPPER_NAME'])
|
88
|
+
@dsym_path = @app_path + ".dSYM"
|
89
|
+
@dsym_filename = File.expand_path("#{@xcodebuild_settings['WRAPPER_NAME']}.dSYM", @destination)
|
90
|
+
@ipa_name = @ipa_name_override || @xcodebuild_settings['WRAPPER_NAME'].gsub(@xcodebuild_settings['WRAPPER_SUFFIX'], "") + ".ipa"
|
91
|
+
@ipa_path = File.expand_path(@ipa_name, @destination)
|
92
|
+
|
93
|
+
log "xcrun", "PackageApplication"
|
94
|
+
command = %{xcrun -sdk #{@sdk} PackageApplication -v "#{@app_path}" -o "#{@ipa_path}" --embed "#{options.embed || @dsym_path}" #{"-s \"#{options.identity}\"" if options.identity} #{'--verbose' if $verbose} #{'1> /dev/null' unless $verbose}}
|
95
|
+
puts command if $verbose
|
96
|
+
abort unless system command
|
97
|
+
|
98
|
+
|
99
|
+
# Determine whether this is a Swift project and, eventually, the list of libraries to copy from
|
100
|
+
# Xcode's toolchain directory since there's no "xcodebuild" target to do just that (it is done
|
101
|
+
# post-build when exporting an archived build from the "Organizer").
|
102
|
+
@ipa_swift_frameworks = Dir["#{@app_path}/Frameworks/libswift*"]
|
103
|
+
|
104
|
+
if not @ipa_swift_frameworks.empty?
|
105
|
+
Dir.mktmpdir do |tmpdir|
|
106
|
+
# Copy all necessary Swift libraries to a temporary "SwiftSupport" directory so that we can
|
107
|
+
# easily add it to the .ipa later.
|
108
|
+
swift_support = File.join(tmpdir, "SwiftSupport")
|
109
|
+
|
110
|
+
Dir.mkdir(swift_support)
|
111
|
+
|
112
|
+
@ipa_swift_frameworks.each do |path|
|
113
|
+
framework = File.basename(path)
|
114
|
+
|
115
|
+
FileUtils.copy_file("#{xcode}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/#{@sdk}/#{framework}", File.join(swift_support, framework))
|
116
|
+
end
|
117
|
+
|
118
|
+
# Add "SwiftSupport" to the .ipa archive
|
119
|
+
Dir.chdir(tmpdir) do
|
120
|
+
abort unless system %{zip --recurse-paths "#{@ipa_path}" "SwiftSupport" #{'> /dev/null' unless $verbose}}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
if is_watchkit?(@app_path)
|
126
|
+
log "Adding WatchKit support files", "#{xcode}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/Library/Application Support/WatchKit/WK"
|
127
|
+
Dir.mktmpdir do |tmpdir|
|
128
|
+
# Make watchkit support directory
|
129
|
+
watchkit_support = File.join(tmpdir, "WatchKitSupport")
|
130
|
+
Dir.mkdir(watchkit_support)
|
131
|
+
|
132
|
+
# Copy WK from Xcode into WatchKitSupport
|
133
|
+
FileUtils.copy_file("#{xcode}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/Library/Application Support/WatchKit/WK", File.join(watchkit_support, "WK"))
|
134
|
+
|
135
|
+
# Add "WatchKitSupport" to the .ipa archive
|
136
|
+
Dir.chdir(tmpdir) do
|
137
|
+
abort unless system %{zip --recurse-paths "#{@ipa_path}" "WatchKitSupport" #{'> /dev/null' unless $verbose}}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
log "zip", @dsym_filename
|
143
|
+
abort unless system %{cp -r "#{@dsym_path}" "#{@destination}" && pushd "#{File.dirname(@dsym_filename)}" && zip -r "#{@dsym_filename}.zip" "#{File.basename(@dsym_filename)}" #{'> /dev/null' unless $verbose} && popd && rm -rf "#{@dsym_filename}"}
|
144
|
+
|
145
|
+
say_ok "Successfully built:"
|
146
|
+
say_ok @ipa_path
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def is_watchkit?(path)
|
152
|
+
Dir["#{path}/**/*.plist"].each do |current|
|
153
|
+
# `2>&1` to hide the error if it's not there: http://stackoverflow.com/a/4783536/445598
|
154
|
+
watchkit_enabled = `/usr/libexec/PlistBuddy -c 'Print WKWatchKitApp' '#{current}' 2>&1`.strip
|
155
|
+
if watchkit_enabled == 'true'
|
156
|
+
return true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
def validate_xcode_version!
|
163
|
+
version = Shenzhen::XcodeBuild.version
|
164
|
+
say_error "Shenzhen requires Xcode 4 (found #{version}). Please install or switch to the latest Xcode." and abort if version < "4.0.0"
|
165
|
+
end
|
166
|
+
|
167
|
+
def determine_workspace_or_project!
|
168
|
+
workspaces, projects = Dir["*.xcworkspace"], Dir["*.xcodeproj"]
|
169
|
+
|
170
|
+
if workspaces.empty?
|
171
|
+
if projects.empty?
|
172
|
+
say_error "No Xcode projects or workspaces found in current directory" and abort
|
173
|
+
else
|
174
|
+
if projects.length == 1
|
175
|
+
@project = projects.first
|
176
|
+
else
|
177
|
+
@project = choose "Select a project:", *projects
|
178
|
+
end
|
179
|
+
end
|
180
|
+
else
|
181
|
+
if workspaces.length == 1
|
182
|
+
@workspace = workspaces.first
|
183
|
+
else
|
184
|
+
@workspace = choose "Select a workspace:", *workspaces
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def determine_scheme!
|
190
|
+
say_error "No schemes found in Xcode project or workspace" and abort unless @xcodebuild_info.schemes
|
191
|
+
|
192
|
+
if @xcodebuild_info.schemes.length == 1
|
193
|
+
@scheme = @xcodebuild_info.schemes.first
|
194
|
+
else
|
195
|
+
@scheme = choose "Select a scheme:", *@xcodebuild_info.schemes
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def determine_configuration!
|
200
|
+
configurations = @xcodebuild_info.build_configurations rescue []
|
201
|
+
if configurations.nil? or configurations.empty? or configurations.include?("Debug")
|
202
|
+
@configuration = "Debug"
|
203
|
+
elsif configurations.length == 1
|
204
|
+
@configuration = configurations.first
|
205
|
+
end
|
206
|
+
|
207
|
+
if @configuration
|
208
|
+
say_warning "Configuration was not passed, defaulting to #{@configuration}"
|
209
|
+
else
|
210
|
+
@configuration = choose "Select a configuration:", *configurations
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|