sigh 0.4.10 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f344b0ea8e7267db1a3a23e63716f0e34c8ecac2
4
- data.tar.gz: fde321e721289dc00e7f915d5bf4191ed83e6149
3
+ metadata.gz: a8e062edc21ba3bd0acf86486468c8baab7c1403
4
+ data.tar.gz: 4de0a9955ef3f4dfe42da0859d3fdd3929d26ac0
5
5
  SHA512:
6
- metadata.gz: b7ee5c564762a360044b230d522a6a55d7b7532e678da0b058ef5bf9c699f1ba3ab2a9436f2673cb6ace39971a8a6b65a4a665d72bb8884835433a6adc5b30cc
7
- data.tar.gz: 651032d38f80bec4e0efc83267e5518fec291c615737afdc2b9d6ef36c753a8d66069ca9e91ccef947df885d7c4ce41e51688977b317f0cf37981a68905c7f37
6
+ metadata.gz: 8af5e581a46bf4d30d366924faba7b4ffb473fbaa1cb8b8ba43cf1527f1542210c508da12c7b9a118cada96ac2b931e04a57da452e42e04cbe60728965c8196f
7
+ data.tar.gz: 0ebf33635e3efa1e5c51ffbd425d64ab5a5a8a604d63d1e62e9ce4959c8c0f137525578c2bb06aaa0eaa889f0382adc09d1058901130ff46f470886f8f08e95f
data/README.md CHANGED
@@ -147,6 +147,20 @@ You can pass more information using the command line:
147
147
 
148
148
  sigh resign ./path/app.ipa -i "iPhone Distribution: Felix Krause" -p "my.mobileprovision"
149
149
 
150
+ # Manage
151
+
152
+ With `sigh manage` you can list all provisioning profiles installed locally.
153
+
154
+ sigh manage
155
+
156
+ Delete all expired provisioning profiles
157
+
158
+ sigh manage -e
159
+
160
+ Or delete all `iOS Team Provisioning Profile` by using a regular expression
161
+
162
+ sigh manage -p "iOS\ ?Team Provisioning Profile:"
163
+
150
164
  ## Environment Variables
151
165
  In case you prefer environment variables:
152
166
 
data/bin/sigh CHANGED
@@ -8,6 +8,7 @@ require 'credentials_manager/password_manager'
8
8
  require 'credentials_manager/appfile_config'
9
9
  require 'sigh/options'
10
10
  require 'sigh/manager'
11
+ require 'sigh/local_manage'
11
12
 
12
13
  HighLine.track_eof = false
13
14
 
@@ -20,7 +21,7 @@ class SighApplication
20
21
  program :help, 'Author', 'Felix Krause <sigh@krausefx.com>'
21
22
  program :help, 'Website', 'https://fastlane.tools'
22
23
  program :help, 'GitHub', 'https://github.com/krausefx/sigh'
23
- program :help_formatter, :compact
24
+ # program :help_formatter, :compact # https://github.com/commander-rb/commander/issues/12
24
25
 
25
26
  always_trace!
26
27
 
@@ -47,6 +48,20 @@ class SighApplication
47
48
  end
48
49
  end
49
50
 
51
+ command :manage do |c|
52
+ c.syntax = 'sigh manage'
53
+ c.description = 'Manage installed provisioning profiles on your system.'
54
+
55
+ c.option '-e', '--clean_expired', 'Remove all expired provisioning profiles.'
56
+
57
+ c.option '-p', '--clean_pattern STRING', String, 'Remove any provisioning profiles that matches the regular expression.'
58
+ c.example 'Remove all "iOS Team Provisioning" provisioning profiles', 'sigh manage -p "iOS\ ?Team Provisioning Profile"'
59
+
60
+ c.action do |args, options|
61
+ Sigh::LocalManage.start(options, args)
62
+ end
63
+ end
64
+
50
65
  default_command :renew
51
66
 
52
67
  run!
@@ -293,7 +293,7 @@ then
293
293
  echo "Resigning embedded frameworks using certificate: '$CERTIFICATE'" >&2
