sigh 0.2.4 → 0.3.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 +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
|