sigh 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b585780730eaef47020d53ae0478b5991f289dd
4
- data.tar.gz: ea30fb8b855256d7f4161902678d4154c5c5d5a3
3
+ metadata.gz: ab5bb66a972ec8b64c52d5ea5ae1b285c51f08f5
4
+ data.tar.gz: cb417be836c696568ad39438c1c553edacf7e653
5
5
  SHA512:
6
- metadata.gz: 48e286ab52ba07fcc9aceadd6c889973c7ddedd82376d23ea4ebb1f46e279c46f9a9237745203694f528bdd3eddd031e38a6eac79a4ca01566f38d81f74c50b6
7
- data.tar.gz: 2c323e4f2ae7f1055cec978229fbea421b07c806f0cbf7b3e42c143cf7c4eaaeeba9daf14c1d8502d80e48df4043fcc39a58af5c0691941fe18c12e4d8441dbc
6
+ metadata.gz: 36aea2553f3c24ac3638dcdf03a0ef989750fcd5a1a62304980e3582ec9120b3d21d174e633784cbe7c28bea9076c0607a11ebc17a2899146eed6ff3fbca6b11
7
+ data.tar.gz: 01f113d0f47e115cd554b04ead4842e416536bbf0cbdd377dc8553b81d6a6cb980e3110a77d19d148837059a03c4ee14900c377b173460a441fc59de5cd8312d
data/README.md CHANGED
@@ -51,6 +51,9 @@ Special thanks to [Matthias Tretter](https://twitter.com/myell0w) for coming up
51
51
 
52
52
  <h5 align="center"><code>sigh</code> is part of <a href="https://fastlane.tools">fastlane</a>: connect all deployment tools into one streamlined workflow.</h5>
53
53
 
54
+ ### spaceship version
55
+
56
+ If you're feeling adventurous and want to test the new `sigh` beta with [spaceship](https://spaceship.airforce), update using `sudo gem update sigh --pre`. More information in the [release notes](https://github.com/KrauseFx/sigh/releases/tag/1.0.0.beta5).
54
57
 
55
58
  # Features
56
59
 
@@ -175,6 +178,8 @@ Choose signing certificate to use:
175
178
  - `SIGH_CERTIFICATE_ID` (The ID of the certificate)
176
179
  - `SIGH_CERTIFICATE_EXPIRE_DATE` (The expire date of the certificate)
177
180
 
181
+ As always, run `sigh --help` to get a list of all variables.
182
+
178
183
  If you're using [cert](https://github.com/KrauseFx/cert) in combination with [fastlane](https://github.com/KrauseFx/fastlane) the signing certificate will automatically be selected for you. (make sure to run `cert` before `sigh`)
179
184
 
180
185
  `sigh` will store the `UDID` of the generated provisioning profile in the environment: `SIGH_UDID`.
data/lib/sigh.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'sigh/version'
2
2
  require 'sigh/dependency_checker'
3
- require 'sigh/developer_center'
4
3
  require 'sigh/resign'
5
4
  require 'fastlane_core'
6
5
 
data/lib/sigh/manager.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'plist'
2
+ require 'sigh/spaceship/runner'
2
3
 
3
4
  module Sigh
4
5
  class Manager
5
6
  def self.start
6
- path = Sigh::DeveloperCenter.new.run
7
+ start = Time.now
8
+ path = Sigh::Runner.new.run
7
9
 
8
10
  return nil unless path
9
11
 
@@ -38,7 +40,7 @@ module Sigh
38
40
  (FileUtils.copy profile, destination rescue nil) # if the directory doesn't exist yet
39
41
 
40
42
  if File.exists? destination
41
- Helper.log.info "Profile installed at \"#{destination}\""
43
+ Helper.log.info "Profile successfully installed".green
42
44
  else
43
45
  raise "Failed installation of provisioning profile at location: #{destination}".red
44
46
  end
data/lib/sigh/options.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core'
2
+ require 'credentials_manager'
2
3
 
3
4
  module Sigh
4
5
  class Options
@@ -22,7 +23,7 @@ module Sigh
22
23
  default_value: false),
