Class: FastlaneCore::DeveloperCenter

Inherits:
Object
  • Object
show all
Includes:
Capybara::DSL
Defined in:
lib/fastlane_core/developer_center/developer_center.rb,
lib/fastlane_core/developer_center/developer_center_login.rb,
lib/fastlane_core/developer_center/developer_center_helper.rb

Defined Under Namespace

Classes: DeveloperCenterGeneralError, DeveloperCenterLoginError

Constant Summary collapse

DEVELOPER_CENTER_URL =
"https://developer.apple.com/devcenter/ios/index.action"
PROFILES_URL =
"https://developer.apple.com/account/ios/profile/profileList.action?type=production"
TMP_FOLDER =
"/tmp/fastlane_core/"

Instance Method Summary collapse

Constructor Details

#initializeDeveloperCenter

Returns a new instance of DeveloperCenter.



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
# File 'lib/fastlane_core/developer_center/developer_center.rb', line 29

def initialize
  FileUtils.mkdir_p TMP_FOLDER
  
  Capybara.run_server = false
  Capybara.default_driver = :poltergeist
  Capybara.javascript_driver = :poltergeist
  Capybara.current_driver = :poltergeist
  Capybara.app_host = DEVELOPER_CENTER_URL

  # Since Apple has some SSL errors, we have to configure the client properly:
  # https://github.com/ariya/phantomjs/issues/11239
  Capybara.register_driver :poltergeist do |a|
    conf = ['--debug=no', '--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1']
    Capybara::Poltergeist::Driver.new(a, {
      phantomjs: Phantomjs.path,
      phantomjs_options: conf,
      phantomjs_logger: File.open("#{TMP_FOLDER}/poltergeist_log.txt", "a"),
      js_errors: false
    })
  end

  page.driver.headers = { "Accept-Language" => "en" }

  self.
end

Instance Method Details

#click_nextObject



26
27
28
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 26

def click_next
  wait_for_elements('.button.small.blue.right.submit').last.click
end

#download_file(url) ⇒ Object

Download a file from the dev center, by using a HTTP client. This will return the content of the file



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 4

def download_file(url)
  Helper.log.info "Downloading profile..."
  host = Capybara.current_session.current_host
  url = [host, url].join('')

  cookieString = ""
  
  page.driver.cookies.each do |key, cookie|
    cookieString << "#{cookie.name}=#{cookie.value};" # append all known cookies
  end 
  
  data = open(url, {'Cookie' => cookieString}).read

  raise "Something went wrong when downloading the file from the Dev Center" unless data
  Helper.log.info "Successfully downloaded provisioning profile"
  return data
end

#error_occured(ex) ⇒ Object



30
31
32
33
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 30

def error_occured(ex)
  snap
  raise ex # re-raise the error after saving the snapshot
end

#login(user = nil, password = nil) ⇒ bool

Loggs in a user with the given login data on the Dev Center Frontend. You don’t need to pass a username and password. It will Automatically be fetched using the CredentialsManager::PasswordManager. This method will also automatically be called when triggering other actions like #open_app_page

Parameters:

  • user (String) (defaults to: nil)

    (optional) The username/email address

  • password (String) (defaults to: nil)

    (optional) The password

Returns:

  • (bool)

    true if everything worked fine

Raises:



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
# File 'lib/fastlane_core/developer_center/developer_center.rb', line 66

