Module: RubyBuildIos

Defined in:
lib/ruby_build_ios.rb

Overview

ruby-build-ios.rb

Constant Summary collapse

PROJECT_BUILD_NUMBER =
'PROJECT_BUILD_NUMBER'

Class Method Summary collapse

Class Method Details

.build_project(project, scheme, configuration, build_number, archive_path) ⇒ Object

TODO allow flexibility in USER DEFINED build variables



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
# File 'lib/ruby_build_ios.rb', line 156

def self.build_project(project, scheme, configuration, build_number, archive_path)
  command = "xcodebuild -project #{project} -scheme #{scheme} -configuration #{configuration} -destination 'generic/platform=iOS' PROJECT_BUILD_NUMBER=#{build_number} -archivePath #{archive_path} archive"
  print "#{command}\n"
  # status is a Process::Status 
  result = 'OK'
  status = nil
  stderr_str = ''
  Open3.popen3(command) do |stdin, stdout, stderr, wait|

    t1 = Thread.new do
      while line = stdout.gets
        puts line
      end
    end
    
    t2 = Thread.new do
      while line = stderr.gets
        stderr_str << line
      end
    end
    
    status = wait.value
    t2.value
    t1.value
  end
    
  if status.success?
    print "#{result}\n"
  else
    raise stderr_str;
  end
  result    
end

.build_workspace(workspace, scheme, configuration, build_number, archive_path) ⇒ Object

TODO allow flexibility in USER DEFINED build variables



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/ruby_build_ios.rb', line 191

def self.build_workspace(workspace, scheme, configuration, build_number, archive_path)
  command = "xcodebuild -workspace #{workspace} -scheme #{scheme} -configuration #{configuration} -destination 'generic/platform=iOS' PROJECT_BUILD_NUMBER=#{build_number} -archivePath #{archive_path} archive"
  print "#{command}\n"
  # status is a Process::Status 
  result = 'OK'
  status = nil
  stderr_str = ''
  Open3.popen3(command) do |stdin, stdout, stderr, wait|

    t1 = Thread.new do
      while line = stdout.gets
        puts line
      end
    end
    
    t2 = Thread.new do
      while line = stderr.gets
        stderr_str << line
      end
    end
    
    status = wait.value
    t2.value
    t1.value
  end
    
  if status.success?
    print "#{result}\n"
  else
    raise stderr_str;
  end
  result    
end

.clean(path) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ruby_build_ios.rb', line 139

def self.clean(path)
  if path.chomp == '/'
    raise "Are you out of your mind?"
  end
  command = "rm -fr #{path}/*"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str    
end

.copy_provision_file(file_name, uuid) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ruby_build_ios.rb', line 100

def self.copy_provision_file(file_name, uuid)
  command = "cp #{file_name} ~/Library/MobileDevice/Provisioning\\ Profiles/#{uuid}.mobileprovision"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str    
end

.create_export_plist(file_name, key_string_pairs) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/ruby_build_ios.rb', line 225

def self.create_export_plist(file_name, key_string_pairs)
  if !key_string_pairs.is_a? Hash
    raise "create_export_plist() key_string_pairs must be a Hash\n"
  end
  
  xml_prelude = <<EO1
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>provisioningProfiles</key>
  <dict>
EO1
  xml_postlude = <<EO2
    </dict>
  <key>method</key>
  <string>app-store</string>
</dict>
</plist>
EO2
  xml_key_string_pairs = ''
  key_string_pairs.each_pair do |key, string|
    xml_key_string_pairs << "        <key>#{key}</key>\n"
    xml_key_string_pairs << "        <string>#{string}</string>\n"
  end

  print "Writing into #{file_name}\n"
  file = File.open(file_name, 'w+', 0666)
  file.puts("#{xml_prelude}#{xml_key_string_pairs}#{xml_postlude}")
  file.close()

  return true
end

.export_to_ipa(archive, plist, ipa_path) ⇒ Object



272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/ruby_build_ios.rb', line 272

def self.export_to_ipa(archive, plist, ipa_path)
  command = "xcodebuild -exportArchive -exportOptionsPlist #{plist} -archivePath #{archive} -exportPath #{ipa_path}"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str        
end

.get_uuid_from_file(file_name) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ruby_build_ios.rb', line 86

def self.get_uuid_from_file(file_name)
  command = "/usr/libexec/PlistBuddy -c \"Print UUID\" /dev/stdin <<< $(security cms -D -i #{file_name} 2> /dev/null)"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    stdout_str = stdout_str.chomp
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str    
end

.install_provision_file(file_name) ⇒ Object



113
114
115
116
# File 'lib/ruby_build_ios.rb', line 113

def self.install_provision_file(file_name)
  uuid = get_uuid_from_file(file_name)
  copy_provision_file(file_name, uuid)
end

.install_provision_files(file_names_str) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/ruby_build_ios.rb', line 118