23
24
  FastlaneCore::ConfigItem.new(key: :force,
24
25
  env_name: "SIGH_FORCE",
25
- description: "Renew non-development provisioning profiles regardless of its state",
26
+ description: "Renew provisioning profiles regardless of its state",
26
27
  is_string: false,
27
28
  default_value: false),
28
29
  FastlaneCore::ConfigItem.new(key: :app_identifier,
@@ -34,7 +35,7 @@ module Sigh
34
35
  short_option: "-u",
35
36
  env_name: "SIGH_USERNAME",
36
37
  description: "Your Apple ID Username",
37
- default_value: CredentialsManager::AppfileConfig.try_fetch_value(:apple_id),
38
+ default_value: ENV["DELIVER_USER"] || CredentialsManager::AppfileConfig.try_fetch_value(:apple_id),
38
39
  verify_block: Proc.new do |value|
39
40
  CredentialsManager::PasswordManager.shared_manager(value)
40
41
  end),
@@ -43,9 +44,19 @@ module Sigh
43
44
  env_name: "SIGH_TEAM_ID",
44
45
  description: "The ID of your team if you're in multiple teams",
45
46
  optional: true,
47
+ default_value: CredentialsManager::AppfileConfig.try_fetch_value(:team_id),
46
48
  verify_block: Proc.new do |value|
47
49
  ENV["FASTLANE_TEAM_ID"] = value
48
50
  end),
51
+ FastlaneCore::ConfigItem.new(key: :team_name,
52
+ short_option: "-l",
53
+ env_name: "SIGH_TEAM_NAME",
54
+ description: "The name of your team if you're in multiple teams",
55
+ optional: true,
56
+ default_value: CredentialsManager::AppfileConfig.try_fetch_value(:team_name),
57
+ verify_block: Proc.new do |value|
58
+ ENV["FASTLANE_TEAM_NAME"] = value
59
+ end),
49
60
  FastlaneCore::ConfigItem.new(key: :provisioning_name,
50
61
  short_option: "-n",
51
62
  env_name: "SIGH_PROVISIONING_PROFILE_NAME",
@@ -62,7 +73,7 @@ module Sigh
62
73
  FastlaneCore::ConfigItem.new(key: :cert_id,
63
74
  short_option: "-i",
64
75
  env_name: "SIGH_CERTIFICATE_ID",
65
- description: "The ID of the certificate to use",
76
+ description: "The ID of the code signing certificate to use (e.g. 78ADL6LVAA) ",
66
77
  optional: true),
67
78
  FastlaneCore::ConfigItem.new(key: :cert_owner_name,
68
79
  short_option: "-c",
@@ -82,6 +93,7 @@ module Sigh
82
93
  verify_block: Proc.new do |value|
83
94
  raise "The output name must end with .mobileprovision".red unless value.end_with?".mobileprovision"
84
95
  end)
96
+
85
97
  ]
86
98
  end
87
99
  end
@@ -5,7 +5,7 @@ module Sigh
5
5
  def self.run(path)
6
6
  plist = Plist::parse_xml(`security cms -D -i '#{path}'`)
7
7
  if plist.count > 10
8
- Helper.log.info("Provisioning profile of app '#{plist['AppIDName']}' with the name '#{plist['Name']}' successfully generated and analysed.".green)
8
+ Helper.log.info("Provisioning profile of app '#{plist['AppIDName']}' with the name '#{plist['Name']}' successfully analysed.".green)
9
9
  return plist["UUID"]
10
10
  else
11
11
  Helper.log.error("Error parsing provisioning profile at path '#{path}'".red)
data/lib/sigh/resign.rb CHANGED
@@ -33,7 +33,14 @@ module Sigh
33
33
  puts command.magenta
34
34
  output = `#{command}`
35
35
  puts output
