iosdeveloper 0.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.
- data/bin/iosdeveloper +119 -0
- data/lib/iosdeveloper.rb +6 -0
- data/lib/iosdeveloper/profile.rb +17 -0
- data/lib/iosdeveloper/provisioning_portal.rb +115 -0
- data/lib/iosdeveloper/version.rb +3 -0
- metadata +106 -0
data/bin/iosdeveloper
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
require 'io/console'
|
4
|
+
begin # XXX: Remove this begin/rescue before distributing your app
|
5
|
+
require 'iosdeveloper'
|
6
|
+
rescue LoadError
|
7
|
+
STDERR.puts "In development, you need to use `bundle exec bin/iosdeveloper` to run your app"
|
8
|
+
STDERR.puts "At install-time, RubyGems will make sure lib, etc. are in the load path"
|
9
|
+
STDERR.puts "Feel free to remove this message from bin/adt now"
|
10
|
+
exit 64
|
11
|
+
end
|
12
|
+
|
13
|
+
DEFAULT_CONFIG_FILE_LOCATION = Dir.pwd + "/iosdeveloper.rc.yml"
|
14
|
+
|
15
|
+
include GLI::App
|
16
|
+
|
17
|
+
program_desc 'iOS Developer Tools'
|
18
|
+
|
19
|
+
version IOSDeveloper::VERSION
|
20
|
+
|
21
|
+
desc 'Location of the configuration file'
|
22
|
+
arg_name 'config_file'
|
23
|
+
default_value DEFAULT_CONFIG_FILE_LOCATION
|
24
|
+
flag [:c, 'config-file']
|
25
|
+
|
26
|
+
desc 'Creates the configuration file containing username, password and optionally team name'
|
27
|
+
command :init do |c|
|
28
|
+
c.desc 'Apple ID'
|
29
|
+
c.arg_name 'username'
|
30
|
+
c.flag [:u, :username]
|
31
|
+
|
32
|
+
c.desc 'Password'
|
33
|
+
c.arg_name 'password'
|
34
|
+
c.flag [:p, :password]
|
35
|
+
|
36
|
+
c.desc 'Team name'
|
37
|
+
c.arg_name 'team_name'
|
38
|
+
c.flag [:t, :team]
|
39
|
+
c.action do |global_options, options, args|
|
40
|
+
File.open(global_options[:c]||DEFAULT_CONFIG_FILE_LOCATION, 'w', 0600) do |file|
|
41
|
+
YAML.dump({"username" => options[:username], "password" => options[:password], "team" => options[:team]}, file)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'List add registered devices'
|
47
|
+
command 'list-devices' do |c|
|
48
|
+
c.action do |global_options, options, args|
|
49
|
+
devices = portal(global_options).list_devices
|
50
|
+
puts ""
|
51
|
+
puts "Registered devices:"
|
52
|
+
puts devices
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Registers a new device'
|
57
|
+
arg_name 'DEVICE_NAME DEVICE_ID'
|
58
|
+
command 'add-device' do |c|
|
59
|
+
c.action do |global_options, options, args|
|
60
|
+
device_name = args.shift
|
61
|
+
help_now!('device id is required') if device_name.nil?
|
62
|
+
device_id = args.shift
|
63
|
+
help_now!('device id is required') if device_id.nil?
|
64
|
+
portal(global_options).add_device(device_name, device_id)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'Downloads provisioning profile'
|
69
|
+
arg_name 'PROFILE_ID'
|
70
|
+
command 'download-profile' do |c|
|
71
|
+
c.action do |global_options, options, args|
|
72
|
+
profile_id = args.shift
|
73
|
+
file_name = "#{profile_id}.mobileprovision"
|
74
|
+
portal(global_options).download_profile(profile_id, file_name)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
desc 'List provisioning profiles'
|
79
|
+
command 'list-profiles' do |c|
|
80
|
+
c.action do |global_options, options, args|
|
81
|
+
profiles = portal(global_options).list_profiles
|
82
|
+
puts ""
|
83
|
+
profiles.each do |profile|
|
84
|
+
puts "#{profile.id}|#{profile.name}|#{profile.app_id}|#{profile.status}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def portal global_options
|
90
|
+
config_file = YAML::load(File.read(global_options[:c]||DEFAULT_CONFIG_FILE_LOCATION))
|
91
|
+
username = config_file['username'] || raise("username not provided")
|
92
|
+
password = config_file['password'] || raise("password not provided")
|
93
|
+
team_name = config_file['team']
|
94
|
+
|
95
|
+
IOSDeveloper::ProvisioningPortal.new(username, password, team_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
pre do |global, command, options, args|
|
99
|
+
# Pre logic here
|
100
|
+
# Return true to proceed; false to abort and not call the
|
101
|
+
# chosen command
|
102
|
+
# Use skips_pre before a command to skip this block
|
103
|
+
# on that command only
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
post do |global, command, options, args|
|
108
|
+
# Post logic here
|
109
|
+
# Use skips_post before a command to skip this
|
110
|
+
# block on that command only
|
111
|
+
end
|
112
|
+
|
113
|
+
on_error do |exception|
|
114
|
+
# Error logic here
|
115
|
+
# return false to skip default error handling
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
exit run(ARGV)
|
data/lib/iosdeveloper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module IOSDeveloper
|
2
|
+
|
3
|
+
class Profile
|
4
|
+
|
5
|
+
def initialize(id, name, app_id, status, type)
|
6
|
+
@id = id
|
7
|
+
@name = name
|
8
|
+
@app_id = app_id
|
9
|
+
@status = status
|
10
|
+
@type = type
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :id, :name, :app_id, :status, :type
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "mechanize"
|
2
|
+
|
3
|
+
module IOSDeveloper
|
4
|
+
|
5
|
+
class ProvisioningPortal
|
6
|
+
|
7
|
+
DEVICES_URL = "https://developer.apple.com/ios/manage/devices/index.action"
|
8
|
+
PROFILES_URL = "https://developer.apple.com/ios/manage/provisioningprofiles/index.action"
|
9
|
+
DISTRIBUTION_PROFILES_URL = "https://developer.apple.com/ios/manage/provisioningprofiles/viewDistributionProfiles.action"
|
10
|
+
ADD_DEVICE_URL = "https://developer.apple.com/ios/manage/devices/add.action"
|
11
|
+
|
12
|
+
def initialize (login, password, team_name)
|
13
|
+
@agent = Mechanize.new
|
14
|
+
@username = login
|
15
|
+
@password = password
|
16
|
+
@team_name = team_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_page url
|
20
|
+
page = @agent.get(url)
|
21
|
+
login_form = page.form_with(:name => 'appleConnectForm')
|
22
|
+
if login_form
|
23
|
+
login(login_form)
|
24
|
+
page = @agent.get(url)
|
25
|
+
end
|
26
|
+
team_select_form = page.form_with(:name => 'saveTeamSelection')
|
27
|
+
if team_select_form
|
28
|
+
page = select_team(team_select_form)
|
29
|
+
end
|
30
|
+
page
|
31
|
+
end
|
32
|
+
|
33
|
+
def select_team(form)
|
34
|
+
team_list = form.field_with(:name => 'memberDisplayId')
|
35
|
+
if @team_name.nil? || @team_name == ''
|
36
|
+
team_option = team_list.options.first
|
37
|
+
else
|
38
|
+
team_option = team_list.option_with(:text => @team_name)
|
39
|
+
end
|
40
|
+
puts "Selecting team '#{team_option.text}'."
|
41
|
+
team_option.select
|
42
|
+
form.click_button(form.button_with(:name => 'action:saveTeamSelection!save'))
|
43
|
+
end
|
44
|
+
|
45
|
+
def login(form)
|
46
|
+
puts "Logging in with Apple ID '#{@username}'."
|
47
|
+
form.theAccountName = @username
|
48
|
+
form.theAccountPW = @password
|
49
|
+
form.submit
|
50
|
+
end
|
51
|
+
|
52
|
+
def list_devices
|
53
|
+
page = get_page(DEVICES_URL)
|
54
|
+
page.search("#removeDevice table tbody tr").map do |item|
|
55
|
+
device_name = item.at(".name span").text
|
56
|
+
device_id = item.at(".id").text
|
57
|
+
"#{device_name} - #{device_id}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_device(name, id)
|
62
|
+
page = get_page(ADD_DEVICE_URL)
|
63
|
+
|
64
|
+
form = page.form_with(:name => 'add')
|
65
|
+
form["deviceNameList[0]"] = name
|
66
|
+
form["deviceNumberList[0]"] = id
|
67
|
+
page = form.submit
|
68
|
+
|
69
|
+
error_message = page.search(".errorMessage li span")
|
70
|
+
raise error_message.text unless error_message.empty?
|
71
|
+
puts "Added device: #{id}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def list_profiles
|
75
|
+
get_development_profiles + get_distribution_profiles
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_development_profiles
|
79
|
+
get_profiles(PROFILES_URL, 'development')
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_distribution_profiles
|
83
|
+
get_profiles(DISTRIBUTION_PROFILES_URL, 'distribution')
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_profiles(url, type)
|
87
|
+
page = get_page(url)
|
88
|
+
page.search("#remove table tbody tr").map do |item|
|
89
|
+
name = item.at(".profile span").text
|
90
|
+
app_id = item.at(".appid").text
|
91
|
+
status = item.at(".statusXcode").child.text.strip
|
92
|
+
profile_id = profile_id(item.at(".profile a").attr("href"))
|
93
|
+
Profile.new(profile_id, name, app_id, status, type)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def profile_id(display_url)
|
98
|
+
/provDisplayId=(\w+)/.match(display_url)[1]
|
99
|
+
end
|
100
|
+
|
101
|
+
def download_profile(profile_name, file_name)
|
102
|
+
page = get_page(PROFILES_URL)
|
103
|
+
page.search("#remove table tbody tr").each do |item|
|
104
|
+
name = item.at(".profile span").text
|
105
|
+
if name == profile_name
|
106
|
+
download_link = item.at(".action a").attr("href")
|
107
|
+
@agent.get(download_link).save(file_name)
|
108
|
+
puts "Saved #{profile_name} profile in #{file_name}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iosdeveloper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marcin Kwiatkowski
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70128864676580 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70128864676580
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rdoc
|
27
|
+
requirement: &70128864676140 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70128864676140
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: aruba
|
38
|
+
requirement: &70128864675720 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70128864675720
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: gli
|
49
|
+
requirement: &70128864675200 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - =
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.5.3
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70128864675200
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mechanize
|
60
|
+
requirement: &70128864674700 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - =
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 2.5.1
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70128864674700
|
69
|
+
description: Command line tools for accessing iOS Provisioning Portal
|
70
|
+
email: marcin.kwiatkowski@hotmail.com
|
71
|
+
executables:
|
72
|
+
- iosdeveloper
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- bin/iosdeveloper
|
77
|
+
- lib/iosdeveloper/version.rb
|
78
|
+
- lib/iosdeveloper/provisioning_portal.rb
|
79
|
+
- lib/iosdeveloper/profile.rb
|
80
|
+
- lib/iosdeveloper.rb
|
81
|
+
homepage: https://github.com/marcinkwiatkowski/iosdeveloper
|
82
|
+
licenses: []
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.8.15
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: iOS Developer Tools
|
106
|
+
test_files: []
|