appsendr 0.0.6 → 1.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.
@@ -1,52 +0,0 @@
1
- module AppSendr::Command
2
- class Collaborators < Build ## Inherhits from Deploy
3
-
4
- def index
5
- if in_project_dir?
6
- unless has_project_droppr?
7
- require_project_droppr
8
- return
9
- end
10
-
11
- testers = appsendr.collaborators(read_app_id)
12
- if testers["message"].size > 0
13
- message "Your collaborators"
14
- i = 0
15
- display testers["message"].map {|app, id|
16
- "#{i+=1}. #{app['name']} - #{app['email']}"
17
- }.join("\n")
18
- else
19
- display "You have no collaborators."
20
- end
21
- end
22
- end
23
-
24
-
25
- def add
26
-
27
- if require_project(2,"add collaborators","an email", true)
28
- email = args.shift.strip
29
-
30
- begin
31
- response = appsendr.add_collaborator(read_app_id,email)
32
- rescue RestClient::RequestFailed => e
33
- message "Errors"
34
- response = JSON.parse(e.http_body)
35
- response['message'].each{|err|
36
- display err.join(" ")
37
- }
38
- end
39
-
40
- end
41
- end
42
-
43
- def remove
44
- if require_project(1,"remove testers","an email")
45
- entered_email = args.shift.strip
46
-
47
- appsendr.remove_collaborator(read_app_id,entered_email)
48
-
49
- end
50
- end
51
- end
52
- end
@@ -1,36 +0,0 @@
1
- require 'optparse'
2
-
3
- module AppSendr::Command
4
- class Ipa < Build ## Inherhits from Deploy
5
- def create
6
-
7
- app_name = args.join(" ").strip
8
- @app_dir = Dir.pwd
9
- @app_path = @app_dir+"/#{app_name}"
10
-
11
- payload_path = @app_dir+"/Payload"
12
- ipa_path = @app_dir+"/#{ipa_app_name(app_name).delete('^A-Za-z0-9\.\_\-')}"
13
-
14
-
15
- FileUtils.rm_rf payload_path
16
- Dir.mkdir(payload_path)
17
- #display "#{@app_path.cl_escape} #{payload_path.cl_escape}/#{app_name.cl_escape}"
18
- `cp -r #{@app_path.cl_escape} #{payload_path.cl_escape+"/"+app_name.cl_escape}`
19
- build_ipa(payload_path.cl_escape,ipa_path.cl_escape)
20
-
21
- FileUtils.rm_rf payload_path
22
- message "IPA Built"
23
-
24
- #return ipa_path
25
- end
26
-
27
- def codesign
28
- # export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
29
- # codesign –f –s “iPhone Developer: <insert your identity>” <appname>.app/<appname>
30
- #
31
- # You can check the Authorities by which an app is currently signed with the following command:
32
- #
33
- # codesign –d –vv <appname>.app/<appname>
34
- end
35
- end
36
- end
@@ -1,56 +0,0 @@
1
- require 'optparse'
2
-
3
- module AppSendr::Command
4
- class Deploy < Build ## Inherhits from Deploy
5
-
6
- def index
7
- #
8
- # opts = OptionParser.new
9
- # opts.on('-m', '--message') { output_version ; exit 0 }
10
- #
11
- # opts.parse!(args) rescue return false
12
- #
13
- #
14
- notify = option_exists?('--notify', false)
15
- is_public = option_exists?('--public', false)
16
-
17
- @configuration = load_configuration
18
- if require_project(1,"deploy","your active configuration name",true)
19
-
20
- @app_dir = path_to_app_dir
21
- @app_path = @app_dir+"/#{app_name}"
22
- if @app_name
23
-
24
- @notes = ask_for_notes
25
- message "Deploying #{@app_name}"
26
-
27
- message "Building IPA File"
28
-
29
- @ipa_path = build_ipa_with_app_at_path
30
- info = app_info
31
- bundle_identifier ||= info['CFBundleIdentifier']
32
- icon_path = icon_path(info)
33
- if is_file_to_large?(@ipa_path)
34
- upload_large_ipa(read_app_id,@ipa_path, profile_path,is_public,notify,@notes,bundle_identifier,icon_path)
35
- else
36
- message "Uploading IPA"
37
- appsendr.upload(read_app_id,@ipa_path, profile_path,is_public,notify,@notes,bundle_identifier,icon_path)
38
- message "App deployed"
39
-
40
- end
41
- FileUtils.rm_rf @ipa_path
42
- else
43
- error "No .app file was built for the configuration \"#{@configuration}\". Compile your app or use the \"build\" command."
44
- end
45
- end
46
- end
47
-
48
- protected
49
- def ask_for_notes
50
- print "Release Notes: "
51
- notes = ask
52
- return notes.strip
53
- end
54
-
55
- end
56
- end
@@ -1,63 +0,0 @@
1
- module AppSendr::Command
2
- class Groups < Base
3
- def index #output testers
4
- if in_project_dir?
5
-
6
- groups = appsendr.groups(read_app_id)
7
- if groups["message"].size > 0
8
- message "Your groups"
9
- i = 0
10
- display groups["message"].map {|app, id|
11
- "#{i+=1}. #{app['name'].ljust(35)}"
12
- }.join("\n")
13
- else
14
- display "You have no groups."
15
- end
16
- else
17
- error("You are not in a project directory")
18
- end
19
- end
20
-
21
- def add
22
- if in_project_dir?
23
- name = args.join(" ").strip
24
- appsendr.add_group(read_app_id,name)
25
- message "Group added"
26
- else
27
- error("You are not in a project directory")
28
- end
29
- end
30
-
31
- def remove
32
- if in_project_dir?
33
- name = args.join(" ").strip
34
- appsendr.remove_group(read_app_id,name)
35
- message "Removed group"
36
- else
37
- error("You are not in a project directory")
38
- end
39
- end
40
-
41
- def add_tester #<group> #<email>
42
-
43
- if in_project_dir?
44
- email = args.shift.strip
45
- name = args.join(" ").strip
46
- appsendr.add_group_tester(read_app_id,name, email)
47
- message "Added tester to group"
48
- else
49
- error("You are not in a project directory")
50
- end
51
- end
52
- def remove_tester #<group> #<email>
53
- if in_project_dir?
54
- email = args.shift.strip
55
- name = args.join(" ").strip
56
- appsendr.remove_group_tester(read_app_id,name, email)
57
- message "Added tester to group"
58
- else
59
- error("You are not in a project directory")
60
- end
61
- end
62
- end
63
- end
@@ -1,103 +0,0 @@
1
- module AppSendr::Command
2
- class Help < Base
3
- class HelpGroup < Array
4
- attr_reader :title
5
-
6
- def initialize(title)
7
- @title = title
8
- end
9
-
10
- def command(name, description)
11
- self << [name, description]
12
- end
13
-
14
- def space
15
- self << ['', '']
16
- end
17
- end
18
-
19
- def self.groups
20
- @groups ||= []
21
- end
22
-
23
- def self.group(title, &block)
24
- groups << begin
25
- group = HelpGroup.new(title)
26
- yield group
27
- group
28
- end
29
- end
30
-
31
- def self.create_default_groups!
32
- group 'Commands' do |group|
33
- group.command 'help', 'show this usage'
34
- group.command 'version', 'show the gem version'
35
- group.space
36
- group.command 'list', 'list your apps'
37
- group.command 'link', 'link your app with an exsiting one in appsendr'
38
- group.command 'create <name>', 'create a new app'
39
- group.space
40
- group.command 'url', 'get the latest version install url. pass --copy to copy to the clipboard'
41
- group.space
42
- group.command 'build <active configuration>', 'build your xcode project and deploy'
43
- group.command 'build:clean', 'clean your xcode project'
44
- group.space
45
- group.command 'deploy <active configuration>', 'deploy the current build. pass --notify to send notification to all testers'
46
- group.space
47
- group.command 'testers', 'list testers'
48
- group.command 'testers:add <email> <name>', 'add a tester'
49
- group.command 'testers:remove <email> ', 'remove a tester'
50
- group.command 'testers:clear', 'remove all testers'
51
- group.command 'testers:notify <group>', 'notify testers about the latest build. group is optional.'
52
- group.command 'testers:devices', 'devices of your testers'
53
-
54
- # group.space
55
- # group.command 'groups', 'list groups'
56
- # group.command 'groups:add <name>', 'add group'
57
- # group.command 'groups:remove <name>', 'remove group'
58
- # group.command 'groups:add_tester <email> <group name>', 'add tester to group'
59
- # group.command 'groups:remove_tester <email> <group name>', 'remove tester from group'
60
-
61
- group.space
62
- group.command 'collaborators', 'list collaborators'
63
- group.command 'collaborators:add <email>', 'add collaborators'
64
- group.command 'collaborators:remove <email>','remove collaborators'
65
- group.space
66
- group.command 'auth:login', 'reauthorize account'
67
- end
68
-
69
- end
70
-
71
- def index
72
- display usage
73
- end
74
-
75
- def version
76
- display AppSendr::Client.version
77
- end
78
-
79
- def usage
80
- longest_command_length = self.class.groups.map do |group|
81
- group.map { |g| g.first.length }
82
- end.flatten.max
83
-
84
- self.class.groups.inject(StringIO.new) do |output, group|
85
- output.puts "=== %s" % group.title
86
- output.puts
87
-
88
- group.each do |command, description|
89
- if command.empty?
90
- output.puts
91
- else
92
- output.puts "%-*s # %s" % [longest_command_length, command, description]
93
- end
94
- end
95
-
96
- output.puts
97
- output
98
- end.string
99
- end
100
- end
101
- end
102
-
103
- AppSendr::Command::Help.create_default_groups!
@@ -1,375 +0,0 @@
1
- module AppSendr::Command
2
- class Portal < Base
3
-
4
- attr_accessor :credentials
5
-
6
- require 'rubygems'
7
- require 'mechanize'
8
-
9
- @@agent = Mechanize.new
10
- @@agent.user_agent_alias = 'Mac FireFox'
11
- @@agent.follow_meta_refresh = true
12
-
13
- @@available_devices = []
14
- @@available_profiles = []
15
-
16
- LOGIN_URL = 'https://developer.apple.com/ios/manage/overview/index.action'
17
- DEVICES_URL = "https://developer.apple.com/ios/manage/devices/index.action"
18
- DEVICE_BULK_UPLOAD_URL = "http://developer.apple.com/ios/manage/devices/saveupload.action"
19
- SAVE_TEAM_URL = "http://developer.apple.com/membercenter/saveTeamSelection.action"
20
-
21
- DEV_PROVISIONING_PROFILE_URL = "https://developer.apple.com/ios/manage/provisioningprofiles/index.action"
22
- DIST_PROVISIONING_PROFILE_URL = "https://developer.apple.com/ios/manage/provisioningprofiles/viewDistributionProfiles.action"
23
-
24
- CREATE_ADHOC_PROFILE_URL = "http://developer.apple.com/ios/manage/provisioningprofiles/create.action?type=2"
25
- DOWNLOAD_PROFILE_URL_WO_ID ="/ios/manage/provisioningprofiles/download.action?blobId="
26
- EDIT_PROFILE_URL_WO_ID = "/ios/manage/provisioningprofiles/edit.action?provDisplayId="
27
-
28
-
29
- def index
30
-
31
- result = check_for_manual_login
32
-
33
- if result
34
- @available_devices = get_devices
35
- @available_dev_profiles = development_provisioning_profiles
36
- @available_dist_profiles = distribution_provisioning_profiles
37
-
38
- display "#{@available_devices.length} Devices"
39
- display "#{@available_dev_profiles.length} Development Profiles"
40
- display "#{@available_dist_profiles.length} Distribution Profiles"
41
-
42
- end
43
- end
44
-
45
- def devices
46
- result = check_for_manual_login
47
-
48
- if result
49
- @available_devices = get_devices
50
- @available_devices.each{|device|
51
- display "#{device[:name]} - #{device[:id]}"
52
- }
53
- end
54
- end
55
-
56
- def profiles
57
- result = check_for_manual_login
58
-
59
- if result
60
- @available_dev_profiles = development_provisioning_profiles
61
- @available_dist_profiles = distribution_provisioning_profiles
62
-
63
- display "\nDevelopment Profiles\n"
64
- @available_dev_profiles.each{|profile|
65
-
66
- display "#{profile[:name]} - #{profile[:app_id]}"
67
- }
68
- display "\nDistribution Profiles\n"
69
- @available_dist_profiles.each{|profile|
70
- display "#{profile[:name]} - #{profile[:app_id]}"
71
- }
72
-
73
-
74
- end
75
- end
76
-
77
- def update
78
-
79
- @remote_devices = appsendr.devices(nil,false)
80
- @available_devices = get_devices
81
-
82
- ## get devices for users for this app
83
- ## get all devices from portal
84
- ## reconcile
85
- ## add device not on portal
86
- ## get profile for app
87
- ##
88
- end
89
-
90
-
91
- private
92
- def check_for_manual_login
93
- username = extract_option('--username', false)
94
- password = extract_option('--password', false)
95
-
96
- result = false
97
- if username and password
98
- result = login(username,password)
99
-
100
- error "\nAuthentication failed" unless result
101
-
102
- else
103
- result = login(user,pass)
104
- end
105
-
106
- return result
107
- end
108
-
109
-
110
- ###
111
-
112
-
113
- def login(username, password)
114
-
115
- # Get login page
116
- #puts "- fetching login page"
117
- #page = agent.get('https://phobos.apple.com/WebObjects/MZLabel.woa/wa/default')
118
- page = @@agent.get(LOGIN_URL)
119
-
120
-
121
- # Submit form to login
122
- login_form = page.forms.first
123
- login_form['theAccountName']=username
124
- login_form['theAccountPW']=password
125
- page = @@agent.submit(login_form)
126
-
127
- # Fail if it looks like we ended up back at a login page
128
- if page.form('appleConnectForm')
129
- #puts "Error: Login failed"
130
- return nil
131
- #exit
132
- else
133
- select_form = page.form('saveTeamSelection')
134
- if select_form
135
- options = []
136
- select_form.fields.first.options.each{|option|
137
- display "#{options.length + 1}. #{option.text}"
138
- options.push([option.text,option.value])
139
-
140
- }
141
- print "Enter the # for the account you wish to login to: "
142
- selection = ask
143
- if selection.to_i > (options.length )
144
- error "Invalid selection"
145
- return nil
146
-
147
- end
148
-
149
- team = options[selection.to_i - 1]
150
- select_form['memberDisplayId'] = team[1]
151
- page = @@agent.submit(select_form, select_form.buttons[1])
152
- return page
153
- else
154
- return page
155
- end
156
- end
157
- end
158
-
159
- def get_details(username, password)
160
- if login(username,password)
161
- @available_devices = get_devices
162
- @available_dev_profiles = development_provisioning_profiles
163
- @available_dist_profiles = distribution_provisioning_profiles
164
- display ""
165
-
166
-
167
- end
168
- end
169
-
170
-
171
- #####
172
- # provisioning
173
- def get_devices
174
- page = @@agent.get(DEVICES_URL)
175
- table = page.at("//table/tbody") # This passes through to hpricot
176
- devices = []
177
- return devices unless table
178
- table.children.each{|tr|
179
- children = tr.children
180
- device_name = children[2].content.strip
181
- device_id = children[4].content.strip
182
- devices.push({:name => device_name, :id => device_id })
183
- }
184
-
185
- return devices;
186
-
187
- end
188
-
189
- def upload_bulk_file
190
- temp_file = TempFile.new('bulk_upload')
191
- temp_file.write(device_file)
192
- temp_file.close
193
- @@agent.post(DEVICE_BULK_UPLOAD_URL, {:upload => temp_file})
194
- end
195
-
196
-
197
-
198
- #####
199
- # provisioning
200
-
201
- def provisioning_profiles(url)
202
- page = @@agent.get(url)
203
- table = page.at("//table/tbody")
204
- profiles = []
205
- return profiles unless table
206
-
207
- table.children.each{|tr|
208
- children = tr.children
209
- cert_key = children[0].children[0]['value'].strip
210
- cert_name = children[2].content.strip
211
- app_id = children[4].content.strip
212
- profiles.push({:name => cert_name, :id => cert_key, :app_id => app_id })
213
- #p children
214
- }
215
- return profiles
216
- end
217
-
218
- def development_provisioning_profiles
219
- provisioning_profiles(DEV_PROVISIONING_PROFILE_URL)
220
- end
221
-
222
- def distribution_provisioning_profiles
223
-
224
- provisioning_profiles(DIST_PROVISIONING_PROFILE_URL)
225
-
226
- end
227
-
228
-
229
- def download_provisioning_profile(id)
230
- page = @@agent.get(DOWNLOAD_PROFILE_URL_WO_ID+id)
231
- return page
232
- end
233
-
234
- def edit_provisioning_profile(id)
235
- page = @@agent.get(EDIT_PROFILE_URL_WO_ID+id)
236
- end
237
-
238
- def create_provisioning_profile
239
- page = @@agent.get(CREATE_ADHOC_PROFILE_URL) #adhoc profiles
240
- create_form = page.forms.first
241
-
242
- end
243
-
244
- ## credentials
245
-
246
- def user # :nodoc:
247
- get_credentials
248
- @credentials[0]
249
- end
250
-
251
- def pass # :nodoc:
252
- get_credentials
253
- @credentials[1]
254
- end
255
-
256
-
257
- def reauthorize
258
- user_pass = ask_for_credentials
259
- @credentials = auth_credentials(user_pass[0],user_pass[1])
260
- write_credentials
261
- end
262
-
263
- def auth_credentials(username,password)
264
- login_agent = Mechanize.new
265
-
266
- page = login_agent.get(LOGIN_URL)
267
-
268
-
269
- # Submit form to login
270
- login_form = page.forms.first
271
- login_form['theAccountName']=username
272
- login_form['theAccountPW']=password
273
- page = login_agent.submit(login_form);
274
- # Fail if it looks like we ended up back at a login page
275
- if (!page.form('appleConnectForm').nil?)
276
- return false
277
- else
278
- return [username,password]
279
- end
280
- end
281
-
282
- def get_credentials # :nodoc:
283
- return if @credentials
284
- unless @credentials = read_credentials
285
- user_pass = ask_for_credentials
286
-
287
- @credentials = auth_credentials(user_pass[0],user_pass[1])
288
- retry unless @credentials
289
- save_credentials
290
- end
291
- @credentials
292
- end
293
-
294
- def read_credentials
295
- File.exists?(credentials_file) and File.read(credentials_file).split("\n")
296
- end
297
-
298
- def echo_off
299
- system "stty -echo"
300
- end
301
-
302
- def echo_on
303
- system "stty echo"
304
- end
305
-
306
- def ask_for_credentials
307
- puts "Enter your Apple Developer credentials. (These are never sent to AppSendr)"
308
-
309
- print "Username: "
310
- user = ask
311
-
312
- print "Password: "
313
- password = ask_for_password
314
-
315
- [ user, password ]
316
- end
317
-
318
- def ask_for_password
319
- echo_off
320
- password = ask
321
- puts
322
- echo_on
323
- return password
324
- end
325
-
326
- def save_credentials
327
- begin
328
- write_credentials
329
- # if self.credentials
330
- # delete_credentials
331
- # raise e unless retry_login?
332
- #
333
- # display "\nAuthentication failed"
334
- # user_pass = ask_for_credentials
335
- # @credentials = auth_credentials(user_pass[0],user_pass[1])
336
- # retry
337
- rescue Exception => e
338
- delete_credentials
339
- end
340
- end
341
-
342
- def retry_login?
343
- @login_attempts ||= 0
344
- @login_attempts += 1
345
- @login_attempts < 3
346
- end
347
-
348
- def write_credentials
349
- FileUtils.mkdir_p(File.dirname(credentials_file))
350
- File.open(credentials_file, 'w') do |f|
351
- f.puts self.credentials
352
- end
353
- set_credentials_permissions
354
- end
355
-
356
- def set_credentials_permissions
357
- FileUtils.chmod 0700, File.dirname(credentials_file)
358
- FileUtils.chmod 0600, credentials_file
359
- end
360
-
361
- def delete_credentials
362
- FileUtils.rm_f(credentials_file)
363
- end
364
-
365
- def credentials_file
366
- "#{home_directory}/#{AppSendr::APPDROPPR_DIR}/portal_credentials"
367
- end
368
-
369
- def credentials_setup?
370
- File.exist?(credentials_file)
371
- end
372
-
373
-
374
- end
375
- end