36
- if output.include?('Assuming Distribution Identity')
36
+
37
+ if signing_identity =~ /^iPhone Developer:*/
38
+ ptn = 'Assuming Development Identity'
39
+ else
40
+ ptn = 'Assuming Distribution Identity'
41
+ end
42
+
43
+ if output.include?(ptn)
37
44
  Helper.log.info "Successfully signed #{ipa}!".green
38
45
  true
39
46
  else
@@ -0,0 +1,144 @@
1
+ require 'spaceship'
2
+
3
+ module Sigh
4
+ class Runner
5
+ attr_accessor :spaceship
6
+
7
+ # Uses the spaceship to create or download a provisioning profile
8
+ # returns the path the newly created provisioning profile (in /tmp usually)
9
+ def run
10
+ Helper.log.info "Starting login"
11
+ Spaceship.login(Sigh.config[:username], nil)
12
+ Spaceship.select_team
13
+ Helper.log.info "Successfully logged in"
14
+
15
+ profiles = fetch_profiles # download the profile if it's there
16
+
17
+ if profiles.count > 0
18
+ Helper.log.info "Found #{profiles.count} matching profile(s)".yellow
19
+ profile = profiles.first
20
+
21
+ if Sigh.config[:force]
22
+ unless profile_type == Spaceship.provisioning_profile::AppStore
23
+ Helper.log.info "Updating the profile to include all devices".yellow
24
+ profile.devices = Spaceship.device.all
25
+ else
26
+ Helper.log.info "Updating the provisioning profile".yellow
27
+ end
28
+
29
+ profile = profile.update! # assign it, as it's a new profile
30
+ end
31
+ else
32
+ Helper.log.info "No existing profiles found, creating a new one for you".yellow
33
+ profile = create_profile!
34
+ end
35
+
36
+ raise "Something went wrong fetching the latest profile".red unless profile
37
+
38
+ path = download_profile(profile)
39
+ store_provisioning_id_in_environment(path)
40
+
41
+ return path
42
+ end
43
+
44
+ # The kind of provisioning profile we're interested in
45
+ def profile_type
46
+ return @profile_type if @profile_type
47
+
48
+ @profile_type = Spaceship.provisioning_profile.app_store
49
+ @profile_type = Spaceship.provisioning_profile.ad_hoc if Sigh.config[:adhoc]
50
+ @profile_type = Spaceship.provisioning_profile.development if Sigh.config[:development]
51
+ @profile_type = Spaceship.provisioning_profile.in_house if Spaceship.client.in_house?
52
+
53
+ @profile_type
54
+ end
55
+
56
+ # Fetches a profile matching the user's search requirements
57
+ def fetch_profiles
58
+ profile_type.find_by_bundle_id(Sigh.config[:app_identifier])
59
+ end
60
+
61
+ # Create a new profile and return it
62
+ def create_profile!
63
+ cert = certificate_to_use
64
+ bundle_id = Sigh.config[:app_identifier]
65
+ name = Sigh.config[:provisioning_name] || [bundle_id, profile_type.pretty_type].join(' ')
66
+
67
+ if Spaceship.provisioning_profile.all.find { |p| p.name == name }
68
+ Helper.log.error "The name '#{name}' is already taken, using another one."
69
+ name += " #{Time.now.to_i}"
70
+ end
71
+
72
+ Helper.log.info "Creating new provisioning profile for '#{Sigh.config[:app_identifier]}' with name '#{name}'".yellow
73
+ profile = profile_type.create!(name: name,
74
+ bundle_id: bundle_id,
75
+ certificate: cert)
76
+ profile
77
+ end
78
+
79
+
80
+ # Certificate to use based on the current distribution mode
81
+ def certificate_to_use
82
+ if profile_type == Spaceship.provisioning_profile.Development
83
+ certificates = Spaceship.certificate.development.all
84
+ elsif profile_type == Spaceship.provisioning_profile.InHouse
85
+ certificates = Spaceship.certificate.in_house.all
86
+ else
87
+ certificates = Spaceship.certificate.production.all # Ad hoc or App Store
88
+ end
89
+
90
+ # Filter them
91
+ certificates = certificates.find_all do |c|
92
+ if Sigh.config[:cert_id]
93
+ next unless (c.id == Sigh.config[:cert_id].strip)
94
+ end
95
+
96
+ if Sigh.config[:cert_owner_name]
97
+ next unless (c.owner_name.strip == Sigh.config[:cert_owner_name].strip)
98
+ end
99
+
100
+ true
101
+ end
102
+
103
+ if certificates.count > 1
104
+ Helper.log.info "Found more than one code signing identity. Choosing the first one. Check out `sigh --help` to see all available options.".yellow
105
+ Helper.log.info "Available Code Signing Identities for current filters:".green
106
+ certificates.each do |c|
107
+ Helper.log.info ("\t- Name: " + c.owner_name + " - ID: " + c.id + " - Expires: " + c.expires.strftime("%d/%m/%Y")).green
108
+ end
109
+ end
110
+
111
+ if certificates.count == 0
112
+ filters = ""
113
+ filters << "Owner Name: '#{Sigh.config[:cert_owner_name]}' " if Sigh.config[:cert_owner_name]
114
+ filters << "Certificate ID: '#{Sigh.config[:cert_id]}' " if Sigh.config[:cert_id]
115
+ Helper.log.info "No certificates for filter: #{filters}".yellow if filters.length > 0
116
+ raise "Could not find a matching code signing identity for #{profile_type}. You can use cert to generate one (https://github.com/fastlane/cert)".red
117
+ end
118
+
119
+ return certificates.first
120
+ end
121
+
122
+ # Downloads and stores the provisioning profile
123
+ def download_profile(profile)
124
+ Helper.log.info "Downloading provisioning profile...".yellow
125
+ profile_name ||= "#{profile.class.pretty_type}_#{Sigh.config[:app_identifier]}.mobileprovision" # default name
126
+ profile_name += '.mobileprovision' unless profile_name.include?'mobileprovision'
127
+
128
+ output_path = File.join('/tmp', profile_name)
129
+ dataWritten = File.open(output_path, "wb") do |f|
130
+ f.write(profile.download)
131
+ end
132
+
133
+ Helper.log.info "Successfully downloaded provisioning profile...".green
134
+ return output_path
135
+ end
136
+
137
+ # Store the profile ID into the environment
138
+ def store_provisioning_id_in_environment(path)
139
+ require 'sigh/profile_analyser'
140
+ udid = Sigh::ProfileAnalyser.run(path)
141
+ ENV["SIGH_UDID"] = udid if udid
142
+ end
143
+ end
144
+ end
data/lib/sigh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sigh
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sigh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-22 00:00:00.000000000 Z
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.2
19
+ version: 0.7.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.2
26
+ version: 0.7.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: plist
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: spaceship
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.8
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.8
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -151,13 +165,12 @@ files:
151
165
  - lib/assets/resign.sh
