sigh 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/bin/sigh +14 -1
- data/lib/assets/resign.sh +439 -0
- data/lib/sigh.rb +1 -0
- data/lib/sigh/developer_center.rb +78 -63
- data/lib/sigh/helper.rb +9 -0
- data/lib/sigh/resign.rb +59 -0
- data/lib/sigh/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef27c541a6d91c50a1a6230aa2dc3598456603b4
|
4
|
+
data.tar.gz: a9cb32dca3f10b03502ee41589d54db9d7d1d6bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cfc39277183515956b30fcd2df642657f60ea084af41a3d8c248bc71f892440e6ffe8c62a1f787654f7ec24569f37fefcd9f68288c306af25697ec7ebafea53
|
7
|
+
data.tar.gz: f53445cff10af39c000800130eeeb139734ddc92f05feb0c2c326c034556eb704be201424ebebea0e12c27e49c74a1d35551a51175dce67a6f6f4f6451884474
|
data/README.md
CHANGED
@@ -82,8 +82,6 @@ Make sure, you have the latest version of the Xcode command line tools installed
|
|
82
82
|
|
83
83
|
xcode-select --install
|
84
84
|
|
85
|
-
If you don't already have homebrew installed, [install it here](http://brew.sh/).
|
86
|
-
|
87
85
|
# Usage
|
88
86
|
|
89
87
|
sigh
|
@@ -121,16 +119,19 @@ If you need the provisioning profile to be renewed regardless of its state use t
|
|
121
119
|
|
122
120
|
sigh --force -a com.krausefx.app -u username
|
123
121
|
|
124
|
-
|
122
|
+
By default, ```sigh``` will include all certificates on development profiles, and first certificate on other types. If you need to specify which certificate to use you can either use the environment variable `SIGH_CERTIFICATE`, or pass the name or expiry date of the certificate as argument:
|
123
|
+
|
124
|
+
sigh -c "SunApps GmbH"
|
125
125
|
|
126
|
-
sigh --force -a com.krausefx.app -u username -d "Nov 11, 2017"
|
127
126
|
|
127
|
+
sigh -d "Nov 11, 2017"
|
128
128
|
|
129
129
|
## Environment Variables
|
130
130
|
In case you prefer environment variables:
|
131
131
|
|
132
132
|
- ```SIGH_USERNAME```
|
133
133
|
- ```SIGH_APP_IDENTIFIER```
|
134
|
+
- ```SIGH_CERTIFICATE``` (The name of the certificate to use)
|
134
135
|
- ```SIGH_TEAM_ID``` (The Team ID, e.g. `Q2CBPK58CA`)
|
135
136
|
- `SIGH_DISABLE_OPEN_ERROR` - in case of error, `sigh` won't open Preview with a screenshot of the error when this variable is set.
|
136
137
|
|
data/bin/sigh
CHANGED
@@ -32,6 +32,7 @@ class SighApplication
|
|
32
32
|
global_option '-n', '--cert_name STRING', String, 'The name of the generated certificate file.'
|
33
33
|
global_option '-o', '--output STRING', String, 'The folder in which the file should be generated.'
|
34
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")'
|
35
36
|
global_option '-f', '--filename STRING', String, 'Filename to use for the provisioning profile'
|
36
37
|
|
37
38
|
command :renew do |c|
|
@@ -45,7 +46,9 @@ class SighApplication
|
|
45
46
|
type = Sigh::DeveloperCenter::APPSTORE
|
46
47
|
type = Sigh::DeveloperCenter::ADHOC if options.adhoc
|
47
48
|
type = Sigh::DeveloperCenter::DEVELOPMENT if options.development
|
48
|
-
|
49
|
+
|
50
|
+
ENV['SIGH_CERTIFICATE'] = options.cert_owner if options.cert_owner
|
51
|
+
|
49
52
|
path = Sigh::DeveloperCenter.new.run(app, type, options.cert_name, options.force, options.cert_date)
|
50
53
|
|
51
54
|
if path
|
@@ -64,6 +67,16 @@ class SighApplication
|
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
70
|
+
command :resign do |c|
|
71
|
+
c.syntax = 'sigh resign'
|
72
|
+
c.description = 'Resigns an existing ipa file with the given provisioning profile'
|
73
|
+
c.option '-i', '--signing_identity STRING', String, 'The signing identity to use. Must match the one defined in the provisioning profile.'
|
74
|
+
|
75
|
+
c.action do |args, options|
|
76
|
+
Sigh::Resign.new.run(options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
67
80
|
default_command :renew
|
68
81
|
|
69
82
|
run!
|
@@ -0,0 +1,439 @@
|
|
1
|
+
# !/bin/bash
|
2
|
+
|
3
|
+
# Copyright (c) 2011 Float Mobile Learning
|
4
|
+
# http://www.floatlearning.com/
|
5
|
+
# Extension Copyright (c) 2013 Weptun Gmbh
|
6
|
+
# http://www.weptun.de
|
7
|
+
#
|
8
|
+
# Extended by Ronan O Ciosoig January 2012
|
9
|
+
#
|
10
|
+
# Extended by Patrick Blitz, April 2013
|
11
|
+
#
|
12
|
+
# Extended by John Turnipseed and Matthew Nespor, November 2014
|
13
|
+
# http://nanonation.net/
|
14
|
+
#
|
15
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
16
|
+
# a copy of this software and associated documentation files (the "Software"),
|
17
|
+
# to deal in the Software without restriction, including without limitation
|
18
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
19
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
20
|
+
# Software is furnished to do so, subject to the following conditions:
|
21
|
+
#
|
22
|
+
# The above copyright notice and this permission notice shall be included
|
23
|
+
# in all copies or substantial portions of the Software.
|
24
|
+
#
|
25
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
26
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
27
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
28
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
29
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
30
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
31
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
|
+
#
|
33
|
+
# Please let us know about any improvements you make to this script!
|
34
|
+
# ./floatsign source "iPhone Distribution: Name" -p "path/to/profile" [-d "display name"] [-e entitlements] [-k keychain] -b "BundleIdentifier" outputIpa
|
35
|
+
#
|
36
|
+
#
|
37
|
+
# Modifed 26th January 2012
|
38
|
+
#
|
39
|
+
# new features January 2012:
|
40
|
+
# 1. change the app display name
|
41
|
+
#
|
42
|
+
# new features April 2013
|
43
|
+
# 1. specify the target bundleId on the command line
|
44
|
+
# 2. correctly handles entitlements for keychain-enabled resigning
|
45
|
+
#
|
46
|
+
# new features November 2014
|
47
|
+
# 1. now re-signs embedded iOS frameworks, if present, prior to re-signing the application itself
|
48
|
+
# 2. extracts the team-identifier from provisioning profile and uses it to update previous entitlements
|
49
|
+
# 3. fixed bug in packaging if -e flag is used
|
50
|
+
# 4. renamed 'temp' directory and made it a variable so it can be easily modified
|
51
|
+
# 5. various code formatting and logging adjustments
|
52
|
+
#
|
53
|
+
|
54
|
+
|
55
|
+
function checkStatus {
|
56
|
+
|
57
|
+
if [ $? -ne 0 ];
|
58
|
+
then
|
59
|
+
echo "Encountered an error, aborting!" >&2
|
60
|
+
exit 1
|
61
|
+
fi
|
62
|
+
}
|
63
|
+
|
64
|
+
if [ $# -lt 3 ]; then
|
65
|
+
echo "usage: $0 source identity -p provisioning [-e entitlements] [-r adjustBetaReports] [-d displayName] [-n version] -b bundleId outputIpa" >&2
|
66
|
+
echo " -p and -b are optional, but their use is heavly recommended" >&2
|
67
|
+
echo " -r flag requires a value '-r yes'"
|
68
|
+
echo " -r flag is ignored if -e is also used" >&2
|
69
|
+
exit 1
|
70
|
+
fi
|
71
|
+
|
72
|
+
ORIGINAL_FILE="$1"
|
73
|
+
CERTIFICATE="$2"
|
74
|
+
NEW_PROVISION=
|
75
|
+
ENTITLEMENTS=
|
76
|
+
BUNDLE_IDENTIFIER=""
|
77
|
+
DISPLAY_NAME=""
|
78
|
+
APP_IDENTIFER_PREFIX=""
|
79
|
+
TEAM_IDENTIFIER=""
|
80
|
+
KEYCHAIN=""
|
81
|
+
VERSION_NUMBER=""
|
82
|
+
ADJUST_BETA_REPORTS_ACTIVE_FLAG="0"
|
83
|
+
TEMP_DIR="_floatsignTemp"
|
84
|
+
|
85
|
+
# options start index
|
86
|
+
OPTIND=3
|
87
|
+
while getopts p:d:e:k:b:r:n: opt; do
|
88
|
+
case $opt in
|
89
|
+
p)
|
90
|
+
NEW_PROVISION="$OPTARG"
|
91
|
+
echo "Specified provisioning profile: '$NEW_PROVISION'" >&2
|
92
|
+
;;
|
93
|
+
d)
|
94
|
+
DISPLAY_NAME="$OPTARG"
|
95
|
+
echo "Specified display name: '$DISPLAY_NAME'" >&2
|
96
|
+
;;
|
97
|
+
e)
|
98
|
+
ENTITLEMENTS="$OPTARG"
|
99
|
+
echo "Specified signing entitlements: '$ENTITLEMENTS'" >&2
|
100
|
+
;;
|
101
|
+
b)
|
102
|
+
BUNDLE_IDENTIFIER="$OPTARG"
|
103
|
+
echo "Specified bundle identifier: '$BUNDLE_IDENTIFIER'" >&2
|
104
|
+
;;
|
105
|
+
k)
|
106
|
+
KEYCHAIN="$OPTARG"
|
107
|
+
echo "Specified Keychain to use: '$KEYCHAIN'" >&2
|
108
|
+
;;
|
109
|
+
n)
|
110
|
+
VERSION_NUMBER="$OPTARG"
|
111
|
+
echo "Specified version to use: '$VERSION_NUMBER'" >&2
|
112
|
+
;;
|
113
|
+
r)
|
114
|
+
ADJUST_BETA_REPORTS_ACTIVE_FLAG="1"
|
115
|
+
echo "Enabled adjustment of beta-reports-active entitlements" >&2
|
116
|
+
;;
|
117
|
+
\?)
|
118
|
+
echo "Invalid option: -$OPTARG" >&2
|
119
|
+
exit 1
|
120
|
+
;;
|
121
|
+
:)
|
122
|
+
echo "Option -$OPTARG requires an argument." >&2
|
123
|
+
exit 1
|
124
|
+
;;
|
125
|
+
esac
|
126
|
+
done
|
127
|
+
|
128
|
+
shift $((OPTIND-1))
|
129
|
+
|
130
|
+
NEW_FILE="$1"
|
131
|
+
if [ -z "$NEW_FILE" ];
|
132
|
+
then
|
133
|
+
echo "Output file name required" >&2
|
134
|
+
exit 1
|
135
|
+
fi
|
136
|
+
|
137
|
+
|
138
|
+
# Check for and remove the temporary directory if it already exists
|
139
|
+
if [ -d "$TEMP_DIR" ];
|
140
|
+
then
|
141
|
+
echo "Removing previous temporary directory: '$TEMP_DIR'" >&2
|
142
|
+
rm -Rf "$TEMP_DIR"
|
143
|
+
fi
|
144
|
+
|
145
|
+
filename=$(basename "$ORIGINAL_FILE")
|
146
|
+
extension="${filename##*.}"
|
147
|
+
filename="${filename%.*}"
|
148
|
+
|
149
|
+
# Check if the supplied file is an ipa or an app file
|
150
|
+
if [ "${extension}" = "ipa" ]
|
151
|
+
then
|
152
|
+
# Unzip the old ipa quietly
|
153
|
+
unzip -q "$ORIGINAL_FILE" -d $TEMP_DIR
|
154
|
+
checkStatus
|
155
|
+
elif [ "${extension}" = "app" ]
|
156
|
+
then
|
157
|
+
# Copy the app file into an ipa-like structure
|
158
|
+
mkdir -p "$TEMP_DIR/Payload"
|
159
|
+
cp -Rf "${ORIGINAL_FILE}" "$TEMP_DIR/Payload/${filename}.app"
|
160
|
+
checkStatus
|
161
|
+
else
|
162
|
+
echo "Error: Only can resign .app files and .ipa files." >&2
|
163
|
+
exit
|
164
|
+
fi
|
165
|
+
|
166
|
+
# check the keychain
|
167
|
+
if [ "${KEYCHAIN}" != "" ];
|
168
|
+
then
|
169
|
+
security list-keychains -s $KEYCHAIN
|
170
|
+
security unlock $KEYCHAIN
|
171
|
+
security default-keychain -s $KEYCHAIN
|
172
|
+
fi
|
173
|
+
|
174
|
+
# Set the app name
|
175
|
+
# The app name is the only file within the Payload directory
|
176
|
+
APP_NAME=$(ls "$TEMP_DIR/Payload/")
|
177
|
+
|
178
|
+
# Make sure that PATH includes the location of the PlistBuddy helper tool as its location is not standard
|
179
|
+
export PATH=$PATH:/usr/libexec
|
180
|
+
|
181
|
+
# Make sure that the Info.plist file is where we expect it
|
182
|
+
if [ ! -e "$TEMP_DIR/Payload/$APP_NAME/Info.plist" ];
|
183
|
+
then
|
184
|
+
echo "Expected file does not exist: '$TEMP_DIR/Payload/$APP_NAME/Info.plist'" >&2
|
185
|
+
exit 1;
|
186
|
+
fi
|
187
|
+
|
188
|
+
# Read in current values from the app
|
189
|
+
CURRENT_NAME=`PlistBuddy -c "Print :CFBundleDisplayName" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
190
|
+
CURRENT_BUNDLE_IDENTIFIER=`PlistBuddy -c "Print :CFBundleIdentifier" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
191
|
+
if [ "${BUNDLE_IDENTIFIER}" == "" ];
|
192
|
+
then
|
193
|
+
BUNDLE_IDENTIFIER=`egrep -a -A 2 application-identifier "${NEW_PROVISION}" | grep string | sed -e 's/<string>//' -e 's/<\/string>//' -e 's/ //' | awk '{split($0,a,"."); i = length(a); for(ix=2; ix <= i;ix++){ s=s a[ix]; if(i!=ix){s=s "."};} print s;}'`
|
194
|
+
if [[ "${BUNDLE_IDENTIFIER}" == *\** ]]; then
|
195
|
+
echo "Bundle Identifier contains a *, using the current bundle identifier" >&2
|
196
|
+
BUNDLE_IDENTIFIER=$CURRENT_BUNDLE_IDENTIFIER;
|
197
|
+
fi
|
198
|
+
checkStatus
|
199
|
+
fi
|
200
|
+
|
201
|
+
echo "Current bundle identifier is: '$CURRENT_BUNDLE_IDENTIFIER'" >&2
|
202
|
+
echo "New bundle identifier will be: '$BUNDLE_IDENTIFIER'" >&2
|
203
|
+
|
204
|
+
# Update the CFBundleDisplayName property in the Info.plist if a new name has been provided
|
205
|
+
if [ "${DISPLAY_NAME}" != "" ];
|
206
|
+
then
|
207
|
+
if [ "${DISPLAY_NAME}" != "${CURRENT_NAME}" ];
|
208
|
+
then
|
209
|
+
echo "Changing display name from '$CURRENT_NAME' to '$DISPLAY_NAME'" >&2
|
210
|
+
`PlistBuddy -c "Set :CFBundleDisplayName $DISPLAY_NAME" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
211
|
+
fi
|
212
|
+
fi
|
213
|
+
|
214
|
+
# Replace the embedded mobile provisioning profile
|
215
|
+
if [ "$NEW_PROVISION" != "" ];
|
216
|
+
then
|
217
|
+
if [[ -e "$NEW_PROVISION" ]];
|
218
|
+
then
|
219
|
+
echo "Validating the new provisioning profile: $NEW_PROVISION" >&2
|
220
|
+
security cms -D -i "$NEW_PROVISION" > "$TEMP_DIR/profile.plist"
|
221
|
+
checkStatus
|
222
|
+
|
223
|
+
APP_IDENTIFER_PREFIX=`PlistBuddy -c "Print :Entitlements:application-identifier" "$TEMP_DIR/profile.plist" | grep -E '^[A-Z0-9]*' -o | tr -d '\n'`
|
224
|
+
if [ "$APP_IDENTIFER_PREFIX" == "" ];
|
225
|
+
then
|
226
|
+
APP_IDENTIFER_PREFIX=`PlistBuddy -c "Print :ApplicationIdentifierPrefix:0" "$TEMP_DIR/profile.plist"`
|
227
|
+
if [ "$APP_IDENTIFER_PREFIX" == "" ];
|
228
|
+
then
|
229
|
+
echo "Failed to extract any app identifier prefix from '$NEW_PROVISION'" >&2
|
230
|
+
exit 1;
|
231
|
+
else
|
232
|
+
echo "WARNING: extracted an app identifier prefix '$APP_IDENTIFER_PREFIX' from '$NEW_PROVISION', but it was not found in the profile's entitlements" >&2
|
233
|
+
fi
|
234
|
+
else
|
235
|
+
echo "Profile app identifier prefix is '$APP_IDENTIFER_PREFIX'" >&2
|
236
|
+
fi
|
237
|
+
|
238
|
+
TEAM_IDENTIFIER=`PlistBuddy -c "Print :Entitlements:com.apple.developer.team-identifier" "$TEMP_DIR/profile.plist" | tr -d '\n'`
|
239
|
+
if [ "$TEAM_IDENTIFIER" == "" ];
|
240
|
+
then
|
241
|
+
TEAM_IDENTIFIER=`PlistBuddy -c "Print :TeamIdentifier:0" "$TEMP_DIR/profile.plist"`
|
242
|
+
if [ "$TEAM_IDENTIFIER" == "" ];
|
243
|
+
then
|
244
|
+
echo "Failed to extract team identifier from '$NEW_PROVISION', resigned ipa may fail on iOS 8 and higher" >&2
|
245
|
+
else
|
246
|
+
echo "WARNING: extracted a team identifier '$TEAM_IDENTIFIER' from '$NEW_PROVISION', but it was not found in the profile's entitlements, resigned ipa may fail on iOS 8 and higher" >&2
|
247
|
+
fi
|
248
|
+
else
|
249
|
+
echo "Profile team identifier is '$TEAM_IDENTIFIER'" >&2
|
250
|
+
fi
|
251
|
+
|
252
|
+
cp "$NEW_PROVISION" "$TEMP_DIR/Payload/$APP_NAME/embedded.mobileprovision"
|
253
|
+
else
|
254
|
+
echo "Provisioning profile '$NEW_PROVISION' file does not exist" >&2
|
255
|
+
exit 1;
|
256
|
+
fi
|
257
|
+
else
|
258
|
+
echo "-p 'xxxx.mobileprovision' argument is required" >&2
|
259
|
+
exit 1;
|
260
|
+
fi
|
261
|
+
|
262
|
+
|
263
|
+
#if the current bundle identifier is different from the new one in the provisioning profile, then change it.
|
264
|
+
if [ "$CURRENT_BUNDLE_IDENTIFIER" != "$BUNDLE_IDENTIFIER" ];
|
265
|
+
then
|
266
|
+
echo "Updating the bundle identifier from '$CURRENT_BUNDLE_IDENTIFIER' to '$BUNDLE_IDENTIFIER'" >&2
|
267
|
+
`PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_IDENTIFIER" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
268
|
+
checkStatus
|
269
|
+
fi
|
270
|
+
|
271
|
+
# Update the version number properties in the Info.plist if a version number has been provided
|
272
|
+
if [ "$VERSION_NUMBER" != "" ];
|
273
|
+
then
|
274
|
+
CURRENT_VERSION_NUMBER=`PlistBuddy -c "Print :CFBundleVersion" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
275
|
+
if [ "$VERSION_NUMBER" != "$CURRENT_VERSION_NUMBER" ];
|
276
|
+
then
|
277
|
+
echo "Updating the version from '$CURRENT_VERSION_NUMBER' to '$VERSION_NUMBER'" >&2
|
278
|
+
`PlistBuddy -c "Set :CFBundleVersion $VERSION_NUMBER" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
279
|
+
`PlistBuddy -c "Set :CFBundleShortVersionString $VERSION_NUMBER" "$TEMP_DIR/Payload/$APP_NAME/Info.plist"`
|
280
|
+
fi
|
281
|
+
fi
|
282
|
+
|
283
|
+
# Check for and resign any embedded frameworks (new feature for iOS 8 and above apps)
|
284
|
+
FRAMEWORKS_DIR="$TEMP_DIR/Payload/$APP_NAME/Frameworks"
|
285
|
+
if [ -d "$FRAMEWORKS_DIR" ];
|
286
|
+
then
|
287
|
+
if [ "$TEAM_IDENTIFIER" == "" ];
|
288
|
+
then
|
289
|
+
echo "ERROR: embedded frameworks detected, re-signing iOS 8 (or higher) applications wihout a team identifier in the certificate/profile does not work" >&2
|
290
|
+
exit 1;
|
291
|
+
fi
|
292
|
+
|
293
|
+
echo "Resigning embedded frameworks using certificate: '$CERTIFICATE'" >&2
|
294
|
+
for framework in "$FRAMEWORKS_DIR"/*
|
295
|
+
do
|
296
|
+
if [[ "$framework" == *.framework ]]
|
297
|
+
then
|
298
|
+
/usr/bin/codesign -f -s "$CERTIFICATE" "$framework"
|
299
|
+
checkStatus
|
300
|
+
else
|
301
|
+
echo "Ignoring non-framework: $framework" >&2
|
302
|
+
fi
|
303
|
+
done
|
304
|
+
fi
|
305
|
+
|
306
|
+
|
307
|
+
# Resign the application
|
308
|
+
if [ "$ENTITLEMENTS" != "" ];
|
309
|
+
then
|
310
|
+
if [ -n "$APP_IDENTIFER_PREFIX" ];
|
311
|
+
then
|
312
|
+
# sanity check the 'application-identifier' is present in the provided entitlements and matches the provisioning profile value
|
313
|
+
ENTITLEMENTS_APP_ID_PREFIX=`PlistBuddy -c "Print :application-identifier" "$ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n'`
|
314
|
+
if [ "$ENTITLEMENTS_APP_ID_PREFIX" == "" ];
|
315
|
+
then
|
316
|
+
echo "Provided entitlements file is missing a value for the required 'application-identifier' key" >&2
|
317
|
+
exit 1;
|
318
|
+
elif [ "$ENTITLEMENTS_APP_ID_PREFIX" != "$APP_IDENTIFER_PREFIX" ];
|
319
|
+
then
|
320
|
+
echo "Provided entitlements file's app identifier prefix value '$ENTITLEMENTS_APP_ID_PREFIX' does not match the provided provisioning profile's value '$APP_IDENTIFER_PREFIX'" >&2
|
321
|
+
exit 1;
|
322
|
+
fi
|
323
|
+
fi
|
324
|
+
|
325
|
+
if [ -n "$TEAM_IDENTIFIER" ];
|
326
|
+
then
|
327
|
+
# sanity check the 'com.apple.developer.team-identifier' is present in the provided entitlements and matches the provisioning profile value
|
328
|
+
ENTITLEMENTS_TEAM_IDENTIFIER=`PlistBuddy -c "Print :com.apple.developer.team-identifier" "$ENTITLEMENTS" | tr -d '\n'`
|
329
|
+
if [ "$ENTITLEMENTS_TEAM_IDENTIFIER" == "" ];
|
330
|
+
then
|
331
|
+
echo "Provided entitlements file is missing a value for the required 'com.apple.developer.team-identifier' key" >&2
|
332
|
+
exit 1;
|
333
|
+
elif [ "$ENTITLEMENTS_TEAM_IDENTIFIER" != "$TEAM_IDENTIFIER" ];
|
334
|
+
then
|
335
|
+
echo "Provided entitlements file's 'com.apple.developer.team-identifier' '$ENTITLEMENTS_TEAM_IDENTIFIER' does not match the provided provisioning profile's value '$TEAM_IDENTIFIER'" >&2
|
336
|
+
exit 1;
|
337
|
+
fi
|
338
|
+
fi
|
339
|
+
|
340
|
+
echo "Resigning application using certificate: '$CERTIFICATE'" >&2
|
341
|
+
echo "and entitlements: $ENTITLEMENTS" >&2
|
342
|
+
/usr/bin/codesign -f -s "$CERTIFICATE" --entitlements="$ENTITLEMENTS" "$TEMP_DIR/Payload/$APP_NAME"
|
343
|
+
checkStatus
|
344
|
+
else
|
345
|
+
echo "Extracting existing entitlements for updating" >&2
|
346
|
+
/usr/bin/codesign -d --entitlements - "$TEMP_DIR/Payload/$APP_NAME" > "$TEMP_DIR/newEntitlements" 2> /dev/null
|
347
|
+
if [ $? -eq 0 ];
|
348
|
+
then
|
349
|
+
ENTITLEMENTS_TEMP=`cat "$TEMP_DIR/newEntitlements" | sed -E -e '1d'`
|
350
|
+
if [ -n "$ENTITLEMENTS_TEMP" ]; then
|
351
|
+
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>$ENTITLEMENTS_TEMP" > "$TEMP_DIR/newEntitlements"
|
352
|
+
if [ -s "$TEMP_DIR/newEntitlements" ];
|
353
|
+
then
|
354
|
+
if [ "$TEAM_IDENTIFIER" != "" ];
|
355
|
+
then
|
356
|
+
PlistBuddy -c "Set :com.apple.developer.team-identifier ${TEAM_IDENTIFIER}" "$TEMP_DIR/newEntitlements"
|
357
|
+
checkStatus
|
358
|
+
fi
|
359
|
+
PlistBuddy -c "Set :application-identifier ${APP_IDENTIFER_PREFIX}.${BUNDLE_IDENTIFIER}" "$TEMP_DIR/newEntitlements"
|
360
|
+
checkStatus
|
361
|
+
PlistBuddy -c "Set :keychain-access-groups:0 ${APP_IDENTIFER_PREFIX}.${BUNDLE_IDENTIFIER}" "$TEMP_DIR/newEntitlements"
|
362
|
+
# checkStatus -- if this fails it's likely because the keychain-access-groups key does not exist, so we have nothing to update
|
363
|
+
if [[ "$CERTIFICATE" == *Distribution* ]]; then
|
364
|
+
echo "Assuming Distribution Identity"
|
365
|
+
if [ "$ADJUST_BETA_REPORTS_ACTIVE_FLAG" == "1" ]; then
|
366
|
+
echo "Ensuring beta-reports-active is present and enabled"
|
367
|
+
# new beta key is only used for Distribution; might not exist yet, if we were building Development
|
368
|
+
PlistBuddy -c "Add :beta-reports-active bool true" "$TEMP_DIR/newEntitlements"
|
369
|
+
if [ $? -ne 0 ]; then
|
370
|
+
PlistBuddy -c "Set :beta-reports-active YES" "$TEMP_DIR/newEntitlements"
|
371
|
+
fi
|
372
|
+
checkStatus
|
373
|
+
fi
|
374
|
+
echo "Setting get-task-allow entitlement to NO"
|
375
|
+
PlistBuddy -c "Set :get-task-allow NO" "$TEMP_DIR/newEntitlements"
|
376
|
+
else
|
377
|
+
echo "Assuming Development Identity"
|
378
|
+
if [ "$ADJUST_BETA_REPORTS_ACTIVE_FLAG" == "1" ]; then
|
379
|
+
# if we were building with Distribution profile, we have to delete the beta key
|
380
|
+
echo "Ensuring beta-reports-active is not included"
|
381
|
+
PlistBuddy -c "Delete :beta-reports-active" "$TEMP_DIR/newEntitlements"
|
382
|
+
# do not check status here, just let it fail if entry does not exist
|
383
|
+
fi
|
384
|
+
echo "Setting get-task-allow entitlement to YES"
|
385
|
+
PlistBuddy -c "Set :get-task-allow YES" "$TEMP_DIR/newEntitlements"
|
386
|
+
fi
|
387
|
+
checkStatus
|
388
|
+
plutil -lint "$TEMP_DIR/newEntitlements" > /dev/null
|
389
|
+
checkStatus
|
390
|
+
echo "Resigning application using certificate: '$CERTIFICATE'" >&2
|
391
|
+
echo "using existing entitlements updated with bundle identifier: '$APP_IDENTIFER_PREFIX.$BUNDLE_IDENTIFIER'" >&2
|
392
|
+
if [ "$TEAM_IDENTIFIER" != "" ];
|
393
|
+
then
|
394
|
+
echo "and team identifier: '$TEAM_IDENTIFIER'" >&2
|
395
|
+
fi
|
396
|
+
/usr/bin/codesign -f -s "$CERTIFICATE" --entitlements="$TEMP_DIR/newEntitlements" "$TEMP_DIR/Payload/$APP_NAME"
|
397
|
+
checkStatus
|
398
|
+
else
|
399
|
+
echo "Failed to create required intermediate file" >&2
|
400
|
+
exit 1;
|
401
|
+
fi
|
402
|
+
else
|
403
|
+
echo "No entitlements found" >&2
|
404
|
+
echo "Resigning application using certificate: '$CERTIFICATE'" >&2
|
405
|
+
echo "without entitlements" >&2
|
406
|
+
/usr/bin/codesign -f -s "$CERTIFICATE" "$TEMP_DIR/Payload/$APP_NAME"
|
407
|
+
checkStatus
|
408
|
+
fi
|
409
|
+
else
|
410
|
+
echo "Failed to extract entitlements" >&2
|
411
|
+
echo "Resigning application using certificate: '$CERTIFICATE'" >&2
|
412
|
+
echo "without entitlements" >&2
|
413
|
+
/usr/bin/codesign -f -s "$CERTIFICATE" "$TEMP_DIR/Payload/$APP_NAME"
|
414
|
+
checkStatus
|
415
|
+
fi
|
416
|
+
fi
|
417
|
+
|
418
|
+
# Remove the temporary files if they were created before generating ipa
|
419
|
+
rm -f "$TEMP_DIR/newEntitlements"
|
420
|
+
rm -f "$TEMP_DIR/profile.plist"
|
421
|
+
|
422
|
+
# Repackage quietly
|
423
|
+
echo "Repackaging as $NEW_FILE" >&2
|
424
|
+
|
425
|
+
# Zip up the contents of the "$TEMP_DIR" folder
|
426
|
+
# Navigate to the temporary directory (sending the output to null)
|
427
|
+
# Zip all the contents, saving the zip file in the above directory
|
428
|
+
# Navigate back to the orignating directory (sending the output to null)
|
429
|
+
pushd "$TEMP_DIR" > /dev/null
|
430
|
+
zip -qr "../$TEMP_DIR.ipa" *
|
431
|
+
popd > /dev/null
|
432
|
+
|
433
|
+
# Move the resulting ipa to the target destination
|
434
|
+
mv "$TEMP_DIR.ipa" "$NEW_FILE"
|
435
|
+
|
436
|
+
# Remove the temp directory
|
437
|
+
rm -rf "$TEMP_DIR"
|
438
|
+
|
439
|
+
echo "Process complete" >&2
|
data/lib/sigh.rb
CHANGED
@@ -76,19 +76,15 @@ module Sigh
|
|
76
76
|
result = visit PROFILES_URL
|
77
77
|
raise "Could not open Developer Center" unless result['status'] == 'success'
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
return true
|
82
|
-
end
|
79
|
+
# Already logged in
|
80
|
+
return true if page.has_content? "Member Center"
|
83
81
|
|
84
82
|
(wait_for_elements(".button.blue").first.click rescue nil) # maybe already logged in
|
85
83
|
|
86
84
|
(wait_for_elements('#accountpassword') rescue nil) # when the user is already logged in, this will raise an exception
|
87
85
|
|
88
|
-
|
89
|
-
|
90
|
-
return true
|
91
|
-
end
|
86
|
+
# Already logged in
|
87
|
+
return true if page.has_content? "Member Center"
|
92
88
|
|
93
89
|
fill_in "accountname", with: user
|
94
90
|
fill_in "accountpassword", with: password
|
@@ -96,9 +92,8 @@ module Sigh
|
|
96
92
|
all(".button.large.blue.signin-button").first.click
|
97
93
|
|
98
94
|
begin
|
99
|
-
|
100
|
-
|
101
|
-
end
|
95
|
+
# If the user is not on multiple teams
|
96
|
+
select_team if page.has_content? "Select Team"
|
102
97
|
rescue => ex
|
103
98
|
Helper.log.debug ex
|
104
99
|
raise DeveloperCenterLoginError.new("Error loggin in user #{user}. User is on multiple teams and we were unable to correctly retrieve them.")
|
@@ -198,37 +193,27 @@ module Sigh
|
|
198
193
|
certs = post_ajax(@list_certs_url)
|
199
194
|
|
200
195
|
Helper.log.info "Checking if profile is available. (#{certs['provisioningProfiles'].count} profiles found)"
|
196
|
+
required_cert_types = type == DEVELOPMENT ? ['iOS Development'] : ['iOS Distribution', 'iOS UniversalDistribution']
|
201
197
|
certs['provisioningProfiles'].each do |current_cert|
|
202
|
-
|
203
|
-
if current_cert['type'] != "iOS Development"
|
204
|
-
next
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
if type != DEVELOPMENT
|
209
|
-
if not ['iOS Distribution', 'iOS UniversalDistribution'].include?current_cert['type']
|
210
|
-
next
|
211
|
-
end
|
212
|
-
end
|
198
|
+
next unless required_cert_types.include?(current_cert['type'])
|
213
199
|
|
214
200
|
details = profile_details(current_cert['provisioningProfileId'])
|
215
201
|
|
216
202
|
if details['provisioningProfile']['appId']['identifier'] == app_identifier
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
end
|
203
|
+
# that's an Ad Hoc profile. I didn't find a better way to detect if it's one ... skipping it
|
204
|
+
next if type == APPSTORE && details['provisioningProfile']['deviceCount'] > 0
|
205
|
+
|
206
|
+
# that's an App Store profile ... skipping it
|
207
|
+
next if type != APPSTORE && details['provisioningProfile']['deviceCount'] == 0
|
223
208
|
|
224
209
|
# We found the correct certificate
|
225
|
-
if force
|
210
|
+
if force && type != DEVELOPMENT
|
226
211
|
provisioningProfileId = current_cert['provisioningProfileId']
|
227
212
|
renew_profile(provisioningProfileId, type, cert_date) # This one needs to be forcefully renewed
|
228
213
|
return maintain_app_certificate(app_identifier, type, false, cert_date) # recursive
|
229
214
|
elsif current_cert['status'] == 'Active'
|
230
215
|
return download_profile(details['provisioningProfile']['provisioningProfileId']) # this one is already finished. Just download it.
|
231
|
-
elsif ['Expired', 'Invalid'].include?current_cert['status']
|
216
|
+
elsif ['Expired', 'Invalid'].include? current_cert['status']
|
232
217
|
renew_profile(current_cert['provisioningProfileId'], type, cert_date) # This one needs to be renewed
|
233
218
|
return maintain_app_certificate(app_identifier, type, false, cert_date) # recursive
|
234
219
|
end
|
@@ -250,7 +235,7 @@ module Sigh
|
|
250
235
|
|
251
236
|
def create_profile(app_identifier, type, cert_date)
|
252
237
|
Helper.log.info "Creating new profile for app '#{app_identifier}' for type '#{type}'.".yellow
|
253
|
-
|
238
|
+
certificates = code_signing_certificates(type, cert_date)
|
254
239
|
|
255
240
|
create_url = "https://developer.apple.com/account/ios/profile/profileCreate.action"
|
256
241
|
visit create_url
|
@@ -265,7 +250,7 @@ module Sigh
|
|
265
250
|
enterprise = true
|
266
251
|
end
|
267
252
|
|
268
|
-
value =
|
253
|
+
value = enterprise ? 'inhouse' : 'store'
|
269
254
|
value = 'limited' if type == DEVELOPMENT
|
270
255
|
value = 'adhoc' if type == ADHOC
|
271
256
|
|
@@ -273,7 +258,7 @@ module Sigh
|
|
273
258
|
click_next
|
274
259
|
|
275
260
|
# 2) Select the App ID
|
276
|
-
while
|
261
|
+
sleep 1 while !page.has_content? "Select App ID"
|
277
262
|
# example: <option value="RGAWZGXSY4">ABP (5A997XSHK2.net.sunapps.34)</option>
|
278
263
|
identifiers = all(:xpath, "//option[contains(text(), '.#{app_identifier})')]")
|
279
264
|
if identifiers.count == 0
|
@@ -288,19 +273,32 @@ module Sigh
|
|
288
273
|
click_next
|
289
274
|
|
290
275
|
# 3) Select the certificate
|
291
|
-
while
|
276
|
+
sleep 1 while !page.has_content? "Select certificates"
|
292
277
|
sleep 3
|
293
|
-
Helper.log.info "Using
|
278
|
+
Helper.log.info "Using certificates: #{certificates.map { |c| "#{c['ownerName']} (#{c['certificateId']})" } }"
|
294
279
|
|
295
280
|
# example: <input type="radio" name="certificateIds" class="validate" value="[XC5PH8D47H]"> (production)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
281
|
+
|
282
|
+
clicked = false
|
283
|
+
certificates.each do |cert|
|
284
|
+
cert_id = cert['certificateId']
|
285
|
+
input = if type == DEVELOPMENT
|
286
|
+
# development uses a checkbox and has no [] around the value
|
287
|
+
first(:xpath, "//input[@type='checkbox' and @value='#{cert_id}']")
|
288
|
+
else
|
289
|
+
break if clicked
|
290
|
+
# production uses radio and has a [] around the value
|
291
|
+
first(:xpath, "//input[@type='radio' and @value='[#{cert_id}]']")
|
292
|
+
end
|
293
|
+
if input
|
294
|
+
input.click
|
295
|
+
clicked = true
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
if !clicked
|
301
300
|
raise "Could not find certificate in the list of available certificates."
|
302
301
|
end
|
303
|
-
certs.first.click
|
304
302
|
click_next
|
305
303
|
|
306
304
|
if type != APPSTORE
|
@@ -321,7 +319,7 @@ module Sigh
|
|
321
319
|
end
|
322
320
|
|
323
321
|
def renew_profile(profile_id, type, cert_date)
|
324
|
-
certificate =
|
322
|
+
certificate = code_signing_certificates(type, cert_date).first
|
325
323
|
|
326
324
|
details_url = "https://developer.apple.com/account/ios/profile/profileEdit.action?type=&provisioningProfileId=#{profile_id}"
|
327
325
|
Helper.log.info "Renewing provisioning profile '#{profile_id}' using URL '#{details_url}'"
|
@@ -367,9 +365,9 @@ module Sigh
|
|
367
365
|
end
|
368
366
|
end
|
369
367
|
|
370
|
-
# Returns a
|
368
|
+
# Returns a array of hashs, that contains information about the iOS certificate
|
371
369
|
# @example
|
372
|
-
# {"certRequestId"=>"B23Q2P396B",
|
370
|
+
# [{"certRequestId"=>"B23Q2P396B",
|
373
371
|
# "name"=>"SunApps GmbH",
|
374
372
|
# "statusString"=>"Issued",
|
375
373
|
# "expirationDate"=>"2015-11-25T22:45:50Z",
|
@@ -385,10 +383,10 @@ module Sigh
|
|
385
383
|
# "certificateTypeDisplayId"=>"...",
|
386
384
|
# "serialNum"=>"....",
|
387
385
|
# "typeString"=>"iOS Distribution"},
|
388
|
-
|
386
|
+
# {another sertificate...}]
|
387
|
+
def code_signing_certificates(type, cert_date)
|
389
388
|
certs_url = "https://developer.apple.com/account/ios/certificate/certificateList.action?type="
|
390
|
-
certs_url <<
|
391
|
-
certs_url << "development" if type == DEVELOPMENT
|
389
|
+
certs_url << (type == DEVELOPMENT ? 'development' : 'distribution')
|
392
390
|
visit certs_url
|
393
391
|
|
394
392
|
certificateDataURL = wait_for_variable('certificateDataURL')
|
@@ -400,27 +398,44 @@ module Sigh
|
|
400
398
|
# 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
|
401
399
|
|
402
400
|
certs = post_ajax(url)['certRequests']
|
401
|
+
|
402
|
+
ret_certs = []
|
403
|
+
certificate_name = ENV['SIGH_CERTIFICATE']
|
404
|
+
|
405
|
+
# The other profiles are push profiles
|
406
|
+
certificate_type = type == DEVELOPMENT ? 'iOS Development' : 'iOS Distribution'
|
407
|
+
|
408
|
+
# New profiles first
|
409
|
+
certs.sort! do |a, b|
|
410
|
+
Time.parse(b['expirationDate']) <=> Time.parse(a['expirationDate'])
|
411
|
+
end
|
412
|
+
|
403
413
|
certs.each do |current_cert|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
+
next unless current_cert['typeString'] == certificate_type
|
415
|
+
|
416
|
+
if cert_date || certificate_name
|
417
|
+
if current_cert['expirationDateString'] == cert_date
|
418
|
+
Helper.log.info "Certificate ID '#{current_cert['certificateId']}' with expiry date '#{current_cert['expirationDateString']}' located"
|
419
|
+
ret_certs << current_cert
|
420
|
+
end
|
421
|
+
if current_cert['name'] == certificate_name
|
422
|
+
Helper.log.info "Certificate ID '#{current_cert['certificateId']}' with name '#{certificate_name}' located"
|
423
|
+
ret_certs << current_cert
|
414
424
|
end
|
415
|
-
|
416
|
-
|
425
|
+
else
|
426
|
+
ret_certs << current_cert
|
417
427
|
end
|
418
428
|
end
|
419
429
|
|
420
|
-
|
421
|
-
|
430
|
+
return ret_certs unless ret_certs.empty?
|
431
|
+
|
432
|
+
predicates = []
|
433
|
+
predicates << "name: #{certificate_name}" if certificate_name
|
434
|
+
predicates << "expiry date: #{cert_date}" if cert_date
|
435
|
+
|
436
|
+
predicates_str = " with #{predicates.join(' or ')}"
|
422
437
|
|
423
|
-
raise
|
438
|
+
raise "Could not find a Certificate#{predicates_str}. Please open #{current_url} and make sure you have a signing profile created.".red
|
424
439
|
end
|
425
440
|
|
426
441
|
# Download a file from the dev center, by using a HTTP client. This will return the content of the file
|
@@ -464,7 +479,7 @@ module Sigh
|
|
464
479
|
def wait_for(method, parameter, success)
|
465
480
|
counter = 0
|
466
481
|
result = method.call(parameter)
|
467
|
-
while !success.call(result)
|
482
|
+
while !success.call(result)
|
468
483
|
sleep 0.2
|
469
484
|
|
470
485
|
result = method.call(parameter)
|
data/lib/sigh/helper.rb
CHANGED
@@ -45,5 +45,14 @@ module Sigh
|
|
45
45
|
return "" if self.is_test? and not OS.mac?
|
46
46
|
`xcode-select -p`.gsub("\n", '') + "/"
|
47
47
|
end
|
48
|
+
|
49
|
+
# Path to the installed gem to load resources (e.g. resign.sh)
|
50
|
+
def self.gem_path
|
51
|
+
if not Helper.is_test? and Gem::Specification::find_all_by_name('sigh').any?
|
52
|
+
return Gem::Specification.find_by_name('sigh').gem_dir
|
53
|
+
else
|
54
|
+
return './'
|
55
|
+
end
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
data/lib/sigh/resign.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Sigh
|
2
|
+
# Resigns an existing ipa file
|
3
|
+
class Resign
|
4
|
+
def run(options)
|
5
|
+
get_inputs(options)
|
6
|
+
|
7
|
+
command = [
|
8
|
+
@resign_path,
|
9
|
+
"'#{@ipa}'",
|
10
|
+
"'#{@signing_identity}'",
|
11
|
+
"-p '#{@provisioning_profile}'",
|
12
|
+
"'#{@ipa}'"
|
13
|
+
].join(' ')
|
14
|
+
|
15
|
+
puts command.magenta
|
16
|
+
puts `#{command}`
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_inputs(options)
|
20
|
+
@resign_path = File.join(Helper.gem_path, 'lib', 'assets', 'resign.sh')
|
21
|
+
raise "Could not find resign.sh file. Please try re-installing the gem.".red unless File.exists?@resign_path
|
22
|
+
|
23
|
+
@ipa = options.ipa || find_ipa || ask("Path to ipa file: ")
|
24
|
+
@signing_identity = options.signing_identity || ask_for_signing_identity
|
25
|
+
validate_signing_identity
|
26
|
+
@provisioning_profile = options.provisioning_profile || find_provisioning_profile || ask("Path to provisioning file: ")
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_ipa
|
30
|
+
Dir[File.join(Dir.pwd, "*.ipa")].sort { |a,b| File.mtime(a) <=> File.mtime(b) }.first
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_provisioning_profile
|
34
|
+
Dir[File.join(Dir.pwd, "*.mobileprovision")].sort { |a,b| File.mtime(a) <=> File.mtime(b) }.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_signing_identity
|
38
|
+
while not installed_identies.include?@signing_identity
|
39
|
+
Helper.log.error "Couldn't find signing identity '#{@signing_identity}'. Available identities: \n\t#{installed_identies.join("\n\t")}\n"
|
40
|
+
@signing_identity = ask_for_signing_identity
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ask_for_signing_identity
|
45
|
+
ask("Signing Identity (e.g. 'iPhone Distribution: SunApps GmbH (5A997XAHK2)'): ")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Array of available signing identities
|
49
|
+
def installed_identies
|
50
|
+
available = `security find-identity -v -p codesigning`
|
51
|
+
ids = []
|
52
|
+
available.split("\n").each do |current|
|
53
|
+
(ids << current.match(/.*\"(.*)\"/)[1]) rescue nil # the last line does not match
|
54
|
+
end
|
55
|
+
|
56
|
+
return ids
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/sigh/version.rb
CHANGED
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
|
+
version: 0.3.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-02-
|
11
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.
|
61
|
+
version: 4.3.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.
|
68
|
+
version: 4.3.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: credentials_manager
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -232,10 +232,12 @@ files:
|
|
232
232
|
- LICENSE
|
233
233
|
- README.md
|
234
234
|
- bin/sigh
|
235
|
+
- lib/assets/resign.sh
|
235
236
|
- lib/sigh.rb
|
236
237
|
- lib/sigh/dependency_checker.rb
|
237
238
|
- lib/sigh/developer_center.rb
|
238
239
|
- lib/sigh/helper.rb
|
240
|
+
- lib/sigh/resign.rb
|
239
241
|
- lib/sigh/update_checker.rb
|
240
242
|
- lib/sigh/version.rb
|
241
243
|
homepage: http://fastlane.tools
|