ruby_build_ios 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +110 -0
- data/example.rb +77 -0
- data/lib/ruby_build_ios.rb +361 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d86c0facbac4741b8325a9c178841d29c68ab964
|
4
|
+
data.tar.gz: 4034c6f566de14a9c1a09152418b91c738ef5551
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3a6442765b90ce2bfb015140cf2027a9f1018c3d4317a8281f949de29bbc7a93161102381283abf4a544d112c1287f7cdb0145a875099c391555791b92f7c4ab
|
7
|
+
data.tar.gz: da154b9855cf4eee3d53f1af59c818e93c7b7b98dfccb8e98d5ba901be9c0ac7fccfaf199f0966c04f0e0aaf54abce80497e30a09df8d3195956a3f10677c12b
|
data/README.md
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# README #
|
2
|
+
|
3
|
+
ruby_build_ios is a set of helper methods to assist in the development of build scripts for IOS mobile development.
|
4
|
+
|
5
|
+
These methods all reside in module RubyBuildIos and were developed as part of HS2's 2017 Hackathon.
|
6
|
+
|
7
|
+
## Installation / Usage ##
|
8
|
+
|
9
|
+
Install it yourself as:
|
10
|
+
|
11
|
+
$ gem install ruby_build_ios
|
12
|
+
|
13
|
+
Then in your build script:
|
14
|
+
|
15
|
+
require 'ruby_build_ios'
|
16
|
+
|
17
|
+
## Who do I talk to? ##
|
18
|
+
|
19
|
+
HS2 Solutions
|
20
|
+
|
21
|
+
https://www.hs2solutions.com
|
22
|
+
|
23
|
+
## Documentation ##
|
24
|
+
|
25
|
+
Very sparse, but here it is:
|
26
|
+
|
27
|
+
build_project(project, target, configuration, build_number, output_dir)
|
28
|
+
|
29
|
+
build_workspace(workspace, scheme, configuration, build_number, archive_path)
|
30
|
+
|
31
|
+
clean(path)
|
32
|
+
|
33
|
+
copy_provision_file(file_name, uuid)
|
34
|
+
|
35
|
+
create_export_plist(file_name, key_string_pairs)
|
36
|
+
|
37
|
+
get_uuid_from_file(file_name)
|
38
|
+
|
39
|
+
install_provision_file(file_name)
|
40
|
+
|
41
|
+
install_provision_files(file_names_str)
|
42
|
+
|
43
|
+
latest_git_commit_comment(revision = '--all')
|
44
|
+
|
45
|
+
latest_git_commit_count(revision = '--all')
|
46
|
+
|
47
|
+
project_build_number(file_name = PROJECT_BUILD_NUMBER)
|
48
|
+
|
49
|
+
tag_latest_git_commit(tag, message = 'Sorry, no tag message provided.')
|
50
|
+
|
51
|
+
upload_to_hockey(app_id, api_token, note, file_to_upload)
|
52
|
+
|
53
|
+
upload_to_itunes(user, password, archive)
|
54
|
+
|
55
|
+
xcode_path()
|
56
|
+
|
57
|
+
## Testing ##
|
58
|
+
|
59
|
+
We're hacking, so our testing is not what it would usually be. Here are some commands I used in irb to test each function:
|
60
|
+
|
61
|
+
Play this to test Module (Class) Functions
|
62
|
+
|
63
|
+
require './lib/ruby_build_ios.rb'
|
64
|
+
|
65
|
+
x=RubyBuildIos.latest_git_commit_count
|
66
|
+
|
67
|
+
x=RubyBuildIos.latest_git_commit_count('badbranch')
|
68
|
+
|
69
|
+
|
70
|
+
require './lib/ruby_build_ios.rb'
|
71
|
+
|
72
|
+
y=RubyBuildIos.latest_git_commit_comment
|
73
|
+
|
74
|
+
|
75
|
+
require './lib/ruby_build_ios.rb'
|
76
|
+
|
77
|
+
RubyBuildIos.tag_latest_git_commit('v1.0', "It is a fine day to commit!")
|
78
|
+
|
79
|
+
|
80
|
+
require './lib/ruby_build_ios.rb'
|
81
|
+
|
82
|
+
z=RubyBuildIos.project_build_number()
|
83
|
+
|
84
|
+
|
85
|
+
TODO: David, add a play here to test copy_provision_files
|
86
|
+
|
87
|
+
require './lib/ruby_build_ios.rb'
|
88
|
+
|
89
|
+
RubyBuildIos.install_provision_files("<file1>,<file2>,<file3>")
|
90
|
+
|
91
|
+
|
92
|
+
TODO: David, add a play script here to test upload_to_hockey
|
93
|
+
|
94
|
+
require './lib/ruby_build_ios.rb'
|
95
|
+
|
96
|
+
RubyBuildIos.upload_to_hockey(app_id, api_token, file_to_upload)
|
97
|
+
|
98
|
+
|
99
|
+
require './lib/ruby_build_ios.rb'
|
100
|
+
|
101
|
+
RubyBuildIos.create_export_plist('test_plist.xml', {
|
102
|
+
"ca.xxx.iphoneapp" => "XXXXX Prod App",
|
103
|
+
"ca.xxx.iphoneapp.watchkitapp" => "XXXXX Prod WKApp",
|
104
|
+
"ca.xxx.iphoneapp.watchkitapp.extension" => "XXXXX Prod WKExt" })
|
105
|
+
|
106
|
+
|
107
|
+
require './lib/ruby_build_ios.rb'
|
108
|
+
|
109
|
+
RubyBuildIos.xcode_path()
|
110
|
+
|
data/example.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# example.rb
|
4
|
+
|
5
|
+
require './lib/ruby_build_ios.rb'
|
6
|
+
|
7
|
+
# This code along with the build_project_workspace fills our current need for
|
8
|
+
# setting the build's version number. We have a TODO to allow for greater flexibility
|
9
|
+
# in setting build variables
|
10
|
+
def get_build_number_string()
|
11
|
+
build_number = RubyBuildIos.latest_git_commit_count()
|
12
|
+
build_number = build_number += 300000000
|
13
|
+
return build_number.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def release_to_qa()
|
17
|
+
archive_path = './build/qa'
|
18
|
+
archive_file = archive_path + '/Example.xcarchive'
|
19
|
+
|
20
|
+
RubyBuildIos.clean(archive_path)
|
21
|
+
|
22
|
+
# Copies the provision file to the appropriately named file in ~/Library/MobileDevice/Provisioning Profiles
|
23
|
+
# where Xcode expects to find them.
|
24
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_QA_App.mobileprovision')
|
25
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_QA_WKApp.mobileprovision')
|
26
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_QA_WKExt.mobileprovision')
|
27
|
+
|
28
|
+
# build_workspace(workspace, scheme, configuration, build_number, archive_path)
|
29
|
+
RubyBuildIos.build_workspace('Example.xcworkspace', 'Example', 'QA', get_build_number_string(), archive_file)
|
30
|
+
|
31
|
+
#upload the app to hockey
|
32
|
+
api_token = '<YOUR HOCKEY API TOKEN>'
|
33
|
+
app_id = "<YOUR HOCKEY APP ID>"
|
34
|
+
hockey_note = RubyBuildIos.latest_git_commit_comment()
|
35
|
+
|
36
|
+
# upload_to_hockey(app_id, api_token, note, file_to_upload)
|
37
|
+
RubyBuildIos.upload_to_hockey(app_id, api_token, hockey_note, archive_file)
|
38
|
+
end
|
39
|
+
|
40
|
+
def release_to_prod()
|
41
|
+
archive_path = './build/prod'
|
42
|
+
archive_file = archive_path + '/Example.xcarchive'
|
43
|
+
|
44
|
+
|
45
|
+
RubyBuildIos.clean('./build')
|
46
|
+
|
47
|
+
# Copies the provision file to the appropriately named file in ~/Library/MobileDevice/Provisioning Profiles
|
48
|
+
# where Xcode expects to find them.
|
49
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_Prod_App.mobileprovision')
|
50
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_Prod_WKApp.mobileprovision')
|
51
|
+
RubyBuildIos.install_provision_file('./certs/EXAMPLE_Prod_WKExt.mobileprovision')
|
52
|
+
|
53
|
+
# build_workspace(workspace, scheme, configuration, build_number, archive_path)
|
54
|
+
RubyBuildIos.build_workspace('Example.xcworkspace', 'Example', 'Release', get_build_number_string(), archive_file)
|
55
|
+
|
56
|
+
# This builds the plist necessary to create the ipa from the xcarchive
|
57
|
+
# The keys are the bundle ids for the various parts of your app
|
58
|
+
# This particular app has a watch app associated
|
59
|
+
# The values are the Name baked into the provision file. The one you specified when you created the provision profile
|
60
|
+
# You need one entry per profile required for you app. Simple apps need just one. Apps with watch apps need three.
|
61
|
+
plist_file = './build/build.plist'
|
62
|
+
provision_keys = {
|
63
|
+
"com.example.iphoneapp" => "EXAMPLE Prod App",
|
64
|
+
"com.example.iphoneapp.watchkitapp" => "EXAMPLE Prod WKApp",
|
65
|
+
"com.example.iphoneapp.watchkitapp.extension" => "EXAMPLE Prod WKExt" }
|
66
|
+
|
67
|
+
RubyBuildIos.create_export_plist(plist_file, provision_keys)
|
68
|
+
|
69
|
+
RubyBuildIos.export_to_ipa(archive_file, plist_file, archive_path)
|
70
|
+
|
71
|
+
user = '<YOUR ITUNES UPLOAD USER>'
|
72
|
+
password = '<YOUR ITUNES UPLOAD PASS>'
|
73
|
+
|
74
|
+
RubyBuildIos.validate_with_itunes(user, password, './build/example.ipa')
|
75
|
+
end
|
76
|
+
|
77
|
+
release_to_qa()
|
@@ -0,0 +1,361 @@
|
|
1
|
+
# ruby-build-ios.rb
|
2
|
+
|
3
|
+
module RubyBuildIos
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
PROJECT_BUILD_NUMBER = 'PROJECT_BUILD_NUMBER';
|
7
|
+
|
8
|
+
# https://ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture3
|
9
|
+
# https://ruby-doc.org/core-2.2.0/Process/Status.html
|
10
|
+
# http://ruby-doc.org/core-2.0.0/IO.html#method-i-puts
|
11
|
+
|
12
|
+
def self.latest_git_commit_count(revision = '--all')
|
13
|
+
command = "git rev-list --count #{revision}"
|
14
|
+
print "#{command}\n"
|
15
|
+
# status is a Process::Status
|
16
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
17
|
+
if status.success?
|
18
|
+
print "#{stdout_str}\n"
|
19
|
+
else
|
20
|
+
raise stderr_str;
|
21
|
+
end
|
22
|
+
result = stdout_str.chomp.chomp
|
23
|
+
result.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.latest_git_commit_comment(revision = '--all')
|
27
|
+
command = "git log -1 --oneline #{revision}"
|
28
|
+
print "#{command}\n"
|
29
|
+
# status is a Process::Status
|
30
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
31
|
+
if status.success?
|
32
|
+
print "#{stdout_str}\n"
|
33
|
+
else
|
34
|
+
raise stderr_str;
|
35
|
+
end
|
36
|
+
result = stdout_str.chomp.chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.tag_latest_git_commit(tag, message = 'Sorry, no tag message provided.')
|
40
|
+
command = "git tag -a #{tag} -m \"#{message}\""
|
41
|
+
print "#{command}\n"
|
42
|
+
# status is a Process::Status
|
43
|
+
# -a is annotate
|
44
|
+
# -m is message
|
45
|
+
# ex: git tag -a v1.4 -m "my version 1.4"
|
46
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
47
|
+
if status.success?
|
48
|
+
print "#{stdout_str}\n"
|
49
|
+
else
|
50
|
+
raise stderr_str;
|
51
|
+
end
|
52
|
+
result = stdout_str
|
53
|
+
command = "git push origin #{tag}"
|
54
|
+
print "#{command}\n"
|
55
|
+
# ex: git push origin v1.4
|
56
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
57
|
+
if status.success?
|
58
|
+
print "#{stdout_str}\n"
|
59
|
+
else
|
60
|
+
raise stderr_str;
|
61
|
+
end
|
62
|
+
|
63
|
+
result = "#{result}\n#{stdout_str}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.project_build_number(file_name = PROJECT_BUILD_NUMBER)
|
67
|
+
print "Reading from #{file_name} to get the last project build number\n"
|
68
|
+
file = File.open(file_name, 'r')
|
69
|
+
build_str = file.gets()
|
70
|
+
file.close()
|
71
|
+
|
72
|
+
build_int = build_str.chomp.to_i
|
73
|
+
|
74
|
+
build_int += 1
|
75
|
+
|
76
|
+
build_str = build_int.to_s
|
77
|
+
|
78
|
+
print "Writing into #{file_name} to set the next project build number\n"
|
79
|
+
file = File.open(file_name, 'w+', 0666)
|
80
|
+
file.puts(build_str)
|
81
|
+
file.close()
|
82
|
+
|
83
|
+
build_str
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.get_uuid_from_file(file_name)
|
87
|
+
command = "/usr/libexec/PlistBuddy -c \"Print UUID\" /dev/stdin <<< $(security cms -D -i #{file_name} 2> /dev/null)"
|
88
|
+
print "#{command}\n"
|
89
|
+
# status is a Process::Status
|
90
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
91
|
+
if status.success?
|
92
|
+
stdout_str = stdout_str.chomp
|
93
|
+
print "#{stdout_str}\n"
|
94
|
+
else
|
95
|
+
raise stderr_str;
|
96
|
+
end
|
97
|
+
result = stdout_str
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.copy_provision_file(file_name, uuid)
|
101
|
+
command = "cp #{file_name} ~/Library/MobileDevice/Provisioning\\ Profiles/#{uuid}.mobileprovision"
|
102
|
+
print "#{command}\n"
|
103
|
+
# status is a Process::Status
|
104
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
105
|
+
if status.success?
|
106
|
+
print "#{stdout_str}\n"
|
107
|
+
else
|
108
|
+
raise stderr_str;
|
109
|
+
end
|
110
|
+
result = stdout_str
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.install_provision_file(file_name)
|
114
|
+
uuid = get_uuid_from_file(file_name)
|
115
|
+
copy_provision_file(file_name, uuid)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.install_provision_files(file_names_str)
|
119
|
+
file_names = file_name_str.gsub("\n",'').strip().split(',')
|
120
|
+
file_names.each do |file_name|
|
121
|
+
uuid = get_uuid_from_file(file_name)
|
122
|
+
copy_provision_file(file_name, uuid)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.upload_to_hockey(app_id, api_token, note, file_to_upload)
|
127
|
+
command = "puck -app_id=#{app_id} -api_token=#{api_token} -submit=auto -download=true -notify=true -notes=\"#{note}\" #{file_to_upload}"
|
128
|
+
print "#{command}\n"
|
129
|
+
# status is a Process::Status
|
130
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
131
|
+
if status.success?
|
132
|
+
print "#{stdout_str}\n"
|
133
|
+
else
|
134
|
+
raise stderr_str;
|
135
|
+
end
|
136
|
+
result = stdout_str
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.clean(path)
|
140
|
+
if path.chomp == '/'
|
141
|
+
raise "Are you out of your mind?"
|
142
|
+
end
|
143
|
+
command = "rm -fr #{path}/*"
|
144
|
+
print "#{command}\n"
|
145
|
+
# status is a Process::Status
|
146
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
147
|
+
if status.success?
|
148
|
+
print "#{stdout_str}\n"
|
149
|
+
else
|
150
|
+
raise stderr_str;
|
151
|
+
end
|
152
|
+
result = stdout_str
|
153
|
+
end
|
154
|
+
|
155
|
+
# TODO allow flexibility in USER DEFINED build variables
|
156
|
+
def self.build_project(project, scheme, configuration, build_number, archive_path)
|
157
|
+
command = "xcodebuild -project #{project} -scheme #{scheme} -configuration #{configuration} -destination 'generic/platform=iOS' PROJECT_BUILD_NUMBER=#{build_number} -archivePath #{archive_path} archive"
|
158
|
+
print "#{command}\n"
|
159
|
+
# status is a Process::Status
|
160
|
+
result = 'OK'
|
161
|
+
status = nil
|
162
|
+
stderr_str = ''
|
163
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait|
|
164
|
+
|
165
|
+
t1 = Thread.new do
|
166
|
+
while line = stdout.gets
|
167
|
+
puts line
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
t2 = Thread.new do
|
172
|
+
while line = stderr.gets
|
173
|
+
stderr_str << line
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
status = wait.value
|
178
|
+
t2.value
|
179
|
+
t1.value
|
180
|
+
end
|
181
|
+
|
182
|
+
if status.success?
|
183
|
+
print "#{result}\n"
|
184
|
+
else
|
185
|
+
raise stderr_str;
|
186
|
+
end
|
187
|
+
result
|
188
|
+
end
|
189
|
+
|
190
|
+
# TODO allow flexibility in USER DEFINED build variables
|
191
|
+
def self.build_workspace(workspace, scheme, configuration, build_number, archive_path)
|
192
|
+
command = "xcodebuild -workspace #{workspace} -scheme #{scheme} -configuration #{configuration} -destination 'generic/platform=iOS' PROJECT_BUILD_NUMBER=#{build_number} -archivePath #{archive_path} archive"
|
193
|
+
print "#{command}\n"
|
194
|
+
# status is a Process::Status
|
195
|
+
result = 'OK'
|
196
|
+
status = nil
|
197
|
+
stderr_str = ''
|
198
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait|
|
199
|
+
|
200
|
+
t1 = Thread.new do
|
201
|
+
while line = stdout.gets
|
202
|
+
puts line
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
t2 = Thread.new do
|
207
|
+
while line = stderr.gets
|
208
|
+
stderr_str << line
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
status = wait.value
|
213
|
+
t2.value
|
214
|
+
t1.value
|
215
|
+
end
|
216
|
+
|
217
|
+
if status.success?
|
218
|
+
print "#{result}\n"
|
219
|
+
else
|
220
|
+
raise stderr_str;
|
221
|
+
end
|
222
|
+
result
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.create_export_plist(file_name, key_string_pairs)
|
226
|
+
if !key_string_pairs.is_a? Hash
|
227
|
+
raise "create_export_plist() key_string_pairs must be a Hash\n"
|
228
|
+
end
|
229
|
+
|
230
|
+
xml_prelude = <<EO1
|
231
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
232
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
233
|
+
<plist version="1.0">
|
234
|
+
<dict>
|
235
|
+
<key>provisioningProfiles</key>
|
236
|
+
<dict>
|
237
|
+
EO1
|
238
|
+
xml_postlude = <<EO2
|
239
|
+
</dict>
|
240
|
+
<key>method</key>
|
241
|
+
<string>app-store</string>
|
242
|
+
</dict>
|
243
|
+
</plist>
|
244
|
+
EO2
|
245
|
+
xml_key_string_pairs = ''
|
246
|
+
key_string_pairs.each_pair do |key, string|
|
247
|
+
xml_key_string_pairs << " <key>#{key}</key>\n"
|
248
|
+
xml_key_string_pairs << " <string>#{string}</string>\n"
|
249
|
+
end
|
250
|
+
|
251
|
+
print "Writing into #{file_name}\n"
|
252
|
+
file = File.open(file_name, 'w+', 0666)
|
253
|
+
file.puts("#{xml_prelude}#{xml_key_string_pairs}#{xml_postlude}")
|
254
|
+
file.close()
|
255
|
+
|
256
|
+
return true
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.xcode_path()
|
260
|
+
command = "dirname \"$(xcode-select -p)\""
|
261
|
+
print "#{command}\n"
|
262
|
+
# status is a Process::Status
|
263
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
264
|
+
if status.success?
|
265
|
+
print "#{stdout_str}\n"
|
266
|
+
else
|
267
|
+
raise stderr_str;
|
268
|
+
end
|
269
|
+
result = stdout_str.chomp.chomp
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.export_to_ipa(archive, plist, ipa_path)
|
273
|
+
command = "xcodebuild -exportArchive -exportOptionsPlist #{plist} -archivePath #{archive} -exportPath #{ipa_path}"
|
274
|
+
print "#{command}\n"
|
275
|
+
# status is a Process::Status
|
276
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
277
|
+
if status.success?
|
278
|
+
print "#{stdout_str}\n"
|
279
|
+
else
|
280
|
+
raise stderr_str;
|
281
|
+
end
|
282
|
+
result = stdout_str
|
283
|
+
end
|
284
|
+
|
285
|
+
# May want to stream stderr to console too, because altool uses stderr instead of stdout
|
286
|
+
def self.validate_with_itunes(user, password, ipa)
|
287
|
+
# get altools path
|
288
|
+
xcode_path = self.xcode_path
|
289
|
+
altool = "#{xcode_path}/Applications/Application\\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
|
290
|
+
command = "#{altool} --validate-app --type ios -u \"#{user}\" -p \"#{password}\" -f #{ipa}"
|
291
|
+
print "#{command}\n"
|
292
|
+
result = 'OK'
|
293
|
+
status = nil
|
294
|
+
stderr_str = ''
|
295
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait|
|
296
|
+
|
297
|
+
t1 = Thread.new do
|
298
|
+
while line = stdout.gets
|
299
|
+
puts line
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
t2 = Thread.new do
|
304
|
+
while line = stderr.gets
|
305
|
+
puts line
|
306
|
+
stderr_str << line
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
status = wait.value
|
311
|
+
t2.value
|
312
|
+
t1.value
|
313
|
+
end
|
314
|
+
|
315
|
+
if status.success?
|
316
|
+
print "#{result}\n"
|
317
|
+
else
|
318
|
+
raise stderr_str;
|
319
|
+
end
|
320
|
+
result
|
321
|
+
end
|
322
|
+
|
323
|
+
# May want to stream stderr to console too, because altool uses stderr instead of stdout
|
324
|
+
def self.upload_to_itunes(user, password, ipa)
|
325
|
+
# get altools path
|
326
|
+
xcode_path = self.xcode_path
|
327
|
+
altool = "#{xcode_path}/Applications/Application\\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
|
328
|
+
command = "#{altool} --upload-app --type ios -u \"#{user}\" -p \"#{password}\" -f #{ipa}"
|
329
|
+
print "#{command}\n"
|
330
|
+
result = 'OK'
|
331
|
+
status = nil
|
332
|
+
stderr_str = ''
|
333
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait|
|
334
|
+
|
335
|
+
t1 = Thread.new do
|
336
|
+
while line = stdout.gets
|
337
|
+
puts line
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
t2 = Thread.new do
|
342
|
+
while line = stderr.gets
|
343
|
+
puts line
|
344
|
+
stderr_str << line
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
status = wait.value
|
349
|
+
t2.value
|
350
|
+
t1.value
|
351
|
+
end
|
352
|
+
|
353
|
+
if status.success?
|
354
|
+
print "#{result}\n"
|
355
|
+
else
|
356
|
+
raise stderr_str;
|
357
|
+
end
|
358
|
+
result
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_build_ios
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Rogers of HS2 Solutions
|
8
|
+
- Don Bales of HS2 Solutions
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-09-15 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A Ruby library to help write scripts to build IOS mobile apps written
|
15
|
+
during HS2's 2017 Hackathon. Please use RubyBuildIOS in the subject line when emailing
|
16
|
+
Dave.
|
17
|
+
email: david.rogers@hs2solutions.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- README.md
|
23
|
+
- example.rb
|
24
|
+
- lib/ruby_build_ios.rb
|
25
|
+
homepage: https://rubygems.org/gems/ruby_build_ios
|
26
|
+
licenses:
|
27
|
+
- MIT
|
28
|
+
metadata: {}
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 2.6.11
|
46
|
+
signing_key:
|
47
|
+
specification_version: 4
|
48
|
+
summary: Ruby Build IOS
|
49
|
+
test_files: []
|