mysigner 0.1.2 → 0.1.3
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/.githooks/pre-commit +15 -0
- data/.githooks/pre-push +21 -0
- data/.github/workflows/ci.yml +29 -0
- data/.rubocop.yml +55 -0
- data/.rubocop_todo.yml +112 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +5 -3
- data/Gemfile.lock +38 -8
- data/README.md +13 -15
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/bin/setup +3 -0
- data/exe/mysigner +2 -1
- data/lib/mysigner/build/android_executor.rb +46 -52
- data/lib/mysigner/build/android_parser.rb +33 -40
- data/lib/mysigner/build/configurator.rb +17 -16
- data/lib/mysigner/build/detector.rb +39 -50
- data/lib/mysigner/build/error_analyzer.rb +70 -68
- data/lib/mysigner/build/executor.rb +30 -37
- data/lib/mysigner/build/parser.rb +18 -18
- data/lib/mysigner/cli/auth_commands.rb +735 -752
- data/lib/mysigner/cli/build_commands.rb +697 -721
- data/lib/mysigner/cli/concerns/actionable_suggestions.rb +208 -154
- data/lib/mysigner/cli/concerns/api_helpers.rb +46 -54
- data/lib/mysigner/cli/concerns/error_handlers.rb +247 -237
- data/lib/mysigner/cli/concerns/helpers.rb +12 -1
- data/lib/mysigner/cli/diagnostic_commands.rb +659 -635
- data/lib/mysigner/cli/resource_commands.rb +880 -902
- data/lib/mysigner/cli/validate_commands.rb +25 -25
- data/lib/mysigner/cli.rb +3 -1
- data/lib/mysigner/client.rb +27 -19
- data/lib/mysigner/config.rb +93 -56
- data/lib/mysigner/export/exporter.rb +32 -36
- data/lib/mysigner/signing/certificate_checker.rb +18 -23
- data/lib/mysigner/signing/keystore_manager.rb +34 -39
- data/lib/mysigner/signing/validator.rb +38 -40
- data/lib/mysigner/signing/wizard.rb +329 -342
- data/lib/mysigner/upload/app_store_automation.rb +51 -49
- data/lib/mysigner/upload/app_store_submission.rb +87 -92
- data/lib/mysigner/upload/play_store_uploader.rb +98 -115
- data/lib/mysigner/upload/uploader.rb +101 -109
- data/lib/mysigner/version.rb +3 -1
- data/lib/mysigner.rb +13 -11
- data/mysigner.gemspec +36 -33
- data/test_manual.rb +37 -36
- metadata +37 -16
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
1
4
|
require 'fileutils'
|
|
2
5
|
require 'tempfile'
|
|
3
6
|
|
|
@@ -20,7 +23,8 @@ module Mysigner
|
|
|
20
23
|
# - key_alias: Key alias in keystore
|
|
21
24
|
# - key_password: Key password (defaults to keystore_password)
|
|
22
25
|
# - version_code: Override version code (passed via gradle property)
|
|
23
|
-
def build_aab!(variant: 'release', keystore_path: nil, keystore_password: nil, key_alias: nil, key_password: nil,
|
|
26
|
+
def build_aab!(variant: 'release', keystore_path: nil, keystore_password: nil, key_alias: nil, key_password: nil,
|
|
27
|
+
version_code: nil)
|
|
24
28
|
@variant = variant
|
|
25
29
|
@keystore_path = keystore_path
|
|
26
30
|
@keystore_password = keystore_password
|
|
@@ -34,13 +38,11 @@ module Mysigner
|
|
|
34
38
|
# Build
|
|
35
39
|
success = run_gradle_build(task)
|
|
36
40
|
|
|
37
|
-
unless success
|
|
38
|
-
raise BuildError, "Android build failed. Check output above for errors."
|
|
39
|
-
end
|
|
41
|
+
raise BuildError, 'Android build failed. Check output above for errors.' unless success
|
|
40
42
|
|
|
41
43
|
# Find output AAB
|
|
42
44
|
aab_path = find_aab_output(variant)
|
|
43
|
-
|
|
45
|
+
|
|
44
46
|
unless aab_path && File.exist?(aab_path)
|
|
45
47
|
raise BuildError, "Build reported success but AAB not found. Expected at: #{@parser.aab_output_path(variant)}"
|
|
46
48
|
end
|
|
@@ -63,13 +65,11 @@ module Mysigner
|
|
|
63
65
|
# Build
|
|
64
66
|
success = run_gradle_build(task)
|
|
65
67
|
|
|
66
|
-
unless success
|
|
67
|
-
raise BuildError, "Android build failed. Check output above for errors."
|
|
68
|
-
end
|
|
68
|
+
raise BuildError, 'Android build failed. Check output above for errors.' unless success
|
|
69
69
|
|
|
70
70
|
# Find output APK
|
|
71
71
|
apk_path = find_apk_output(variant)
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
unless apk_path && File.exist?(apk_path)
|
|
74
74
|
raise BuildError, "Build reported success but APK not found. Expected at: #{@parser.apk_output_path(variant)}"
|
|
75
75
|
end
|
|
@@ -99,7 +99,7 @@ module Mysigner
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def ensure_java_home!
|
|
102
|
-
java_home = ENV
|
|
102
|
+
java_home = ENV.fetch('JAVA_HOME', nil)
|
|
103
103
|
|
|
104
104
|
# Check if JAVA_HOME is set and valid
|
|
105
105
|
if java_home && !java_home.empty? && Dir.exist?(java_home)
|
|
@@ -112,8 +112,8 @@ module Mysigner
|
|
|
112
112
|
ENV['JAVA_HOME'] = detected
|
|
113
113
|
elsif java_home && !java_home.empty?
|
|
114
114
|
raise BuildError, "JAVA_HOME is set to invalid directory: #{java_home}\n" \
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
"Run 'mysigner doctor' to fix, or set JAVA_HOME manually:\n " \
|
|
116
|
+
'export JAVA_HOME=$(/usr/libexec/java_home -v 17)'
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -122,12 +122,10 @@ module Mysigner
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
def ensure_android_home!
|
|
125
|
-
android_home = ENV['ANDROID_HOME'] || ENV
|
|
125
|
+
android_home = ENV['ANDROID_HOME'] || ENV.fetch('ANDROID_SDK_ROOT', nil)
|
|
126
126
|
|
|
127
127
|
# Check if already valid
|
|
128
|
-
if android_home && !android_home.empty? && Dir.exist?(android_home)
|
|
129
|
-
return
|
|
130
|
-
end
|
|
128
|
+
return if android_home && !android_home.empty? && Dir.exist?(android_home)
|
|
131
129
|
|
|
132
130
|
# Try to detect Android SDK
|
|
133
131
|
detected = detect_android_home
|
|
@@ -137,8 +135,8 @@ module Mysigner
|
|
|
137
135
|
ENV['ANDROID_SDK_ROOT'] = detected
|
|
138
136
|
else
|
|
139
137
|
raise BuildError, "Android SDK not found.\n" \
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
"Run 'mysigner doctor' to diagnose, or set ANDROID_HOME:\n " \
|
|
139
|
+
'export ANDROID_HOME=~/Library/Android/sdk'
|
|
142
140
|
end
|
|
143
141
|
end
|
|
144
142
|
|
|
@@ -190,7 +188,7 @@ module Mysigner
|
|
|
190
188
|
case @project_info[:framework]
|
|
191
189
|
when :capacitor
|
|
192
190
|
# Capacitor: sync before build
|
|
193
|
-
puts
|
|
191
|
+
puts '🔄 Syncing Capacitor...'
|
|
194
192
|
Dir.chdir(@project_info[:directory]) do
|
|
195
193
|
system('npx cap sync android > /dev/null 2>&1')
|
|
196
194
|
end
|
|
@@ -199,14 +197,14 @@ module Mysigner
|
|
|
199
197
|
if File.exist?(File.join(@project_info[:directory], 'node_modules'))
|
|
200
198
|
# Dependencies already installed
|
|
201
199
|
else
|
|
202
|
-
puts
|
|
200
|
+
puts '📦 Installing npm dependencies...'
|
|
203
201
|
Dir.chdir(@project_info[:directory]) do
|
|
204
202
|
system('npm install > /dev/null 2>&1') || system('yarn install > /dev/null 2>&1')
|
|
205
203
|
end
|
|
206
204
|
end
|
|
207
205
|
when :flutter
|
|
208
206
|
# Flutter: ensure dependencies are fetched
|
|
209
|
-
puts
|
|
207
|
+
puts '📦 Getting Flutter dependencies...'
|
|
210
208
|
Dir.chdir(@project_info[:directory]) do
|
|
211
209
|
system('flutter pub get > /dev/null 2>&1')
|
|
212
210
|
end
|
|
@@ -218,26 +216,26 @@ module Mysigner
|
|
|
218
216
|
gradle_cmd = @parser.gradle_command
|
|
219
217
|
|
|
220
218
|
cmd_parts = []
|
|
221
|
-
|
|
219
|
+
|
|
222
220
|
# Export JAVA_HOME if we detected/fixed it
|
|
223
|
-
java_home = ENV
|
|
221
|
+
java_home = ENV.fetch('JAVA_HOME', nil)
|
|
224
222
|
if java_home && Dir.exist?(java_home)
|
|
225
223
|
cmd_parts << "export JAVA_HOME=#{shell_escape(java_home)}"
|
|
226
|
-
cmd_parts <<
|
|
224
|
+
cmd_parts << '&&'
|
|
227
225
|
end
|
|
228
226
|
|
|
229
227
|
# Export ANDROID_HOME if we detected/fixed it
|
|
230
|
-
android_home = ENV
|
|
228
|
+
android_home = ENV.fetch('ANDROID_HOME', nil)
|
|
231
229
|
if android_home && Dir.exist?(android_home)
|
|
232
230
|
cmd_parts << "export ANDROID_HOME=#{shell_escape(android_home)}"
|
|
233
|
-
cmd_parts <<
|
|
231
|
+
cmd_parts << '&&'
|
|
234
232
|
cmd_parts << "export ANDROID_SDK_ROOT=#{shell_escape(android_home)}"
|
|
235
|
-
cmd_parts <<
|
|
233
|
+
cmd_parts << '&&'
|
|
236
234
|
end
|
|
237
|
-
|
|
235
|
+
|
|
238
236
|
# Change to android directory and run gradle
|
|
239
237
|
cmd_parts << "cd #{shell_escape(android_dir)}"
|
|
240
|
-
cmd_parts <<
|
|
238
|
+
cmd_parts << '&&'
|
|
241
239
|
cmd_parts << gradle_cmd
|
|
242
240
|
cmd_parts << task
|
|
243
241
|
|
|
@@ -248,15 +246,13 @@ module Mysigner
|
|
|
248
246
|
cmd_parts << "-Pandroid.injected.signing.key.alias=#{shell_escape(@key_alias)}" if @key_alias
|
|
249
247
|
cmd_parts << "-Pandroid.injected.signing.key.password=#{shell_escape(@key_password)}" if @key_password
|
|
250
248
|
end
|
|
251
|
-
|
|
249
|
+
|
|
252
250
|
# Add version code override if provided (no file modification needed)
|
|
253
|
-
if @version_code
|
|
254
|
-
cmd_parts << "-PversionCode=#{@version_code}"
|
|
255
|
-
end
|
|
251
|
+
cmd_parts << "-PversionCode=#{@version_code}" if @version_code
|
|
256
252
|
|
|
257
253
|
# Standard build options
|
|
258
|
-
cmd_parts <<
|
|
259
|
-
cmd_parts <<
|
|
254
|
+
cmd_parts << '--no-daemon' # Avoid daemon issues in CI
|
|
255
|
+
cmd_parts << '-q' # Quiet mode (less noise)
|
|
260
256
|
|
|
261
257
|
cmd_parts.join(' ')
|
|
262
258
|
end
|
|
@@ -266,29 +262,29 @@ module Mysigner
|
|
|
266
262
|
gradle_cmd = @parser.gradle_command
|
|
267
263
|
|
|
268
264
|
exports = []
|
|
269
|
-
java_home = ENV
|
|
265
|
+
java_home = ENV.fetch('JAVA_HOME', nil)
|
|
270
266
|
exports << "export JAVA_HOME=#{shell_escape(java_home)}" if java_home && Dir.exist?(java_home)
|
|
271
|
-
|
|
272
|
-
android_home = ENV
|
|
267
|
+
|
|
268
|
+
android_home = ENV.fetch('ANDROID_HOME', nil)
|
|
273
269
|
if android_home && Dir.exist?(android_home)
|
|
274
270
|
exports << "export ANDROID_HOME=#{shell_escape(android_home)}"
|
|
275
271
|
exports << "export ANDROID_SDK_ROOT=#{shell_escape(android_home)}"
|
|
276
272
|
end
|
|
277
|
-
|
|
278
|
-
export_str = exports.any? ? exports.join(' && ')
|
|
273
|
+
|
|
274
|
+
export_str = exports.any? ? "#{exports.join(' && ')} && " : ''
|
|
279
275
|
cmd = "#{export_str}cd #{shell_escape(android_dir)} && #{gradle_cmd} #{task} --no-daemon -q"
|
|
280
276
|
system(cmd)
|
|
281
277
|
end
|
|
282
278
|
|
|
283
279
|
def execute_with_output(cmd)
|
|
284
280
|
puts "🏗️ Running: gradle #{@variant}..."
|
|
285
|
-
puts
|
|
281
|
+
puts ''
|
|
286
282
|
|
|
287
283
|
# Run command and capture output in real-time
|
|
288
284
|
IO.popen("#{cmd} 2>&1", 'r') do |io|
|
|
289
285
|
io.each_line do |line|
|
|
290
286
|
next if line.strip.empty?
|
|
291
|
-
|
|
287
|
+
|
|
292
288
|
# Show errors and warnings
|
|
293
289
|
if line.include?('FAILURE') || line.include?('ERROR') || line.include?('error:')
|
|
294
290
|
puts line
|
|
@@ -304,14 +300,14 @@ module Mysigner
|
|
|
304
300
|
end
|
|
305
301
|
end
|
|
306
302
|
|
|
307
|
-
puts
|
|
303
|
+
puts '' # New line after dots
|
|
308
304
|
|
|
309
|
-
|
|
305
|
+
$CHILD_STATUS.success?
|
|
310
306
|
end
|
|
311
307
|
|
|
312
308
|
def find_aab_output(variant)
|
|
313
309
|
android_dir = @parser.android_directory
|
|
314
|
-
|
|
310
|
+
|
|
315
311
|
# Search patterns for AAB files
|
|
316
312
|
patterns = [
|
|
317
313
|
File.join(android_dir, "app/build/outputs/bundle/#{variant}/*.aab"),
|
|
@@ -332,7 +328,7 @@ module Mysigner
|
|
|
332
328
|
|
|
333
329
|
def find_apk_output(variant)
|
|
334
330
|
android_dir = @parser.android_directory
|
|
335
|
-
|
|
331
|
+
|
|
336
332
|
# Search patterns for APK files
|
|
337
333
|
patterns = [
|
|
338
334
|
File.join(android_dir, "app/build/outputs/apk/#{variant}/*.apk"),
|
|
@@ -353,14 +349,12 @@ module Mysigner
|
|
|
353
349
|
|
|
354
350
|
def shell_escape(str)
|
|
355
351
|
return "''" if str.nil? || str.empty?
|
|
356
|
-
|
|
352
|
+
|
|
357
353
|
# If string contains no special characters, return as-is
|
|
358
|
-
if str =~
|
|
359
|
-
|
|
360
|
-
end
|
|
361
|
-
|
|
354
|
+
return str if str =~ %r{\A[a-zA-Z0-9_.\-/]+\z}
|
|
355
|
+
|
|
362
356
|
# Otherwise, quote it
|
|
363
|
-
"'
|
|
357
|
+
"'#{str.gsub("'", "'\\''")}'"
|
|
364
358
|
end
|
|
365
359
|
end
|
|
366
360
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mysigner
|
|
2
4
|
module Build
|
|
3
5
|
class AndroidParser
|
|
@@ -57,42 +59,41 @@ module Mysigner
|
|
|
57
59
|
# Get all build types (debug, release, etc.)
|
|
58
60
|
def build_types
|
|
59
61
|
types = []
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
# Match buildTypes block
|
|
62
64
|
if @gradle_content =~ /buildTypes\s*\{(.*?)\n\s*\}/m
|
|
63
|
-
block =
|
|
65
|
+
block = ::Regexp.last_match(1)
|
|
64
66
|
# Find all type names (e.g., "release {" or "debug {")
|
|
65
67
|
block.scan(/(\w+)\s*\{/) do |match|
|
|
66
68
|
types << match[0] unless %w[debug release].include?(match[0]) && types.include?(match[0])
|
|
67
69
|
types << match[0]
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
|
-
|
|
72
|
+
|
|
71
73
|
# Default build types if none found
|
|
72
|
-
types = [
|
|
74
|
+
types = %w[debug release] if types.empty?
|
|
73
75
|
types.uniq
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
# Get all product flavors
|
|
77
79
|
def product_flavors
|
|
78
80
|
flavors = []
|
|
79
|
-
|
|
81
|
+
|
|
80
82
|
if @gradle_content =~ /productFlavors\s*\{(.*?)\n\s{4}\}/m
|
|
81
|
-
block =
|
|
83
|
+
block = ::Regexp.last_match(1)
|
|
82
84
|
block.scan(/(\w+)\s*\{/) do |match|
|
|
83
85
|
flavors << match[0]
|
|
84
86
|
end
|
|
85
87
|
end
|
|
86
|
-
|
|
88
|
+
|
|
87
89
|
flavors
|
|
88
90
|
end
|
|
89
91
|
|
|
90
92
|
# Get signing config for a build type
|
|
91
93
|
def signing_config(build_type = 'release')
|
|
92
94
|
# Look for signingConfig in the build type block
|
|
93
|
-
if @gradle_content =~ /#{build_type}\s*\{[^}]*signingConfig\s*(?:=\s*)?signingConfigs\.(\w+)/m
|
|
94
|
-
|
|
95
|
-
end
|
|
95
|
+
return ::Regexp.last_match(1) if @gradle_content =~ /#{build_type}\s*\{[^}]*signingConfig\s*(?:=\s*)?signingConfigs\.(\w+)/m
|
|
96
|
+
|
|
96
97
|
nil
|
|
97
98
|
end
|
|
98
99
|
|
|
@@ -104,30 +105,28 @@ module Mysigner
|
|
|
104
105
|
# Get signing configs defined in the project
|
|
105
106
|
def signing_configs
|
|
106
107
|
configs = []
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
if @gradle_content =~ /signingConfigs\s*\{(.*?)\n\s{4}\}/m
|
|
109
|
-
block =
|
|
110
|
+
block = ::Regexp.last_match(1)
|
|
110
111
|
block.scan(/(\w+)\s*\{/) do |match|
|
|
111
112
|
configs << match[0]
|
|
112
113
|
end
|
|
113
114
|
end
|
|
114
|
-
|
|
115
|
+
|
|
115
116
|
configs
|
|
116
117
|
end
|
|
117
118
|
|
|
118
119
|
# Get keystore path from signing config
|
|
119
120
|
def keystore_path(config_name = 'release')
|
|
120
|
-
if @gradle_content =~ /#{config_name}\s*\{[^}]*storeFile\s*(?:=\s*)?(?:file\()?"?([^")\n]+)"?\)?/m
|
|
121
|
-
|
|
122
|
-
end
|
|
121
|
+
return ::Regexp.last_match(1) if @gradle_content =~ /#{config_name}\s*\{[^}]*storeFile\s*(?:=\s*)?(?:file\()?"?([^")\n]+)"?\)?/m
|
|
122
|
+
|
|
123
123
|
nil
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
# Get keystore alias from signing config
|
|
127
127
|
def keystore_alias(config_name = 'release')
|
|
128
|
-
if @gradle_content =~ /#{config_name}\s*\{[^}]*keyAlias\s*(?:=\s*)?["']?([^"'\n]+)["']?/m
|
|
129
|
-
|
|
130
|
-
end
|
|
128
|
+
return ::Regexp.last_match(1).strip if @gradle_content =~ /#{config_name}\s*\{[^}]*keyAlias\s*(?:=\s*)?["']?([^"'\n]+)["']?/m
|
|
129
|
+
|
|
131
130
|
nil
|
|
132
131
|
end
|
|
133
132
|
|
|
@@ -137,15 +136,11 @@ module Mysigner
|
|
|
137
136
|
strings_path = File.join(android_directory, 'app/src/main/res/values/strings.xml')
|
|
138
137
|
if File.exist?(strings_path)
|
|
139
138
|
content = File.read(strings_path)
|
|
140
|
-
if content =~
|
|
141
|
-
return $1
|
|
142
|
-
end
|
|
139
|
+
return ::Regexp.last_match(1) if content =~ %r{<string\s+name="app_name"[^>]*>([^<]+)</string>}
|
|
143
140
|
end
|
|
144
141
|
|
|
145
142
|
# Fallback to manifest label
|
|
146
|
-
if @manifest_content && @manifest_content =~ /android:label="([^"]+)"/
|
|
147
|
-
return $1
|
|
148
|
-
end
|
|
143
|
+
return ::Regexp.last_match(1) if @manifest_content && @manifest_content =~ /android:label="([^"]+)"/
|
|
149
144
|
|
|
150
145
|
# Fallback to directory name
|
|
151
146
|
File.basename(@project_info[:directory])
|
|
@@ -217,7 +212,7 @@ module Mysigner
|
|
|
217
212
|
|
|
218
213
|
def read_gradle_file
|
|
219
214
|
gradle_path = @project_info[:app_build_gradle]
|
|
220
|
-
|
|
215
|
+
|
|
221
216
|
unless gradle_path && File.exist?(gradle_path)
|
|
222
217
|
# Try to find it
|
|
223
218
|
android_dir = android_directory
|
|
@@ -228,12 +223,14 @@ module Mysigner
|
|
|
228
223
|
end
|
|
229
224
|
|
|
230
225
|
return '' unless File.exist?(gradle_path)
|
|
226
|
+
|
|
231
227
|
File.read(gradle_path)
|
|
232
228
|
end
|
|
233
229
|
|
|
234
230
|
def read_manifest_file
|
|
235
231
|
manifest_path = File.join(android_directory, 'app/src/main/AndroidManifest.xml')
|
|
236
232
|
return nil unless File.exist?(manifest_path)
|
|
233
|
+
|
|
237
234
|
File.read(manifest_path)
|
|
238
235
|
end
|
|
239
236
|
|
|
@@ -241,7 +238,7 @@ module Mysigner
|
|
|
241
238
|
# Handle both Groovy and Kotlin DSL syntax
|
|
242
239
|
# Groovy: applicationId "com.example.app" or applicationId = "com.example.app"
|
|
243
240
|
# Kotlin: applicationId = "com.example.app"
|
|
244
|
-
|
|
241
|
+
|
|
245
242
|
patterns = [
|
|
246
243
|
/#{property}\s*=?\s*["']([^"']+)["']/,
|
|
247
244
|
/#{property}\s+["']([^"']+)["']/,
|
|
@@ -250,9 +247,7 @@ module Mysigner
|
|
|
250
247
|
]
|
|
251
248
|
|
|
252
249
|
patterns.each do |pattern|
|
|
253
|
-
if @gradle_content =~ pattern
|
|
254
|
-
return $1
|
|
255
|
-
end
|
|
250
|
+
return ::Regexp.last_match(1) if @gradle_content =~ pattern
|
|
256
251
|
end
|
|
257
252
|
|
|
258
253
|
nil
|
|
@@ -260,11 +255,9 @@ module Mysigner
|
|
|
260
255
|
|
|
261
256
|
def extract_package_from_manifest
|
|
262
257
|
return nil unless @manifest_content
|
|
263
|
-
|
|
264
|
-
if @manifest_content =~ /package="([^"]+)"/
|
|
265
|
-
|
|
266
|
-
end
|
|
267
|
-
|
|
258
|
+
|
|
259
|
+
return ::Regexp.last_match(1) if @manifest_content =~ /package="([^"]+)"/
|
|
260
|
+
|
|
268
261
|
nil
|
|
269
262
|
end
|
|
270
263
|
|
|
@@ -272,19 +265,19 @@ module Mysigner
|
|
|
272
265
|
# Check for app.json in project root
|
|
273
266
|
project_dir = @project_info[:directory]
|
|
274
267
|
app_json_path = File.join(project_dir, 'app.json')
|
|
275
|
-
|
|
268
|
+
|
|
276
269
|
return nil unless File.exist?(app_json_path)
|
|
277
|
-
|
|
270
|
+
|
|
278
271
|
begin
|
|
279
272
|
require 'json'
|
|
280
273
|
config = JSON.parse(File.read(app_json_path))
|
|
281
|
-
|
|
274
|
+
|
|
282
275
|
# Expo config can be nested under 'expo' key or at root
|
|
283
276
|
expo_config = config['expo'] || config
|
|
284
|
-
|
|
277
|
+
|
|
285
278
|
# Get Android package name
|
|
286
279
|
expo_config.dig('android', 'package')
|
|
287
|
-
rescue
|
|
280
|
+
rescue StandardError
|
|
288
281
|
nil
|
|
289
282
|
end
|
|
290
283
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mysigner
|
|
2
4
|
module Build
|
|
3
5
|
class Configurator
|
|
@@ -15,7 +17,7 @@ module Mysigner
|
|
|
15
17
|
target = @parser.find_target(target_name)
|
|
16
18
|
bundle_id = @parser.bundle_id(target_name, configuration)
|
|
17
19
|
|
|
18
|
-
raise
|
|
20
|
+
raise 'Bundle ID not found in project' if bundle_id.to_s.empty?
|
|
19
21
|
|
|
20
22
|
# Map build type to profile type
|
|
21
23
|
profile_type = map_build_type_to_profile_type(build_type)
|
|
@@ -30,21 +32,21 @@ module Mysigner
|
|
|
30
32
|
# Set manual signing
|
|
31
33
|
config.build_settings['CODE_SIGN_STYLE'] = 'Manual'
|
|
32
34
|
config.build_settings['PROVISIONING_PROFILE_SPECIFIER'] = profile['name']
|
|
33
|
-
|
|
35
|
+
|
|
34
36
|
# Set code sign identity based on type
|
|
35
37
|
code_sign_identity = case build_type
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
when :development
|
|
39
|
+
'iPhone Developer'
|
|
40
|
+
else
|
|
41
|
+
'iPhone Distribution'
|
|
42
|
+
end
|
|
41
43
|
config.build_settings['CODE_SIGN_IDENTITY'] = code_sign_identity
|
|
42
44
|
|
|
43
45
|
# Ensure development team is set
|
|
44
46
|
team_id = @parser.team_id(target_name, configuration)
|
|
45
|
-
if team_id.to_s.empty?
|
|
47
|
+
if team_id.to_s.empty? && profile['team_id']
|
|
46
48
|
# Try to get from profile or use organization default
|
|
47
|
-
config.build_settings['DEVELOPMENT_TEAM'] = profile['team_id']
|
|
49
|
+
config.build_settings['DEVELOPMENT_TEAM'] = profile['team_id']
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
# Save project
|
|
@@ -93,9 +95,9 @@ module Mysigner
|
|
|
93
95
|
type: profile_type
|
|
94
96
|
}
|
|
95
97
|
)
|
|
96
|
-
|
|
98
|
+
|
|
97
99
|
return response[:profile] if response[:profile]
|
|
98
|
-
rescue Mysigner::NotFoundError
|
|
100
|
+
rescue Mysigner::NotFoundError
|
|
99
101
|
# Profile matching returned no match, fall through to manual search
|
|
100
102
|
end
|
|
101
103
|
|
|
@@ -110,11 +112,11 @@ module Mysigner
|
|
|
110
112
|
)
|
|
111
113
|
|
|
112
114
|
profiles = response[:profiles] || []
|
|
113
|
-
|
|
115
|
+
|
|
114
116
|
if profiles.empty?
|
|
115
|
-
raise ProfileNotFoundError,
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
raise ProfileNotFoundError,
|
|
118
|
+
"No active #{profile_type} profile found for bundle ID '#{bundle_id}'. " \
|
|
119
|
+
"Create one at the My Signer dashboard or run 'mysigner profiles'"
|
|
118
120
|
end
|
|
119
121
|
|
|
120
122
|
# Return the profile expiring furthest in the future
|
|
@@ -123,4 +125,3 @@ module Mysigner
|
|
|
123
125
|
end
|
|
124
126
|
end
|
|
125
127
|
end
|
|
126
|
-
|