-
Notifications
You must be signed in to change notification settings - Fork 70
/
base_builder.rb
212 lines (173 loc) · 5.79 KB
/
base_builder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
module Xcode
module Builder
#
# This class tries to pull various bits of Xcoder together to provide a higher-level API for common
# project build tasks.
#
class BaseBuilder
attr_accessor :profile, :identity, :build_path, :keychain, :sdk, :objroot, :symroot
attr_reader :config, :target
def initialize(target, config)
@target = target
@config = config
@sdk = @target.project.sdk
@build_path = "#{File.dirname(@target.project.path)}/build/"
@objroot = @build_path
@symroot = @build_path
end
def common_environment
env = {}
env["OBJROOT"] = "\"#{@objroot}\""
env["SYMROOT"] = "\"#{@symroot}\""
env
end
def build_environment
profile = install_profile
env = common_environment
env["OTHER_CODE_SIGN_FLAGS"] = "'--keychain #{@keychain.path}'" unless @keychain.nil?
env["CODE_SIGN_IDENTITY"] = "\"#{@identity}\"" unless @identity.nil?
env["PROVISIONING_PROFILE"] = "#{profile.uuid}" unless profile.nil?
env
end
def build(options = {:sdk => @sdk})
cmd = xcodebuild
cmd << "-sdk #{options[:sdk]}" unless options[:sdk].nil?
with_keychain do
cmd.execute
end
self
end
#
# Invoke the configuration's test target and parse the resulting output
#
# If a block is provided, the report is yielded for configuration before the test is run
#
def test(options = {:sdk => 'iphonesimulator'}) #, :parser => :OCUnit })
cmd = xcodebuild
cmd << "-sdk #{options[:sdk]}" unless options[:sdk].nil?
cmd.env["TEST_AFTER_BUILD"]="YES"
report = Xcode::Test::Report.new
if block_given?
yield(report)
else
report.add_formatter :stdout
report.add_formatter :junit, 'test-reports'
end
parser = Xcode::Test::Parsers::OCUnitParser.new report
begin
cmd.execute(false) do |line|
parser << line
end
rescue Xcode::Shell::ExecutionError => e
puts "Test platform exited: #{e.message}"
ensure
parser.flush
end
report
end
#
# Upload to testflight
#
# The testflight object is yielded so further configuration can be performed before uploading
#
# @param api_token the API token for your testflight account
# @param team_token the token for the team you want to deploy to
#
def testflight(api_token, team_token)
raise "Can't find #{ipa_path}, do you need to call builder.package?" unless File.exists? ipa_path
raise "Can't find #{dsym_zip_path}, do you need to call builder.package?" unless File.exists? dsym_zip_path
testflight = Xcode::Deploy::Testflight.new(api_token, team_token)
yield(testflight) if block_given?
testflight.upload(ipa_path, dsym_zip_path)
end
def clean
cmd = xcodebuild
cmd << "-sdk #{@sdk}" unless @sdk.nil?
cmd << "clean"
cmd.execute
@built = false
@packaged = false
self
end
def sign
cmd = Xcode::Shell::Command.new 'codesign'
cmd << "--force"
cmd << "--sign \"#{@identity}\""
cmd << "--resource-rules=\"#{app_path}/ResourceRules.plist\""
cmd << "--entitlements \"#{entitlements_path}\""
cmd << "\"#{ipa_path}\""
cmd.execute
self
end
def package
raise "Can't find #{app_path}, do you need to call builder.build?" unless File.exists? app_path
#package IPA
cmd = Xcode::Shell::Command.new 'xcrun'
cmd << "-sdk #{@sdk}" unless @sdk.nil?
cmd << "PackageApplication"
cmd << "-v \"#{app_path}\""
cmd << "-o \"#{ipa_path}\""
unless @profile.nil?
cmd << "--embed \"#{@profile}\""
end
with_keychain do
cmd.execute
end
# package dSYM
cmd = Xcode::Shell::Command.new 'zip'
cmd << "-r"
cmd << "-T"
cmd << "-y \"#{dsym_zip_path}\""
cmd << "\"#{dsym_path}\""
cmd.execute
self
end
def configuration_build_path
"#{build_path}/#{@config.name}-#{@sdk}"
end
def entitlements_path
"#{build_path}/#{@target.name}.build/#{name}-#{@target.project.sdk}/#{@target.name}.build/#{@config.product_name}.xcent"
end
def app_path
"#{configuration_build_path}/#{@config.product_name}.app"
end
def product_version_basename
version = @config.info_plist.version
version = "SNAPSHOT" if version.nil? or version==""
"#{configuration_build_path}/#{@config.product_name}-#{@config.name}-#{version}"
end
def ipa_path
"#{product_version_basename}.ipa"
end
def dsym_path
"#{app_path}.dSYM"
end
def dsym_zip_path
"#{product_version_basename}.dSYM.zip"
end
private
def with_keychain(&block)
if @keychain.nil?
yield
else
Xcode::Keychains.with_keychain_in_search_path @keychain, &block
end
end
def install_profile
return nil if @profile.nil?
# TODO: remove other profiles for the same app?
p = ProvisioningProfile.new(@profile)
ProvisioningProfile.installed_profiles.each do |installed|
if installed.identifiers==p.identifiers and installed.uuid==p.uuid
installed.uninstall
end
end
p.install
p
end
def xcodebuild #:yield: Xcode::Shell::Command
Xcode::Shell::Command.new 'xcodebuild', build_environment
end
end
end
end