152
166
  - lib/sigh.rb
153
167
  - lib/sigh/dependency_checker.rb
154
- - lib/sigh/developer_center.rb
155
- - lib/sigh/developer_center_signing.rb
156
168
  - lib/sigh/local_manage.rb
157
169
  - lib/sigh/manager.rb
158
170
  - lib/sigh/options.rb
159
171
  - lib/sigh/profile_analyser.rb
160
172
  - lib/sigh/resign.rb
173
+ - lib/sigh/spaceship/runner.rb
161
174
  - lib/sigh/version.rb
162
175
  homepage: https://fastlane.tools
163
176
  licenses:
@@ -179,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
192
  version: '0'
180
193
  requirements: []
181
194
  rubyforge_project:
182
- rubygems_version: 2.2.2
195
+ rubygems_version: 2.4.7
183
196
  signing_key:
184
197
  specification_version: 4
185
198
  summary: Because you would rather spend your time building stuff than fighting provisioning
@@ -1,292 +0,0 @@
1
- require 'fastlane_core/developer_center/developer_center'
2
- require 'sigh/developer_center_signing'
3
-
4
- module Sigh
5
- class DeveloperCenter < FastlaneCore::DeveloperCenter
6
- # Types of certificates
7
- APPSTORE = "AppStore"
8
- ADHOC = "AdHoc"
9
- DEVELOPMENT = "Development"
10
-
11
- PROFILES_URL_DEV = "https://developer.apple.com/account/ios/profile/profileList.action?type=limited"
12
-
13
- def run
14
- @type = Sigh::DeveloperCenter::APPSTORE
15
- @type = Sigh::DeveloperCenter::ADHOC if Sigh.config[:adhoc]
16
- @type = Sigh::DeveloperCenter::DEVELOPMENT if Sigh.config[:development]
17
-
18
- cert = maintain_app_certificate # create/download the certificate
19
-
20
- if @type == APPSTORE # both enterprise and App Store
21
- type_name = "Distribution"
22
- elsif @type == ADHOC
23
- type_name = "AdHoc"
24
- else
25
- type_name = "Development"
26
- end
27
- cert_name ||= "#{type_name}_#{Sigh.config[:app_identifier]}.mobileprovision" # default name
28
- cert_name += '.mobileprovision' unless cert_name.include?'mobileprovision'
29
-
30
- output_path = File.join(TMP_FOLDER, cert_name)
31
- dataWritten = File.open(output_path, "wb") do |f|
32
- f.write(cert)
33
- end
34
-
35
- store_provisioning_id_in_environment(output_path)
36
-
37
- return output_path
38
- end
39
-
40
- def store_provisioning_id_in_environment(path)
41
- require 'sigh/profile_analyser'
42
- udid = Sigh::ProfileAnalyser.run(path)
43
- ENV["SIGH_UDID"] = udid if udid
44
- end
45
-
46
- def maintain_app_certificate(force = nil)
47
- force = Sigh.config[:force] if (force == nil)
48
- begin
49
- if @type == DEVELOPMENT
50
- visit PROFILES_URL_DEV
51
- else
52
- visit PROFILES_URL
53
- end
54
-
55
- @list_certs_url = wait_for_variable('profileDataURL')
56
- # list_certs_url will look like this: "https://developer.apple.com/services-account/..../account/ios/profile/listProvisioningProfiles.action?content-type=application/x-www-form-urlencoded&accept=application/json&requestId=id&userLocale=en_US&teamId=xy&includeInactiveProfiles=true&onlyCountLists=true"
57
- Helper.log.info "Fetching all available provisioning profiles..."
58
-
59
- has_all_profiles = false
60
- page_index = 1
61
- page_size = 500
62
-
63
- until has_all_profiles do
64
- bundle_id = Sigh.config[:app_identifier]
65
-
66
- certs = post_ajax(@list_certs_url, "{pageNumber: #{page_index}, pageSize: #{page_size}, sort: 'name%3dasc', search: ''}")
67
-
68
- if certs
69
- profile_name = Sigh.config[:provisioning_name]
70
-
71
- profile_count = certs['provisioningProfiles'].count
72
-
73
- Helper.log.info "Checking if profile is available. (#{profile_count} profiles found on page #{page_index})"
74
- required_cert_types = (@type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution'])
75
- certs['provisioningProfiles'].each do |current_cert|
76
- next unless required_cert_types.include?(current_cert['type'])
77
-
78
- details = profile_details(current_cert['provisioningProfileId'])
79
-
80
- if details['provisioningProfile']['appId']['identifier'] == bundle_id
81
-
82
- next if profile_name && details['provisioningProfile']['name'] != profile_name
83
-
84
- # that's an Ad Hoc profile. I didn't find a better way to detect if it's one ... skipping it
85
- next if @type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
86
-
87
- # that's an App Store profile ... skipping it
88
- next if @type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
89
-
90
- # We found the correct certificate
91
- if force
92
- renew_profile(current_cert['provisioningProfileId']) # This one needs to be forcefully renewed
93
- return maintain_app_certificate(false) # recursive
94
- elsif current_cert['status'] == 'Active'
95
- return download_profile(details['provisioningProfile']['provisioningProfileId']) # this one is already finished. Just download it.
96
- elsif ['Expired', 'Invalid'].include? current_cert['status']
97
- # Broken profile
98
- begin
99
- renew_profile(current_cert['provisioningProfileId']) # This one needs to be renewed
100
- return maintain_app_certificate(false) # recursive
101
- rescue
102
- # Something went wrong, just create a new one instead
103
- end
104
- end
105
-
106
- break
107
- end
108
- end
109
-
110
- if page_size <= profile_count
111
- page_index += 1
112
- else
113
- has_all_profiles = true
114
- end
115
- end
116
- end
117
-
118
- Helper.log.info "Could not find existing profile. Trying to create a new one."
119
- # Certificate does not exist yet, we need to create a new one
120
- create_profile
121
- # After creating the profile, we need to download it
122
- return maintain_app_certificate(false) # recursive
123
-
124
- rescue => ex
125
- error_occured(ex)
126
- end
127
- end
128
-
129
- def create_profile
130
- app_identifier = Sigh.config[:app_identifier]
131
- Helper.log.info "Creating new profile for app '#{app_identifier}' for type '#{@type}'.".yellow
132
- certificates = code_signing_certificates(@type)
133
-
134
- create_url = "https://developer.apple.com/account/ios/profile/profileCreate.action"
135
- visit create_url
136
-
137
- # 1) Select the profile type (AppStore, Adhoc)
138
- enterprise = false
139
-
140
- begin
141
- wait_for_elements('#type-production')
142
- rescue => ex
143
- wait_for_elements('#type-inhouse') # enterprise accounts
144
- enterprise = true
145
- end
146
-
147
- value = enterprise ? 'inhouse' : 'store'
148
- value = 'limited' if @type == DEVELOPMENT
149
- value = 'adhoc' if @type == ADHOC
150
-
151
- first(:xpath, "//input[@type='radio' and @value='#{value}']").click
152
- click_next
153
-
154
- # 2) Select the App ID
155
- sleep 1 while !page.has_content? "Select App ID"
156
- # example: <option value="RGAWZGXSY4">ABP (5A997XSHK2.net.sunapps.34)</option>
157
- identifiers = all(:xpath, "//option[contains(text(), '.#{app_identifier})')]")
158
- if identifiers.count == 0
159
- puts "Couldn't find App ID '#{app_identifier}'\nonly found the following bundle identifiers:".red
160
- all(:xpath, "//option").each do |current|
161
- puts "\t- #{current.text}".yellow
162
- end
163
- raise "Could not find App ID '#{app_identifier}'.".red
164
- else
165
- identifiers.first.select_option
166
- end
167
- click_next
168
-
169
- # 3) Select the certificate
170
- sleep 1 while !page.has_content? "Select certificates"
171
- sleep 3
172
- Helper.log.info "Using certificates: #{certificates.map { |c| "#{c['ownerName']} (#{c['certificateId']})" } }"
173
-
174
- # example: <input type="radio" name="certificateIds" class="validate" value="[XC5PH8D47H]"> (production)
175
-
176
- clicked = false
177
- certificates.each do |cert|
178
- cert_id = cert['certificateId']
179
- input = if @type == DEVELOPMENT
180
- # development uses a checkbox and has no [] around the value
181
- first(:xpath, "//input[@type='checkbox' and @value='#{cert_id}']")
182
- else
183
- break if clicked
184
- # production uses radio and has a [] around the value
185
- first(:xpath, "//input[@type='radio' and @value='[#{cert_id}]']")
186
- end
187
- if input
188
- input.click
189
- clicked = true
190
- end
191
- end
192
-
193
- if !clicked
194
- raise "Could not find certificate in the list of available certificates."
195
- end
196
- click_next
197
-
198
- if @type != APPSTORE
199
- # 4) Devices selection
200
- wait_for_elements('.selectAll.column')
201
- sleep 3
202
-
203
- first(:xpath, "//div[@class='selectAll column']/input").click # select all the devices
204
- click_next
205
- end
206
-
207
- # 5) Choose a profile name
208
- wait_for_elements('.distributionType')
209
- profile_name = Sigh.config[:provisioning_name]
210
- profile_name ||= [app_identifier, @type].join(' ')
211
- fill_in "provisioningProfileName", with: profile_name
212
- click_next
213
-
214
- if page.has_content?"Multiple profiles found with the name"
215
- fill_in "provisioningProfileName", with: (profile_name + " sigh")
216
- click_next
217
- end
218
-
219
- wait_for_elements('.row-details')
220
- end
221
-
222
- def renew_profile(profile_id)
223
- certificate = code_signing_certificates(@type).first
224
-
225
- details_url = "https://developer.apple.com/account/ios/profile/profileEdit.action?type=&provisioningProfileId=#{profile_id}"
226
- Helper.log.info "Renewing provisioning profile '#{profile_id}' using URL '#{details_url}'"
227
- visit details_url
228
-
229
- Helper.log.info "Using certificate ID '#{certificate['certificateId']}' from '#{certificate['ownerName']}'"
230
- wait_for_elements('.selectCertificates')
231
-
232
- certs = all(:xpath, "//input[@type='radio' and @value='#{certificate["certificateId"]}']")
233
- if certs.count == 1
234
- certs.first.click
235
-
236
- if @type != APPSTORE
237
- # Add all devices
238
- wait_for_elements('.selectAll.column')
239
- sleep 3
240
- unless first(:xpath, "//div[@class='selectAll column']/input")["checked"]
241
- first(:xpath, "//div[@class='selectAll column']/input").click # select all the devices
242
- end
243
- end
244
-
245
- click_next
246
-
247
- wait_for_elements('.row-details')
248
- click_on "Done"
249
- else
250
- if @type != APPSTORE
251
- # Add all devices
252
- wait_for_elements('.selectAll.column')
253
- sleep 3
254
- unless all(:xpath, "//div[@class='selectAll column']/input").last["checked"]
255
- all(:xpath, "//div[@class='selectAll column']/input").last.click # select all the devices
256
- end
257
- click_next
258
-
259
- wait_for_elements('.row-details')
260
- click_on "Done"
261
- else
262
- Helper.log.info "Looking for certificate: #{certificate}."
263
- raise "Could not find certificate in the list of available certificates."
264
- end
265
- end
266
- end
267
-
268
- def download_profile(profile_id)
269
- download_cert_url = "/account/ios/profile/profileContentDownload.action?displayId=#{profile_id}"
270
-
271
- return download_file(download_cert_url)
272
- end
273
-
274
-
275
- private
276
- def profile_details(profile_id)
277
- # We need to build the URL to get the App ID for a specific certificate
278
- current_profile_url = @list_certs_url.gsub('listProvisioningProfiles', 'getProvisioningProfile')
279
- current_profile_url += "&provisioningProfileId=#{profile_id}"
280
- # Helper.log.debug "Fetching URL: '#{current_profile_url}'"
281
-
282
- result = post_ajax(current_profile_url)
283
- # Example response, see bottom of file
284
-
285
- if result['resultCode'] == 0
286
- return result
287
- else
288
- raise "Error fetching details for provisioning profile '#{profile_id}'".red
289
- end
290
- end
291
- end
292
- end
@@ -1,88 +0,0 @@
1
- module Sigh
2
- class DeveloperCenter < FastlaneCore::DeveloperCenter
3
- # Returns a array of hashes, that contains information about the iOS certificate
4
- # @example
5
- # [{"certRequestId"=>"B23Q2P396B",
6
- # "name"=>"SunApps GmbH",
7
- # "statusString"=>"Issued",
8
- # "expirationDate"=>"2015-11-25T22:45:50Z",
9
- # "expirationDateString"=>"Nov 25, 2015",
10
- # "ownerType"=>"team",
11
- # "ownerName"=>"SunApps GmbH",
12
- # "ownerId"=>"....",
13
- # "canDownload"=>true,
14
- # "canRevoke"=>true,
15
- # "certificateId"=>"....",
16
- # "certificateStatusCode"=>0,
17
- # "certRequestStatusCode"=>4,
18
- # "certificateTypeDisplayId"=>"...",
19
- # "serialNum"=>"....",
20
- # "typeString"=>"iOS Distribution"},
21
- # {another sertificate...}]
22
- def code_signing_certificates(type)
23
- certs_url = "https://developer.apple.com/account/ios/certificate/certificateList.action?type="
24
- certs_url << (type == DEVELOPMENT ? 'development' : 'distribution')
25
- visit certs_url
26
-
27
- certificateDataURL = wait_for_variable('certificateDataURL')
28
- certificateRequestTypes = wait_for_variable('certificateRequestTypes')
29
- certificateStatuses = wait_for_variable('certificateStatuses')
30
-
31
- url = [certificateDataURL, certificateRequestTypes, certificateStatuses].join('')
32
-
33
- # https://developer.apple.com/services-account/.../account/ios/certificate/listCertRequests.action?content-type=application/x-www-form-urlencoded&accept=application/json&requestId=...&userLocale=en_US&teamId=...&types=...&status=4&certificateStatus=0&type=distribution
34
-
35
- certs = post_ajax(url, "{pageNumber: 1, pageSize: 500, sort: 'name%3dasc'}")['certRequests']
36
-
37
- ret_certs = []
38
-
39
- # Select certificate
40
- certificate_name = Sigh.config[:cert_owner_name]
41
- cert_date = Sigh.config[:cert_date]
42
- cert_id = Sigh.config[:cert_id]
43
-
44
- # The other profiles are push profiles
45
- certificate_type = type == DEVELOPMENT ? 'iOS Development' : 'iOS Distribution'
46
-
47
- # New profiles first
48
- certs.sort! do |a, b|
49
- Time.parse(b['expirationDate']) <=> Time.parse(a['expirationDate'])
50
- end
51
-
52
- certs.each do |current_cert|
53
- next unless current_cert['typeString'] == certificate_type
54
-
55
- if cert_date || certificate_name || cert_id
56
- if current_cert['expirationDateString'] == cert_date
57
- Helper.log.info "Certificate ID '#{current_cert['certificateId']}' with expiry date '#{current_cert['expirationDateString']}' located".green
58
- ret_certs << current_cert
59
- end
60
-
61
- if current_cert['name'] == certificate_name
62
- Helper.log.info "Certificate ID '#{current_cert['certificateId']}' with name '#{certificate_name}' located".green
63
- ret_certs << current_cert
64
- end
65
-
66
- if current_cert['certificateId'] == cert_id
67
- Helper.log.info "Certificate ID '#{current_cert['certificateId']}' with name '#{current_cert['name']}' located".green
68
- ret_certs << current_cert
69
- end
70
- else
71
- ret_certs << current_cert
72
- end
73
- end
74
-
75
- return ret_certs unless ret_certs.empty?
76
-
77
- predicates = []
78
- predicates << "name: #{certificate_name}" if certificate_name
79
- predicates << "expiry date: #{cert_date}" if cert_date
80
- predicates << "certificate ID: #{cert_id}" if cert_id
81
- predicates << "type: #{(type == DEVELOPMENT ? 'development' : 'distribution')}"
82
-
83
- predicates_str = " with #{predicates.join(', ')}"
84
-
85
- raise "Could not find a Certificate#{predicates_str}. Please open #{current_url} and make sure you have a signing profile created, which matches the given filters".red
86
- end
87
- end
88
- end