sigh 0.3.5 → 0.4.1
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 +4 -4
- data/README.md +3 -3
- data/bin/sigh +12 -46
- data/lib/sigh.rb +5 -0
- data/lib/sigh/developer_center.rb +38 -34
- data/lib/sigh/developer_center_signing.rb +5 -5
- data/lib/sigh/options.rb +74 -0
- data/lib/sigh/profile_analyser.rb +1 -1
- data/lib/sigh/resign.rb +64 -32
- data/lib/sigh/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f526a0a5cfb3f72abca695aa7345504a520539f
|
4
|
+
data.tar.gz: 2d750cc363d9776803b4235217727a16a48821ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73a2d366758dc8eb917a751e0250a5286f1acb89ae3626eb79cfb2f7482916acdaea88d89f01590b354fa1d328f2bb1c21e105db33dd941a68f3984145ec1d7f
|
7
|
+
data.tar.gz: 6fddc9be1d9c09abb57764a6fb75a6226a3027f984ab7141ffe42d4d834eddddc33dc7a21704510b68694a53725e388d1586ba55ea6c41e56d4efb27a9fdb7e8
|
data/README.md
CHANGED
@@ -47,7 +47,7 @@ Get in contact with the developer on Twitter: [@KrauseFx](https://twitter.com/Kr
|
|
47
47
|
|
48
48
|
-------
|
49
49
|
|
50
|
-
<h5 align="center"><code>sigh</code> is part of <a href="
|
50
|
+
<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>
|
51
51
|
|
52
52
|
|
53
53
|
# Features
|
@@ -169,9 +169,9 @@ If you're using [cert](https://github.com/KrauseFx/cert) in combination with [fa
|
|
169
169
|
```sigh``` uses the [password manager](https://github.com/KrauseFx/CredentialsManager) from `fastlane`. Take a look the [CredentialsManager README](https://github.com/KrauseFx/CredentialsManager) for more information.
|
170
170
|
|
171
171
|
# Tips
|
172
|
-
## [`fastlane`](
|
172
|
+
## [`fastlane`](https://fastlane.tools) Toolchain
|
173
173
|
|
174
|
-
- [`fastlane`](
|
174
|
+
- [`fastlane`](https://fastlane.tools): Connect all deployment tools into one streamlined workflow
|
175
175
|
- [`deliver`](https://github.com/KrauseFx/deliver): Upload screenshots, metadata and your app to the App Store using a single command
|
176
176
|
- [`snapshot`](https://github.com/KrauseFx/snapshot): Automate taking localized screenshots of your iOS app on every device
|
177
177
|
- [`frameit`](https://github.com/KrauseFx/frameit): Quickly put your screenshots into the right device frames
|
data/bin/sigh
CHANGED
@@ -6,6 +6,7 @@ require 'sigh'
|
|
6
6
|
require 'commander'
|
7
7
|
require 'credentials_manager/password_manager'
|
8
8
|
require 'credentials_manager/appfile_config'
|
9
|
+
require 'sigh/options'
|
9
10
|
|
10
11
|
HighLine.track_eof = false
|
11
12
|
|
@@ -16,53 +17,33 @@ class SighApplication
|
|
16
17
|
program :version, Sigh::VERSION
|
17
18
|
program :description, 'CLI for \'sigh\' - Because you would rather spend your time building stuff than fighting provisioning'
|
18
19
|
program :help, 'Author', 'Felix Krause <sigh@krausefx.com>'
|
19
|
-
program :help, 'Website', '
|
20
|
+
program :help, 'Website', 'https://fastlane.tools'
|
20
21
|
program :help, 'GitHub', 'https://github.com/krausefx/sigh'
|
21
22
|
program :help_formatter, :compact
|
22
23
|
|
23
24
|
always_trace!
|
24
25
|
|
25
|
-
|
26
|
-
global_option '--skip_install', 'By default, the certificate will be added on your local machine. Setting this flag will skip this action.'
|
27
|
-
global_option '--development', 'Renew the development certificate instead of the production one.'
|
28
|
-
global_option '--force', 'Renew non-development provisioning profiles regardless of state.'
|
29
|
-
|
30
|
-
global_option '-a', '--identifier STRING', String, 'The bundle identifier of your app.'
|
31
|
-
global_option '-u', '--username STRING', String, 'Your Apple ID username.'
|
32
|
-
global_option '-n', '--cert_name STRING', String, 'The name of the generated certificate file.'
|
33
|
-
global_option '-o', '--output STRING', String, 'The folder in which the file should be generated.'
|
34
|
-
global_option '-d', '--cert_date STRING', String, 'The certificate with the given expiry date used to renew. (e.g. "Nov 11, 2017")'
|
35
|
-
global_option '-c', '--cert_owner STRING', String, 'The certificate name to use for new profiles, or to renew with. (e.g. "Felix Krause")'
|
36
|
-
global_option '-f', '--filename STRING', String, 'Filename to use for the provisioning profile'
|
26
|
+
FastlaneCore::CommanderGenerator.new.generate(Sigh::Options.available_options)
|
37
27
|
|
38
28
|
command :renew do |c|
|
39
29
|
c.syntax = 'sigh renew'
|
40
30
|
c.description = 'Renews the certificate (in case it expired) and outputs the path to the generated file'
|
41
31
|
|
42
32
|
c.action do |args, options|
|
43
|
-
|
44
|
-
username(options)
|
45
|
-
|
46
|
-
type = FastlaneCore::DeveloperCenter::APPSTORE
|
47
|
-
type = FastlaneCore::DeveloperCenter::ADHOC if options.adhoc
|
48
|
-
type = FastlaneCore::DeveloperCenter::DEVELOPMENT if options.development
|
33
|
+
Sigh.config = FastlaneCore::Configuration.create(Sigh::Options.available_options, options.__hash__)
|
49
34
|
|
50
|
-
|
51
|
-
ENV['SIGH_CERTIFICATE_EXPIRE_DATE'] = options.cert_date if options.cert_date
|
52
|
-
|
53
|
-
path = FastlaneCore::DeveloperCenter.new.run(app, type, options.cert_name, options.force)
|
35
|
+
path = Sigh::DeveloperCenter.new.run
|
54
36
|
|
55
37
|
if path
|
56
|
-
|
57
|
-
|
58
|
-
file_name = File.basename(path)
|
38
|
+
if Sigh.config[:filename]
|
39
|
+
file_name = Sigh.config[:filename]
|
59
40
|
else
|
60
|
-
file_name =
|
41
|
+
file_name = File.basename(path)
|
61
42
|
end
|
62
|
-
|
63
|
-
output = File.join(output_path.gsub("~", ENV["HOME"]), file_name)
|
64
|
-
FileUtils.mv(path, output)
|
65
|
-
system("open -g '#{output}'") unless
|
43
|
+
|
44
|
+
output = File.join(Sigh.config[:output_path].gsub("~", ENV["HOME"]), file_name)
|
45
|
+
(FileUtils.mv(path, output) rescue nil) # in case it already exists
|
46
|
+
system("open -g '#{output}'") unless Sigh.config[:skip_install]
|
66
47
|
puts output.green
|
67
48
|
end
|
68
49
|
end
|
@@ -84,21 +65,6 @@ class SighApplication
|
|
84
65
|
run!
|
85
66
|
end
|
86
67
|
|
87
|
-
def username(options)
|
88
|
-
user = options.username
|
89
|
-
user ||= ENV["SIGH_USERNAME"]
|
90
|
-
user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
|
91
|
-
|
92
|
-
CredentialsManager::PasswordManager.shared_manager(user) if user
|
93
|
-
end
|
94
|
-
|
95
|
-
def app_identifier(options)
|
96
|
-
value = options.identifier
|
97
|
-
value ||= ENV["SIGH_APP_IDENTIFIER"]
|
98
|
-
value ||= CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
|
99
|
-
value ||= ask("App Identifier (Bundle ID, e.g. com.krausefx.app): ")
|
100
|
-
return value
|
101
|
-
end
|
102
68
|
end
|
103
69
|
|
104
70
|
SighApplication.new.run
|
data/lib/sigh.rb
CHANGED
@@ -6,6 +6,11 @@ require 'sigh/resign'
|
|
6
6
|
require 'fastlane_core'
|
7
7
|
|
8
8
|
module Sigh
|
9
|
+
# Use this to just setup the configuration attribute and set it later somewhere else
|
10
|
+
class << self
|
11
|
+
attr_accessor :config
|
12
|
+
end
|
13
|
+
|
9
14
|
Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
|
10
15
|
|
11
16
|
ENV['FASTLANE_TEAM_ID'] ||= ENV["SIGH_TEAM_ID"]
|
@@ -1,28 +1,30 @@
|
|
1
1
|
require 'fastlane_core/developer_center/developer_center'
|
2
2
|
require 'sigh/developer_center_signing'
|
3
3
|
|
4
|
-
module
|
5
|
-
class DeveloperCenter
|
4
|
+
module Sigh
|
5
|
+
class DeveloperCenter < FastlaneCore::DeveloperCenter
|
6
6
|
# Types of certificates
|
7
7
|
APPSTORE = "AppStore"
|
8
8
|
ADHOC = "AdHoc"
|
9
9
|
DEVELOPMENT = "Development"
|
10
10
|
|
11
11
|
PROFILES_URL_DEV = "https://developer.apple.com/account/ios/profile/profileList.action?type=limited"
|
12
|
-
|
13
12
|
|
14
|
-
def run
|
15
|
-
|
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
|
16
19
|
|
17
|
-
type_name = type
|
18
|
-
|
19
|
-
cert_name ||= "#{type_name}_#{app_identifier}.mobileprovision" # default name
|
20
|
+
type_name = "Distribution" if @type == APPSTORE # both enterprise and App Store
|
21
|
+
cert_name ||= "#{type_name}_#{Sigh.config[:app_identifier]}.mobileprovision" # default name
|
20
22
|
cert_name += '.mobileprovision' unless cert_name.include?'mobileprovision'
|
21
23
|
|
22
24
|
output_path = File.join(TMP_FOLDER, cert_name)
|
23
25
|
File.write(output_path, cert)
|
24
26
|
|
25
|
-
store_provisioning_id_in_environment(output_path)
|
27
|
+
store_provisioning_id_in_environment(output_path)
|
26
28
|
|
27
29
|
return output_path
|
28
30
|
end
|
@@ -33,9 +35,10 @@ module FastlaneCore
|
|
33
35
|
ENV["SIGH_UDID"] = udid if udid
|
34
36
|
end
|
35
37
|
|
36
|
-
def maintain_app_certificate(
|
38
|
+
def maintain_app_certificate(force = nil)
|
39
|
+
force = Sigh.config[:force] if (force == nil)
|
37
40
|
begin
|
38
|
-
if type == DEVELOPMENT
|
41
|
+
if @type == DEVELOPMENT
|
39
42
|
visit PROFILES_URL_DEV
|
40
43
|
else
|
41
44
|
visit PROFILES_URL
|
@@ -48,29 +51,29 @@ module FastlaneCore
|
|
48
51
|
certs = post_ajax(@list_certs_url)
|
49
52
|
|
50
53
|
Helper.log.info "Checking if profile is available. (#{certs['provisioningProfiles'].count} profiles found)"
|
51
|
-
required_cert_types = type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution']
|
54
|
+
required_cert_types = (@type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution'])
|
52
55
|
certs['provisioningProfiles'].each do |current_cert|
|
53
56
|
next unless required_cert_types.include?(current_cert['type'])
|
54
57
|
|
55
58
|
details = profile_details(current_cert['provisioningProfileId'])
|
56
59
|
|
57
|
-
if details['provisioningProfile']['appId']['identifier'] == app_identifier
|
60
|
+
if details['provisioningProfile']['appId']['identifier'] == Sigh.config[:app_identifier]
|
58
61
|
# that's an Ad Hoc profile. I didn't find a better way to detect if it's one ... skipping it
|
59
|
-
next if type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
|
62
|
+
next if @type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
|
60
63
|
|
61
64
|
# that's an App Store profile ... skipping it
|
62
|
-
next if type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
|
65
|
+
next if @type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
|
63
66
|
|
64
67
|
# We found the correct certificate
|
65
|
-
if force && type != DEVELOPMENT
|
68
|
+
if force && @type != DEVELOPMENT
|
66
69
|
provisioningProfileId = current_cert['provisioningProfileId']
|
67
|
-
renew_profile(provisioningProfileId
|
68
|
-
return maintain_app_certificate(
|
70
|
+
renew_profile(provisioningProfileId) # This one needs to be forcefully renewed
|
71
|
+
return maintain_app_certificate(false) # recursive
|
69
72
|
elsif current_cert['status'] == 'Active'
|
70
73
|
return download_profile(details['provisioningProfile']['provisioningProfileId']) # this one is already finished. Just download it.
|
71
74
|
elsif ['Expired', 'Invalid'].include? current_cert['status']
|
72
|
-
renew_profile(current_cert['provisioningProfileId']
|
73
|
-
return maintain_app_certificate(
|
75
|
+
renew_profile(current_cert['provisioningProfileId']) # This one needs to be renewed
|
76
|
+
return maintain_app_certificate(false) # recursive
|
74
77
|
end
|
75
78
|
|
76
79
|
break
|
@@ -79,18 +82,19 @@ module FastlaneCore
|
|
79
82
|
|
80
83
|
Helper.log.info "Could not find existing profile. Trying to create a new one."
|
81
84
|
# Certificate does not exist yet, we need to create a new one
|
82
|
-
create_profile
|
85
|
+
create_profile
|
83
86
|
# After creating the profile, we need to download it
|
84
|
-
return maintain_app_certificate(
|
87
|
+
return maintain_app_certificate(false) # recursive
|
85
88
|
|
86
89
|
rescue => ex
|
87
90
|
error_occured(ex)
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
91
|
-
def create_profile
|
92
|
-
|
93
|
-
|
94
|
+
def create_profile
|
95
|
+
app_identifier = Sigh.config[:app_identifier]
|
96
|
+
Helper.log.info "Creating new profile for app '#{app_identifier}' for type '#{@type}'.".yellow
|
97
|
+
certificates = code_signing_certificates(@type)
|
94
98
|
|
95
99
|
create_url = "https://developer.apple.com/account/ios/profile/profileCreate.action"
|
96
100
|
visit create_url
|
@@ -106,8 +110,8 @@ module FastlaneCore
|
|
106
110
|
end
|
107
111
|
|
108
112
|
value = enterprise ? 'inhouse' : 'store'
|
109
|
-
value = 'limited' if type == DEVELOPMENT
|
110
|
-
value = 'adhoc' if type == ADHOC
|
113
|
+
value = 'limited' if @type == DEVELOPMENT
|
114
|
+
value = 'adhoc' if @type == ADHOC
|
111
115
|
|
112
116
|
first(:xpath, "//input[@type='radio' and @value='#{value}']").click
|
113
117
|
click_next
|
@@ -137,7 +141,7 @@ module FastlaneCore
|
|
137
141
|
clicked = false
|
138
142
|
certificates.each do |cert|
|
139
143
|
cert_id = cert['certificateId']
|
140
|
-
input = if type == DEVELOPMENT
|
144
|
+
input = if @type == DEVELOPMENT
|
141
145
|
# development uses a checkbox and has no [] around the value
|
142
146
|
first(:xpath, "//input[@type='checkbox' and @value='#{cert_id}']")
|
143
147
|
else
|
@@ -156,7 +160,7 @@ module FastlaneCore
|
|
156
160
|
end
|
157
161
|
click_next
|
158
162
|
|
159
|
-
if type != APPSTORE
|
163
|
+
if @type != APPSTORE
|
160
164
|
# 4) Devices selection
|
161
165
|
wait_for_elements('.selectAll.column')
|
162
166
|
sleep 3
|
@@ -167,15 +171,15 @@ module FastlaneCore
|
|
167
171
|
|
168
172
|
# 5) Choose a profile name
|
169
173
|
wait_for_elements('.distributionType')
|
170
|
-
profile_name =
|
171
|
-
profile_name ||= [app_identifier, type].join(' ')
|
174
|
+
profile_name = Sigh.config[:provisioning_file_name]
|
175
|
+
profile_name ||= [app_identifier, @type].join(' ')
|
172
176
|
fill_in "provisioningProfileName", with: profile_name
|
173
177
|
click_next
|
174
178
|
wait_for_elements('.row-details')
|
175
179
|
end
|
176
180
|
|
177
|
-
def renew_profile(profile_id
|
178
|
-
certificate = code_signing_certificates(type).first
|
181
|
+
def renew_profile(profile_id)
|
182
|
+
certificate = code_signing_certificates(@type).first
|
179
183
|
|
180
184
|
details_url = "https://developer.apple.com/account/ios/profile/profileEdit.action?type=&provisioningProfileId=#{profile_id}"
|
181
185
|
Helper.log.info "Renewing provisioning profile '#{profile_id}' using URL '#{details_url}'"
|
@@ -188,7 +192,7 @@ module FastlaneCore
|
|
188
192
|
if certs.count == 1
|
189
193
|
certs.first.click
|
190
194
|
|
191
|
-
if type != APPSTORE
|
195
|
+
if @type != APPSTORE
|
192
196
|
# Add all devices
|
193
197
|
wait_for_elements('.selectAll.column')
|
194
198
|
sleep 3
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module
|
2
|
-
class DeveloperCenter
|
1
|
+
module Sigh
|
2
|
+
class DeveloperCenter < FastlaneCore::DeveloperCenter
|
3
3
|
# Returns a array of hashes, that contains information about the iOS certificate
|
4
4
|
# @example
|
5
5
|
# [{"certRequestId"=>"B23Q2P396B",
|
@@ -37,9 +37,9 @@ module FastlaneCore
|
|
37
37
|
ret_certs = []
|
38
38
|
|
39
39
|
# Select certificate
|
40
|
-
certificate_name =
|
41
|
-
cert_date =
|
42
|
-
cert_id =
|
40
|
+
certificate_name = Sigh.config[:cert_owner_name]
|
41
|
+
cert_date = Sigh.config[:cert_date]
|
42
|
+
cert_id = Sigh.config[:cert_id]
|
43
43
|
|
44
44
|
# The other profiles are push profiles
|
45
45
|
certificate_type = type == DEVELOPMENT ? 'iOS Development' : 'iOS Distribution'
|
data/lib/sigh/options.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'fastlane_core'
|
2
|
+
|
3
|
+
module Sigh
|
4
|
+
class Options
|
5
|
+
def self.available_options
|
6
|
+
@@options ||= [
|
7
|
+
FastlaneCore::ConfigItem.new(key: :adhoc,
|
8
|
+
env_name: "SIGH_AD_HOC",
|
9
|
+
description: "Setting this flag will generate AdHoc profiles instead of App Store Profiles",
|
10
|
+
is_string: false),
|
11
|
+
FastlaneCore::ConfigItem.new(key: :skip_install,
|
12
|
+
env_name: "SIGH_SKIP_INSTALL",
|
13
|
+
description: "By default, the certificate will be added on your local machine. Setting this flag will skip this action",
|
14
|
+
is_string: false),
|
15
|
+
FastlaneCore::ConfigItem.new(key: :development,
|
16
|
+
env_name: "SIGH_DEVELOPMENT",
|
17
|
+
description: "Renew the development certificate instead of the production one",
|
18
|
+
is_string: false),
|
19
|
+
FastlaneCore::ConfigItem.new(key: :force,
|
20
|
+
env_name: "SIGH_FORCE",
|
21
|
+
description: "Renew non-development provisioning profiles regardless of its state",
|
22
|
+
is_string: false),
|
23
|
+
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
24
|
+
short_option: "-a",
|
25
|
+
env_name: "SIGH_APP_IDENTIFIER",
|
26
|
+
description: "The bundle identifier of your app",
|
27
|
+
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)),
|
28
|
+
FastlaneCore::ConfigItem.new(key: :username,
|
29
|
+
short_option: "-u",
|
30
|
+
env_name: "SIGH_USERNAME",
|
31
|
+
description: "Your Apple ID Username",
|
32
|
+
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:apple_id),
|
33
|
+
verify_block: Proc.new do |value|
|
34
|
+
CredentialsManager::PasswordManager.shared_manager(value)
|
35
|
+
end),
|
36
|
+
FastlaneCore::ConfigItem.new(key: :provisioning_file_name,
|
37
|
+
short_option: "-n",
|
38
|
+
env_name: "SIGH_PROVISIONING_PROFILE_NAME",
|
39
|
+
description: "The name of the generated certificate file"),
|
40
|
+
FastlaneCore::ConfigItem.new(key: :output_path,
|
41
|
+
short_option: "-o",
|
42
|
+
env_name: "SIGH_OUTPUT_PATH",
|
43
|
+
description: "Directory in which the profile should be stored",
|
44
|
+
default_value: ".",
|
45
|
+
verify_block: Proc.new do |value|
|
46
|
+
raise "Could not find output directory '#{value}'".red unless File.exists?(value)
|
47
|
+
end),
|
48
|
+
FastlaneCore::ConfigItem.new(key: :cert_id,
|
49
|
+
short_option: "-i",
|
50
|
+
env_name: "SIGH_CERTIFICATE_ID",
|
51
|
+
description: "The ID of the certificate to use",
|
52
|
+
optional: true),
|
53
|
+
FastlaneCore::ConfigItem.new(key: :cert_owner_name,
|
54
|
+
short_option: "-c",
|
55
|
+
env_name: "SIGH_CERTIFICATE",
|
56
|
+
description: "The certificate name to use for new profiles, or to renew with. (e.g. \"Felix Krause\")",
|
57
|
+
optional: true),
|
58
|
+
FastlaneCore::ConfigItem.new(key: :cert_date,
|
59
|
+
short_option: "-d",
|
60
|
+
env_name: "SIGH_CERTIFICATE_EXPIRE_DATE",
|
61
|
+
description: "The certificate with the given expiry date used to renew. (e.g. \"Nov 11, 2017\")",
|
62
|
+
optional: true),
|
63
|
+
FastlaneCore::ConfigItem.new(key: :filename,
|
64
|
+
short_option: "-f",
|
65
|
+
env_name: "SIGH_PROFILE_FILE_NAME",
|
66
|
+
optional: true,
|
67
|
+
description: "Filename to use for the generated provisioning profile (must include .mobileprovision)",
|
68
|
+
verify_block: Proc.new do |value|
|
69
|
+
raise "The output name must end with .mobileprovision".red unless value.end_with?".mobileprovision"
|
70
|
+
end)
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -3,7 +3,7 @@ require 'plist'
|
|
3
3
|
module Sigh
|
4
4
|
class ProfileAnalyser
|
5
5
|
def self.run(path)
|
6
|
-
plist = Plist::parse_xml(`security cms -D -i #{path}`)
|
6
|
+
plist = Plist::parse_xml(`security cms -D -i '#{path}'`)
|
7
7
|
if plist.count > 10
|
8
8
|
Helper.log.info("Provisioning profile of app '#{plist['AppIDName']}' with the name '#{plist['Name']}' successfully generated and analysed.".green)
|
9
9
|
return plist["UUID"]
|
data/lib/sigh/resign.rb
CHANGED
@@ -1,60 +1,92 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
1
3
|
module Sigh
|
2
4
|
# Resigns an existing ipa file
|
3
5
|
class Resign
|
4
6
|
def run(options, args)
|
5
|
-
|
7
|
+
# get the command line inputs and parse those into the vars we need...
|
8
|
+
ipa, signing_identity, provisioning_profile = get_inputs(options, args)
|
9
|
+
|
10
|
+
# ... then invoke out programmatic interface with these vars
|
11
|
+
resign(ipa, signing_identity, provisioning_profile)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.resign(ipa, signing_identity, provisioning_profile)
|
15
|
+
self.new.resign(ipa, signing_identity, provisioning_profile)
|
16
|
+
end
|
17
|
+
|
18
|
+
def resign(ipa, signing_identity, provisioning_profile)
|
19
|
+
resign_path = find_resign_path
|
20
|
+
signing_identity = find_signing_identity(signing_identity)
|
21
|
+
|
22
|
+
# validate that we have valid values for all these params, we don't need to check signing_identity because `find_signing_identity` will only ever return a valid value
|
23
|
+
validate_params(resign_path, ipa, provisioning_profile)
|
6
24
|
|
7
25
|
command = [
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
"-p
|
12
|
-
|
26
|
+
resign_path.shellescape,
|
27
|
+
ipa.shellescape,
|
28
|
+
signing_identity.shellescape,
|
29
|
+
"-p #{provisioning_profile.shellescape}",
|
30
|
+
ipa.shellescape
|
13
31
|
].join(' ')
|
14
32
|
|
15
33
|
puts command.magenta
|
16
34
|
output = `#{command}`
|
17
35
|
puts output
|
18
|
-
if output.include?
|
19
|
-
Helper.log.info "Successfully signed #{
|
36
|
+
if output.include?('Assuming Distribution Identity')
|
37
|
+
Helper.log.info "Successfully signed #{ipa}!".green
|
38
|
+
true
|
20
39
|
else
|
21
|
-
Helper.log.fatal "Something went wrong while code signing #{
|
40
|
+
Helper.log.fatal "Something went wrong while code signing #{ipa}".red
|
41
|
+
false
|
22
42
|
end
|
23
43
|
end
|
24
44
|
|
25
45
|
def get_inputs(options, args)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
46
|
+
ipa = args.first || find_ipa || ask('Path to ipa file: ')
|
47
|
+
signing_identity = options.signing_identity || ask_for_signing_identity
|
48
|
+
provisioning_profile = options.provisioning_profile || find_provisioning_profile || ask('Path to provisioning file: ')
|
49
|
+
|
50
|
+
return ipa, signing_identity, provisioning_profile
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_resign_path
|
54
|
+
File.join(Helper.gem_path('sigh'), 'lib', 'assets', 'resign.sh')
|
35
55
|
end
|
36
56
|
|
37
57
|
def find_ipa
|
38
|
-
Dir[File.join(Dir.pwd,
|
58
|
+
Dir[File.join(Dir.pwd, '*.ipa')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
|
39
59
|
end
|
40
60
|
|
41
61
|
def find_provisioning_profile
|
42
|
-
Dir[File.join(Dir.pwd,
|
62
|
+
Dir[File.join(Dir.pwd, '*.mobileprovision')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
|
43
63
|
end
|
44
64
|
|
45
|
-
def
|
46
|
-
|
65
|
+
def find_signing_identity(signing_identity)
|
66
|
+
until installed_identies.include?(signing_identity)
|
67
|
+
Helper.log.error "Couldn't find signing identity '#{signing_identity}'."
|
68
|
+
signing_identity = ask_for_signing_identity
|
69
|
+
end
|
70
|
+
|
71
|
+
signing_identity
|
47
72
|
end
|
48
73
|
|
49
|
-
def
|
50
|
-
|
74
|
+
def validate_params(resign_path, ipa, provisioning_profile)
|
75
|
+
validate_resign_path(resign_path)
|
76
|
+
validate_ipa_file(ipa)
|
77
|
+
validate_provisioning_file(provisioning_profile)
|
51
78
|
end
|
52
79
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
80
|
+
def validate_resign_path(resign_path)
|
81
|
+
raise 'Could not find resign.sh file. Please try re-installing the gem.'.red unless File.exist?(resign_path)
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate_ipa_file(ipa)
|
85
|
+
raise "ipa file could not be found or is not an ipa file (#{ipa})".red unless File.exist?(ipa) && ipa.end_with?('.ipa')
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_provisioning_file(provisioning_profile)
|
89
|
+
raise "Provisioning profile file could not be found or is not a .mobileprovision file (#{provisioning_profile})".red unless File.exists?(provisioning_profile) && provisioning_profile.end_with?('.mobileprovision')
|
58
90
|
end
|
59
91
|
|
60
92
|
def print_available_identities
|
@@ -63,7 +95,7 @@ module Sigh
|
|
63
95
|
|
64
96
|
def ask_for_signing_identity
|
65
97
|
print_available_identities
|
66
|
-
ask(
|
98
|
+
ask('Signing Identity: ')
|
67
99
|
end
|
68
100
|
|
69
101
|
# Array of available signing identities
|
@@ -74,7 +106,7 @@ module Sigh
|
|
74
106
|
(ids << current.match(/.*\"(.*)\"/)[1]) rescue nil # the last line does not match
|
75
107
|
end
|
76
108
|
|
77
|
-
|
109
|
+
ids
|
78
110
|
end
|
79
111
|
end
|
80
|
-
end
|
112
|
+
end
|
data/lib/sigh/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sigh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
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-
|
11
|
+
date: 2015-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fastlane_core
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.3.0
|
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.
|
26
|
+
version: 0.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: plist
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -153,10 +153,11 @@ 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/options.rb
|
156
157
|
- lib/sigh/profile_analyser.rb
|
157
158
|
- lib/sigh/resign.rb
|
158
159
|
- lib/sigh/version.rb
|
159
|
-
homepage:
|
160
|
+
homepage: https://fastlane.tools
|
160
161
|
licenses:
|
161
162
|
- MIT
|
162
163
|
metadata: {}
|