294
294
  for framework in "$FRAMEWORKS_DIR"/*
295
295
  do
296
- if [[ "$framework" == *.framework ]]
296
+ if [[ "$framework" == *.framework || "$framework" == *.dylib ]]
297
297
  then
298
298
  /usr/bin/codesign -f -s "$CERTIFICATE" "$framework"
299
299
  checkStatus
@@ -2,7 +2,6 @@ require 'sigh/version'
2
2
  require 'sigh/dependency_checker'
3
3
  require 'sigh/developer_center'
4
4
  require 'sigh/resign'
5
-
6
5
  require 'fastlane_core'
7
6
 
8
7
  module Sigh
@@ -17,8 +17,13 @@ module Sigh
17
17
 
18
18
  cert = maintain_app_certificate # create/download the certificate
19
19
 
20
- type_name = "Distribution" if @type == APPSTORE # both enterprise and App Store
21
- type_name = "Development" unless @type == APPSTORE
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
22
27
  cert_name ||= "#{type_name}_#{Sigh.config[:app_identifier]}.mobileprovision" # default name
23
28
  cert_name += '.mobileprovision' unless cert_name.include?'mobileprovision'
24
29
 
@@ -48,41 +53,63 @@ module Sigh
48
53
  @list_certs_url = wait_for_variable('profileDataURL')
49
54
  # 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"
50
55
  Helper.log.info "Fetching all available provisioning profiles..."
51
-
52
- certs = post_ajax(@list_certs_url, "{pageNumber: 1, pageSize: 500, sort: 'name%3dasc'}")
53
-
54
- profile_name = Sigh.config[:provisioning_name]
55
-
56
- Helper.log.info "Checking if profile is available. (#{certs['provisioningProfiles'].count} profiles found)"
57
- required_cert_types = (@type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution'])
58
- certs['provisioningProfiles'].each do |current_cert|
59
- next unless required_cert_types.include?(current_cert['type'])
60
-
61
- details = profile_details(current_cert['provisioningProfileId'])
62
-
63
- if details['provisioningProfile']['appId']['identifier'] == Sigh.config[:app_identifier]
64
-
65
- next if profile_name && details['provisioningProfile']['name'] != profile_name
66
-
67
- # that's an Ad Hoc profile. I didn't find a better way to detect if it's one ... skipping it
68
- next if @type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
69
-
70
- # that's an App Store profile ... skipping it
71
- next if @type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
72
-
73
- # We found the correct certificate
74
- if force && @type != DEVELOPMENT
75
- provisioningProfileId = current_cert['provisioningProfileId']
76
- renew_profile(provisioningProfileId) # This one needs to be forcefully renewed
77
- return maintain_app_certificate(false) # recursive
78
- elsif current_cert['status'] == 'Active'
79
- return download_profile(details['provisioningProfile']['provisioningProfileId']) # this one is already finished. Just download it.
80
- elsif ['Expired', 'Invalid'].include? current_cert['status']
81
- renew_profile(current_cert['provisioningProfileId']) # This one needs to be renewed
82
- return maintain_app_certificate(false) # recursive
56
+
57
+ has_all_profiles = false
58
+ page_index = 1
59
+ page_size = 500
60
+
61
+ until has_all_profiles do
62
+ bundle_id = Sigh.config[:app_identifier]
63
+
64
+ certs = post_ajax(@list_certs_url, "{pageNumber: #{page_index}, pageSize: #{page_size}, sort: 'name%3dasc', search: 'name%3D#{bundle_id}%26type%3D#{bundle_id}%26status%3D#{bundle_id}%26appId%3D#{bundle_id}'}")
65
+
66
+ if certs
67
+ profile_name = Sigh.config[:provisioning_name]
68
+
69
+ profile_count = certs['provisioningProfiles'].count
70
+
71
+ Helper.log.info "Checking if profile is available. (#{profile_count} profiles found on page #{page_index})"
72
+ required_cert_types = (@type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution'])
73
+ certs['provisioningProfiles'].each do |current_cert|
74
+ next unless required_cert_types.include?(current_cert['type'])
75
+
76
+ details = profile_details(current_cert['provisioningProfileId'])
77
+
78
+ if details['provisioningProfile']['appId']['identifier'] == bundle_id
79
+
80
+ next if profile_name && details['provisioningProfile']['name'] != profile_name
81
+
82
+ # that's an Ad Hoc profile. I didn't find a better way to detect if it's one ... skipping it
83
+ next if @type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
84
+
85
+ # that's an App Store profile ... skipping it
86
+ next if @type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
87
+
88
+ # We found the correct certificate
89
+ if force
90
+ renew_profile(current_cert['provisioningProfileId']) # This one needs to be forcefully renewed
91
+ return maintain_app_certificate(false) # recursive
92
+ elsif current_cert['status'] == 'Active'
93
+ return download_profile(details['provisioningProfile']['provisioningProfileId']) # this one is already finished. Just download it.
94
+ elsif ['Expired', 'Invalid'].include? current_cert['status']
95
+ # Broken profile
96
+ begin
97
+ renew_profile(current_cert['provisioningProfileId']) # This one needs to be renewed
98
+ return maintain_app_certificate(false) # recursive
99
+ rescue
100
+ # Something went wrong, just create a new one instead
101
+ end
102
+ end
103
+
104
+ break
105
+ end
83
106
  end
84
107
 
85
- break
108
+ if page_size <= profile_count
109
+ page_index += 1
110
+ else
111
+ has_all_profiles = true
112
+ end
86
113
  end
87
114
  end
88
115
 
@@ -181,6 +208,12 @@ module Sigh
181
208
  profile_name ||= [app_identifier, @type].join(' ')
182
209
  fill_in "provisioningProfileName", with: profile_name
183
210
  click_next
211
+
212
+ if page.has_content?"Multiple profiles found with the name"
213
+ fill_in "provisioningProfileName", with: (profile_name + " sigh")
214
+ click_next
215
+ end
216
+
184
217
  wait_for_elements('.row-details')
185
218
  end
186
219
 
@@ -212,8 +245,21 @@ module Sigh
212
245
  wait_for_elements('.row-details')
213
246
  click_on "Done"
214
247
  else
215
- Helper.log.info "Looking for certificate: #{certificate}."
216
- raise "Could not find certificate in the list of available certificates."
248
+ if @type != APPSTORE
249
+ # Add all devices
250
+ wait_for_elements('.selectAll.column')
251
+ sleep 3
252
+ unless all(:xpath, "//div[@class='selectAll column']/input").last["checked"]
253
+ all(:xpath, "//div[@class='selectAll column']/input").last.click # select all the devices
254
+ end
255
+ click_next
256
+
257
+ wait_for_elements('.row-details')
258
+ click_on "Done"
259
+ else
260
+ Helper.log.info "Looking for certificate: #{certificate}."
261
+ raise "Could not find certificate in the list of available certificates."
262
+ end
217
263
  end
218
264
  end
219
265
 
@@ -0,0 +1,121 @@
1
+ module Sigh
2
+ class LocalManage
3
+ LIST = "list"
4
+ CLEANUP = "cleanup"
5
+
6
+ def self.start(options, args)
7
+ command, clean_expired, clean_pattern = get_inputs(options, args)
8
+ if command == LIST
9
+ list_profiles
10
+ elsif command == CLEANUP
11
+ cleanup_profiles(clean_expired, clean_pattern)
12
+ end
13
+ end
14
+
15
+ def self.install_profile(profile)
16
+ Helper.log.info "Installing provisioning profile..."
17
+ profile_path = File.expand_path("~") + "/Library/MobileDevice/Provisioning Profiles/"
18
+ profile_filename = ENV["SIGH_UDID"] + ".mobileprovision"
19
+ destination = profile_path + profile_filename
20
+
21
+ # If the directory doesn't exist, make it first
22
+ unless File.directory?(profile_path)
23
+ FileUtils.mkdir_p(profile_path)
24
+ end
25
+
26
+ # copy to Xcode provisioning profile directory
27
+ FileUtils.copy profile, destination
28
+
29
+ if File.exists? destination
30
+ Helper.log.info "Profile installed at \"#{destination}\""
31
+ else
32
+ raise "Failed installation of provisioning profile at location: #{destination}".red
33
+ end
34
+ end
35
+
36
+ def self.get_inputs(options, args)
37
+ clean_expired = options.clean_expired
38
+ clean_pattern = /#{options.clean_pattern}/ if options.clean_pattern
39
+ command = (clean_expired != nil || clean_pattern != nil) ? CLEANUP : LIST
40
+ return command, clean_expired, clean_pattern
41
+ end
42
+
43
+ def self.list_profiles
44
+ profiles = load_profiles
45
+
46
+ now = DateTime.now
47
+ soon = (Date.today + 30).to_datetime
48
+
49
+ profiles_valid = profiles.select { |profile| profile["ExpirationDate"] > now && profile["ExpirationDate"] > soon }
50
+ if profiles_valid.count > 0
51
+ Helper.log.info "Provisioning profiles installed"
52
+ Helper.log.info "Valid:"
53
+ profiles_valid.each do |profile|
54
+ Helper.log.info profile["Name"].green
55
+ end
56
+ end
57
+
58
+ profiles_soon = profiles.select { |profile| profile["ExpirationDate"] > now && profile["ExpirationDate"] < soon }
59
+ if profiles_soon.count > 0
60
+ Helper.log.info ""
61
+ Helper.log.info "Expiring within 30 day:"
62
+ profiles_soon.each do |profile|
63
+ Helper.log.info profile["Name"].yellow
64
+ end
65
+ end
66
+
67
+ profiles_expired = profiles.select { |profile| profile["ExpirationDate"] < now }
68
+ if profiles_expired.count > 0
69
+ Helper.log.info ""
70
+ Helper.log.info "Expired:"
71
+ profiles_expired.each do |profile|
72
+ Helper.log.info profile["Name"].red
73
+ end
74
+ end
75
+
76
+ Helper.log.info ""
77
+ Helper.log.info "Summary"
78
+ Helper.log.info "#{profiles.count} installed profiles"
79
+ Helper.log.info "#{profiles_expired.count} are expired".red
80
+ Helper.log.info "#{profiles_soon.count} are valid but will expire within 30 days".yellow
81
+ Helper.log.info "#{profiles_valid.count} are valid".green
82
+
83
+ Helper.log.info "You can remove all expired profiles using `sigh manage -e`" if profiles_expired.count > 0
84
+ end
85
+
86
+ def self.cleanup_profiles(expired = false, pattern = nil)
87
+ now = DateTime.now
88
+
89
+ profiles = load_profiles.select { |profile| (expired && profile["ExpirationDate"] < now) || (pattern != nil && profile["Name"] =~ pattern) }
90
+
91
+ Helper.log.info "The following provisioning profiles are either expired or matches your pattern:"
92
+ profiles.each do |profile|
93
+ Helper.log.info profile["Name"].red
94
+ end
95
+
96
+ if agree("Delete these provisioning profiles #{profiles.length}? (y/n) ", true)
97
+ profiles.each do |profile|
98
+ File.delete profile["Path"]
99
+ end
100
+ Helper.log.info "\n\nDeleted #{profiles.length} profiles".green
101
+ end
102
+ end
103
+
104
+ def self.load_profiles
105
+ Helper.log.info "Loading Provisioning profiles from ~/Library/MobileDevice/Provisioning Profiles/"
106
+ profiles_path = File.expand_path("~") + "/Library/MobileDevice/Provisioning Profiles/*.mobileprovision"
107
+ profile_paths = Dir[profiles_path]
108
+
109
+ profiles = []
110
+ profile_paths.each do |profile_path|
111
+ profile = Plist::parse_xml(`security cms -D -i '#{profile_path}'`)
112
+ profile['Path'] = profile_path
113
+ profiles << profile
114
+ end
115
+
116
+ profiles = profiles.sort_by {|profile| profile["Name"].downcase}
117
+
118
+ return profiles
119
+ end
120
+ end
121
+ end
@@ -1,3 +1,5 @@
1
+ require 'plist'
2
+
1
3
  module Sigh
2
4
  class Manager
3
5
  def self.start
@@ -27,8 +29,13 @@ module Sigh
27
29
  profile_filename = ENV["SIGH_UDID"] + ".mobileprovision"
28
30
  destination = profile_path + profile_filename
29
31
 
32
+ # If the directory doesn't exist, make it first
33
+ unless File.directory?(profile_path)
34
+ FileUtils.mkdir_p(profile_path)
35
+ end
36
+
30
37
  # copy to Xcode provisioning profile directory
31
- FileUtils.copy profile, destination
38
+ (FileUtils.copy profile, destination rescue nil) # if the directory doesn't exist yet
32
39
 
33
40
  if File.exists? destination
34
41
  Helper.log.info "Profile installed at \"#{destination}\""
@@ -37,4 +44,4 @@ module Sigh
37
44
  end
38
45
  end
39
46
  end
40
- end
47
+ end
@@ -18,7 +18,7 @@ module Sigh
18
18
  FastlaneCore::ConfigItem.new(key: :development,
19
19
  env_name: "SIGH_DEVELOPMENT",
20
20
  description: "Renew the development certificate instead of the production one",
21
- is_string: false,
21
+ is_string: false,
22
22
  default_value: false),
23
23
  FastlaneCore::ConfigItem.new(key: :force,
24
24
  env_name: "SIGH_FORCE",
@@ -1,3 +1,3 @@
1
1
  module Sigh
2
- VERSION = "0.4.10"
2
+ VERSION = "0.5.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.4.10
4
+ version: 0.5.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-04-20 00:00:00.000000000 Z
11
+ date: 2015-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane_core
@@ -153,6 +153,7 @@ files:
153
153
  - lib/sigh/dependency_checker.rb
154
154
  - lib/sigh/developer_center.rb
155
155
  - lib/sigh/developer_center_signing.rb
156
+ - lib/sigh/local_manage.rb
156
157
  - lib/sigh/manager.rb
157
158
  - lib/sigh/options.rb
158
159
  - lib/sigh/profile_analyser.rb