def self.install_provision_files(file_names_str)
  file_names = file_name_str.gsub("\n",'').strip().split(',')
  file_names.each do |file_name|
    uuid = get_uuid_from_file(file_name)
    copy_provision_file(file_name, uuid)
  end
end

.latest_git_commit_comment(revision = '--all') ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ruby_build_ios.rb', line 26

def self.latest_git_commit_comment(revision = '--all') 
  command = "git log -1 --oneline #{revision}"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)  
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str.chomp.chomp  
end

.latest_git_commit_count(revision = '--all') ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ruby_build_ios.rb', line 12

def self.latest_git_commit_count(revision = '--all')
  command = "git rev-list --count #{revision}"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str.chomp.chomp  
  result.to_i
end

.project_build_number(file_name = PROJECT_BUILD_NUMBER) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby_build_ios.rb', line 66

def self.project_build_number(file_name = PROJECT_BUILD_NUMBER)
  print "Reading from #{file_name} to get the last project build number\n"
  file = File.open(file_name, 'r')
  build_str = file.gets()
  file.close()
  
  build_int = build_str.chomp.to_i
  
  build_int += 1
    
  build_str = build_int.to_s
  
  print "Writing into #{file_name} to set the next project build number\n"
  file = File.open(file_name, 'w+', 0666)
  file.puts(build_str)
  file.close()
  
  build_str
end

.tag_latest_git_commit(tag, message = 'Sorry, no tag message provided.') ⇒ Object



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
# File 'lib/ruby_build_ios.rb', line 39

def self.tag_latest_git_commit(tag, message = 'Sorry, no tag message provided.')
  command = "git tag -a #{tag} -m \"#{message}\""
  print "#{command}\n"
  # status is a Process::Status 
  # -a is annotate
  # -m is message
  # ex: git tag -a v1.4 -m "my version 1.4"
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str
  command = "git push origin #{tag}"
  print "#{command}\n"
  # ex: git push origin v1.4
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end

  result = "#{result}\n#{stdout_str}" 
end

.upload_to_hockey(app_id, api_token, note, file_to_upload) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/ruby_build_ios.rb', line 126

def self.upload_to_hockey(app_id, api_token, note, file_to_upload)
  command = "puck -app_id=#{app_id} -api_token=#{api_token} -submit=auto -download=true -notify=true -notes=\"#{note}\" #{file_to_upload}"
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str    
end

.upload_to_itunes(user, password, ipa) ⇒ Object

May want to stream stderr to console too, because altool uses stderr instead of stdout



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/ruby_build_ios.rb', line 324

def self.upload_to_itunes(user, password, ipa)
  # get altools path
  xcode_path = self.xcode_path
  altool = "#{xcode_path}/Applications/Application\\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
  command = "#{altool} --upload-app --type ios -u \"#{user}\" -p \"#{password}\"  -f #{ipa}"
  print "#{command}\n"
  result = 'OK'
  status = nil
  stderr_str = ''
  Open3.popen3(command) do |stdin, stdout, stderr, wait|

    t1 = Thread.new do
      while line = stdout.gets
        puts line
      end
    end
    
    t2 = Thread.new do
      while line = stderr.gets
        puts line
        stderr_str << line
      end
    end
    
    status = wait.value
    t2.value
    t1.value
  end
    
  if status.success?
    print "#{result}\n"
  else
    raise stderr_str;
  end
  result    
end

.validate_with_itunes(user, password, ipa) ⇒ Object

May want to stream stderr to console too, because altool uses stderr instead of stdout



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/ruby_build_ios.rb', line 286

def self.validate_with_itunes(user, password, ipa)
  # get altools path
  xcode_path = self.xcode_path
  altool = "#{xcode_path}/Applications/Application\\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
  command = "#{altool} --validate-app --type ios -u \"#{user}\" -p \"#{password}\"  -f #{ipa}"
  print "#{command}\n"
  result = 'OK'
  status = nil
  stderr_str = ''
  Open3.popen3(command) do |stdin, stdout, stderr, wait|

    t1 = Thread.new do
      while line = stdout.gets
        puts line
      end
    end
    
    t2 = Thread.new do
      while line = stderr.gets
        puts line
        stderr_str << line
      end
    end
    
    status = wait.value
    t2.value
    t1.value
  end
    
  if status.success?
    print "#{result}\n"
  else
    raise stderr_str;
  end
  result    
end

.xcode_pathObject



259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/ruby_build_ios.rb', line 259

def self.xcode_path()
  command = "dirname \"$(xcode-select -p)\""
  print "#{command}\n"
  # status is a Process::Status 
  stdout_str, stderr_str, status = Open3.capture3(command)
  if status.success?
    print "#{stdout_str}\n"
  else
    raise stderr_str;
  end
  result = stdout_str.chomp.chomp    
end