def (user = nil, password = nil)
  begin
    Helper.log.info "Login into iOS Developer Center"

    user ||= CredentialsManager::PasswordManager.shared_manager.username
    password ||= CredentialsManager::PasswordManager.shared_manager.password

    result = visit PROFILES_URL
    raise "Could not open Developer Center" unless result['status'] == 'success'

    # Already logged in
    return true if page.has_content? "Member Center"

    (wait_for_elements(".button.blue").first.click rescue nil) # maybe already logged in

    (wait_for_elements('#accountpassword') rescue nil) # when the user is already logged in, this will raise an exception

    # Already logged in
    return true if page.has_content? "Member Center"

    fill_in "accountname", with: user
    fill_in "accountpassword", with: password

    all(".button.large.blue.signin-button").first.click

    begin
      # If the user is not on multiple teams
      select_team if page.has_content? "Select Team"
    rescue => ex
      Helper.log.debug ex
      raise DeveloperCenterLoginError.new("Error loggin in user #{user}. User is on multiple teams and we were unable to correctly retrieve them.")
    end

    begin
      wait_for_elements('.ios.profiles.gridList')
      visit PROFILES_URL # again, since after the login, the dev center loses the production GET value
    rescue => ex
      Helper.log.debug ex
      if page.has_content?"Getting Started"
        raise "There was no valid signing certificate found. Please log in and follow the 'Getting Started guide' on '#{current_url}'".red
      else
        raise DeveloperCenterLoginError.new("Error logging in user #{user} with the given password. Make sure you entered them correctly.")
      end
    end

    Helper.log.info "Login successful"
    
    true
  rescue => ex
    error_occured(ex)
  end
end

#post_ajax(url) ⇒ Object



22
23
24
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 22

def post_ajax(url)
  JSON.parse(page.evaluate_script("$.ajax({type: 'POST', url: '#{url}', async: false})")['responseText'])
end

#select_teamObject



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
# File 'lib/fastlane_core/developer_center/developer_center.rb', line 120

def select_team
  team_id = ENV["FASTLANE_TEAM_ID"]
  team_id = nil if team_id.to_s.length == 0

  unless team_id
    Helper.log.info "You can store you preferred team using the environment variable `FASTLANE_TEAM_ID`".green
    Helper.log.info "Your ID belongs to the following teams:".green
  end
  
  available_options = []

  teams = find("div.input").all('.team-value') # Grab all the teams data
  teams.each_with_index do |val, index|
    current_team_id = '"' + val.find("input").value + '"'
    team_text = val.find(".label-primary").text
    description_text = val.find(".label-secondary").text
    description_text = "(#{description_text})" unless description_text.empty? # Include the team description if any
    index_text = (index + 1).to_s + "."

    available_options << [index_text, current_team_id, team_text, description_text].join(" ")
  end

  unless team_id
    puts available_options.join("\n").green
    team_index = ask("Please select the team number you would like to access: ".green)
    team_id = teams[team_index.to_i - 1].find(".radio").value
  end

  team_button = first(:xpath, "//input[@type='radio' and @value='#{team_id}']") # Select the desired team
  if team_button
    team_button.click
  else
    Helper.log.fatal "Could not find given Team. Available options: ".red
    puts available_options.join("\n").yellow
    raise DeveloperCenterLoginError.new("Error finding given team #{team_id}.".red)
  end

  all(".button.large.blue.submit").first.click

  result = visit PROFILES_URL
  raise "Could not open Developer Center" unless result['status'] == 'success'
end

#snapObject



35
36
37
38
39
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 35

def snap
  path = "Error#{Time.now.to_i}.png"
  save_screenshot(path, :full => true)
  system("open '#{path}'") unless ENV['SIGH_DISABLE_OPEN_ERROR']
end

#wait_for(method, parameter, success) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 41

def wait_for(method, parameter, success)
  counter = 0
  result = method.call(parameter)
  while !success.call(result)
    sleep 0.2

    result = method.call(parameter)

    counter += 1
    if counter > 100
      Helper.log.debug caller
      raise DeveloperCenterGeneralError.new("Couldn't find '#{parameter}' after waiting for quite some time")
    end
  end
  return result
end

#wait_for_elements(name) ⇒ Object



58
59
60
61
62
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 58

def wait_for_elements(name)
  method = Proc.new { |n| all(name) }
  success = Proc.new { |r| r.count > 0 }
  return wait_for(method, name, success)
end

#wait_for_variable(name) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/fastlane_core/developer_center/developer_center_helper.rb', line 64

def wait_for_variable(name)
  method = Proc.new { |n|
    retval = page.html.match(/var #{n} = "(.*)"/)
    retval[1] unless retval == nil
  }
  success = Proc.new { |r| r != nil }
  return wait_for(method, name, success)
end