mysigner 0.1.2 → 0.1.4
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/.gitignore +4 -0
- data/.rubocop.yml +55 -0
- data/.rubocop_todo.yml +126 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +5 -3
- data/Gemfile.lock +38 -8
- data/README.md +14 -16
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/bin/setup +3 -0
- data/certificate_.cer +0 -0
- data/exe/mysigner +19 -2
- data/iOS_App_Store_Profile.mobileprovision +1 -0
- data/iOS_Distribution_Certificate.cer +1 -0
- data/lib/mysigner/build/android_executor.rb +83 -63
- 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/cleanup/private_keys_purger.rb +41 -0
- data/lib/mysigner/cli/auth_commands.rb +771 -764
- data/lib/mysigner/cli/build_commands.rb +962 -796
- 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 +44 -1
- data/lib/mysigner/cli/diagnostic_commands.rb +667 -636
- data/lib/mysigner/cli/resource_commands.rb +1153 -985
- data/lib/mysigner/cli/validate_commands.rb +25 -25
- data/lib/mysigner/cli.rb +11 -1
- data/lib/mysigner/client.rb +27 -19
- data/lib/mysigner/config.rb +161 -60
- data/lib/mysigner/export/exporter.rb +38 -37
- data/lib/mysigner/signing/certificate_checker.rb +18 -23
- data/lib/mysigner/signing/gradle_signing_injector.rb +67 -0
- data/lib/mysigner/signing/keystore_manager.rb +81 -61
- data/lib/mysigner/signing/validator.rb +38 -40
- data/lib/mysigner/signing/wizard.rb +329 -342
- data/lib/mysigner/upload/app_store_automation.rb +96 -49
- data/lib/mysigner/upload/app_store_submission.rb +87 -92
- data/lib/mysigner/upload/asc_rest_uploader.rb +119 -0
- data/lib/mysigner/upload/play_store_uploader.rb +164 -144
- data/lib/mysigner/upload/uploader.rb +136 -115
- data/lib/mysigner/version.rb +3 -1
- data/lib/mysigner.rb +13 -11
- data/mysigner.gemspec +36 -33
- data/profile_.mobileprovision +0 -0
- data/test_manual.rb +37 -36
- metadata +44 -17
- data/.DS_Store +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mysigner
|
|
2
4
|
class CLI < Thor
|
|
3
5
|
module Concerns
|
|
@@ -6,141 +8,144 @@ module Mysigner
|
|
|
6
8
|
def show_token_guidance(api_url)
|
|
7
9
|
say "Don't have a token yet?", :yellow
|
|
8
10
|
say " 1. Go to: #{api_url}", :cyan
|
|
9
|
-
say
|
|
11
|
+
say ' 2. Navigate to: Your Organization → API Tokens', :cyan
|
|
10
12
|
say " 3. Click 'Create Token'", :cyan
|
|
11
13
|
say " 4. Copy the token (you'll only see it once!)", :cyan
|
|
12
|
-
say
|
|
14
|
+
say ''
|
|
13
15
|
say "💡 Or run 'mysigner onboard' for step-by-step guidance", :yellow
|
|
14
|
-
say
|
|
16
|
+
say ''
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
# Handle connection failure
|
|
18
20
|
def handle_connection_failure(api_url)
|
|
19
|
-
say
|
|
20
|
-
say
|
|
21
|
+
say ''
|
|
22
|
+
say 'Possible issues:', :yellow
|
|
21
23
|
say " • API server is not running at #{api_url}"
|
|
22
|
-
say
|
|
23
|
-
say
|
|
24
|
-
say
|
|
25
|
-
say
|
|
26
|
-
say
|
|
27
|
-
say
|
|
24
|
+
say ' • Network connectivity problems'
|
|
25
|
+
say ' • Incorrect API URL'
|
|
26
|
+
say ''
|
|
27
|
+
say '💡 Try:', :cyan
|
|
28
|
+
say ' • Check the API URL is correct'
|
|
29
|
+
say ' • Verify the server is running'
|
|
28
30
|
say " • Run 'mysigner onboard' for guided setup"
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
# Show guidance for creating an organization
|
|
32
34
|
def show_create_org_guidance(api_url)
|
|
33
|
-
say
|
|
35
|
+
say 'To create an organization:', :cyan
|
|
34
36
|
say " 1. Go to: #{api_url}"
|
|
35
|
-
say
|
|
37
|
+
say ' 2. Sign in to your account'
|
|
36
38
|
say " 3. Click 'Create Organization'"
|
|
37
|
-
say
|
|
38
|
-
say
|
|
39
|
+
say ' 4. Then generate a new API token for that organization'
|
|
40
|
+
say ''
|
|
39
41
|
say "💡 Run 'mysigner onboard' for step-by-step guidance", :yellow
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
# Handle unauthorized error
|
|
43
45
|
def handle_unauthorized_error(api_url)
|
|
44
|
-
say
|
|
45
|
-
say
|
|
46
|
-
say
|
|
47
|
-
say
|
|
48
|
-
say
|
|
49
|
-
say
|
|
50
|
-
say
|
|
51
|
-
say
|
|
52
|
-
say
|
|
53
|
-
say
|
|
54
|
-
say
|
|
46
|
+
say ''
|
|
47
|
+
say '=' * 80, :red
|
|
48
|
+
say '✗ Authentication Failed', :red
|
|
49
|
+
say '=' * 80, :red
|
|
50
|
+
say ''
|
|
51
|
+
say 'Your API token is invalid or has been revoked.', :bold
|
|
52
|
+
say ''
|
|
53
|
+
say 'Common reasons:', :yellow
|
|
54
|
+
say ' • Token was copied incorrectly (missing characters)'
|
|
55
|
+
say ' • Token was revoked in the web dashboard'
|
|
56
|
+
say ' • Token has expired'
|
|
55
57
|
say " • You're using the wrong API URL"
|
|
56
|
-
say
|
|
57
|
-
say
|
|
58
|
+
say ''
|
|
59
|
+
say 'To fix this:', :cyan
|
|
58
60
|
say " 1. Go to: #{api_url}/organizations/YOUR_ORG/api_tokens"
|
|
59
|
-
say
|
|
60
|
-
say
|
|
61
|
-
say
|
|
61
|
+
say ' 2. Check if your token is still active'
|
|
62
|
+
say ' 3. If revoked or expired, create a new token'
|
|
63
|
+
say ' 4. Copy the NEW token carefully (entire string)'
|
|
62
64
|
say " 5. Run 'mysigner login' again"
|
|
63
|
-
say
|
|
65
|
+
say ''
|
|
64
66
|
say "💡 Or run 'mysigner onboard' for guided setup", :yellow
|
|
65
|
-
say
|
|
67
|
+
say ''
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# Handle connection error
|
|
69
71
|
def handle_connection_error(error, api_url)
|
|
70
|
-
say
|
|
71
|
-
say
|
|
72
|
-
say
|
|
73
|
-
say
|
|
74
|
-
say
|
|
72
|
+
say ''
|
|
73
|
+
say '=' * 80, :red
|
|
74
|
+
say '✗ Connection Failed', :red
|
|
75
|
+
say '=' * 80, :red
|
|
76
|
+
say ''
|
|
75
77
|
say "Error: #{error.message}", :red
|
|
76
|
-
say
|
|
77
|
-
say
|
|
78
|
+
say ''
|
|
79
|
+
say 'Possible causes:', :yellow
|
|
78
80
|
say " • My Signer API is not running at #{api_url}"
|
|
79
|
-
say
|
|
80
|
-
say
|
|
81
|
-
say
|
|
82
|
-
say
|
|
83
|
-
say
|
|
84
|
-
say
|
|
81
|
+
say ' • Network connectivity issues'
|
|
82
|
+
say ' • Firewall blocking the connection'
|
|
83
|
+
say ' • Incorrect API URL'
|
|
84
|
+
say ''
|
|
85
|
+
say 'To fix this:', :cyan
|
|
86
|
+
say ''
|
|
85
87
|
if api_url.include?('localhost')
|
|
86
|
-
say
|
|
87
|
-
say
|
|
88
|
-
say
|
|
89
|
-
say
|
|
90
|
-
say
|
|
88
|
+
say ' For local development:', :bold
|
|
89
|
+
say ' 1. Make sure Rails server is running:'
|
|
90
|
+
say ' cd path/to/my-signer'
|
|
91
|
+
say ' bin/rails server'
|
|
92
|
+
say ''
|
|
91
93
|
say " 2. Verify it's accessible:"
|
|
92
94
|
say " curl #{api_url}/up"
|
|
93
|
-
say ""
|
|
94
95
|
else
|
|
95
|
-
say
|
|
96
|
-
say
|
|
97
|
-
say
|
|
98
|
-
say
|
|
99
|
-
say ""
|
|
96
|
+
say ' For production:', :bold
|
|
97
|
+
say ' 1. Check the API URL is correct'
|
|
98
|
+
say ' 2. Verify the service is running'
|
|
99
|
+
say ' 3. Check your internet connection'
|
|
100
100
|
end
|
|
101
|
-
say
|
|
102
|
-
say
|
|
103
|
-
say
|
|
101
|
+
say ''
|
|
102
|
+
say ' Or set a custom API URL:', :bold
|
|
103
|
+
say ' export MYSIGNER_API_URL=http://your-server.com'
|
|
104
|
+
say ''
|
|
104
105
|
say "💡 Run 'mysigner onboard' to reconfigure", :yellow
|
|
105
|
-
say
|
|
106
|
+
say ''
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
# Handle unexpected error
|
|
109
110
|
def handle_unexpected_error(error, api_url)
|
|
110
|
-
say
|
|
111
|
-
say
|
|
112
|
-
say
|
|
113
|
-
say
|
|
114
|
-
say
|
|
111
|
+
say ''
|
|
112
|
+
say '=' * 80, :red
|
|
113
|
+
say '✗ Unexpected Error', :red
|
|
114
|
+
say '=' * 80, :red
|
|
115
|
+
say ''
|
|
115
116
|
say "Error: #{error.message}", :red
|
|
116
117
|
say "Type: #{error.class}", :red if ENV['DEBUG']
|
|
117
|
-
say
|
|
118
|
-
say
|
|
118
|
+
say ''
|
|
119
|
+
say 'This is unexpected. Please try:', :yellow
|
|
119
120
|
say " 1. Run 'mysigner onboard' to reconfigure"
|
|
120
121
|
say " 2. Check #{api_url} is accessible"
|
|
121
122
|
say " 3. Run 'mysigner doctor' to check your environment"
|
|
122
|
-
say
|
|
123
|
+
say ''
|
|
123
124
|
if ENV['DEBUG']
|
|
124
|
-
say
|
|
125
|
+
say 'Stack trace:', :red
|
|
125
126
|
say error.backtrace.first(5).join("\n"), :red
|
|
126
|
-
say ""
|
|
127
127
|
else
|
|
128
|
-
say
|
|
129
|
-
say ""
|
|
128
|
+
say '💡 For more details, run with DEBUG=1', :yellow
|
|
130
129
|
end
|
|
130
|
+
say ''
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
# Handle Apple API errors with actionable suggestions
|
|
134
134
|
def handle_apple_api_error(error, context: {})
|
|
135
135
|
error_message = error.message.to_s
|
|
136
136
|
|
|
137
|
-
say
|
|
138
|
-
say
|
|
137
|
+
say ''
|
|
138
|
+
say '=' * 80, :red
|
|
139
139
|
say "✗ #{context[:title] || 'Apple API Error'}", :red
|
|
140
|
-
say
|
|
141
|
-
say
|
|
140
|
+
say '=' * 80, :red
|
|
141
|
+
say ''
|
|
142
142
|
say "Error: #{error_message}", :red
|
|
143
|
-
say
|
|
143
|
+
say ''
|
|
144
|
+
|
|
145
|
+
if error.respond_to?(:suggestion) && error.suggestion
|
|
146
|
+
say "Suggestion: #{error.suggestion}", :yellow
|
|
147
|
+
say ''
|
|
148
|
+
end
|
|
144
149
|
|
|
145
150
|
# Check for specific Apple error patterns
|
|
146
151
|
if error_message =~ /no.*build.*found|build.*not.*found|no.*processed.*build/i
|
|
@@ -161,6 +166,8 @@ module Mysigner
|
|
|
161
166
|
show_archive_not_found_suggestions
|
|
162
167
|
elsif error_message =~ /ipa.*not.*found|no.*ipa.*file/i
|
|
163
168
|
show_ipa_not_found_suggestions
|
|
169
|
+
elsif show_actionable_suggestions(error, platform: :ios)
|
|
170
|
+
# Suggestions already shown
|
|
164
171
|
else
|
|
165
172
|
show_generic_apple_suggestions
|
|
166
173
|
end
|
|
@@ -173,13 +180,18 @@ module Mysigner
|
|
|
173
180
|
def handle_android_api_error(error, context: {})
|
|
174
181
|
error_message = error.message.to_s
|
|
175
182
|
|
|
176
|
-
say
|
|
177
|
-
say
|
|
183
|
+
say ''
|
|
184
|
+
say '=' * 80, :red
|
|
178
185
|
say "✗ #{context[:title] || 'Google Play API Error'}", :red
|
|
179
|
-
say
|
|
180
|
-
say
|
|
186
|
+
say '=' * 80, :red
|
|
187
|
+
say ''
|
|
181
188
|
say "Error: #{error_message}", :red
|
|
182
|
-
say
|
|
189
|
+
say ''
|
|
190
|
+
|
|
191
|
+
if error.respond_to?(:suggestion) && error.suggestion
|
|
192
|
+
say "Suggestion: #{error.suggestion}", :yellow
|
|
193
|
+
say ''
|
|
194
|
+
end
|
|
183
195
|
|
|
184
196
|
# Check for specific Google Play error patterns
|
|
185
197
|
if error_message =~ /keystore.*not.*found|no.*keystore|missing.*keystore/i
|
|
@@ -198,6 +210,8 @@ module Mysigner
|
|
|
198
210
|
show_track_not_setup_suggestions(context[:track])
|
|
199
211
|
elsif error_message =~ /aab.*not.*found|no.*aab.*file/i
|
|
200
212
|
show_aab_not_found_suggestions
|
|
213
|
+
elsif show_actionable_suggestions(error, platform: :android)
|
|
214
|
+
# Suggestions already shown
|
|
201
215
|
else
|
|
202
216
|
show_generic_android_suggestions
|
|
203
217
|
end
|
|
@@ -209,236 +223,232 @@ module Mysigner
|
|
|
209
223
|
private
|
|
210
224
|
|
|
211
225
|
# iOS-specific suggestion helpers
|
|
212
|
-
def show_build_not_found_suggestions(
|
|
213
|
-
say
|
|
214
|
-
say
|
|
215
|
-
say
|
|
216
|
-
say
|
|
217
|
-
say
|
|
218
|
-
say
|
|
219
|
-
say
|
|
226
|
+
def show_build_not_found_suggestions(_context)
|
|
227
|
+
say '💡 Build Not Found: How to fix', :cyan
|
|
228
|
+
say ''
|
|
229
|
+
say ' → Upload a build first: mysigner ship testflight', :yellow
|
|
230
|
+
say ' → If already uploaded, wait 5-15 minutes for Apple to process', :yellow
|
|
231
|
+
say ' → Use --wait flag to poll: mysigner ship appstore --wait', :yellow
|
|
232
|
+
say ' → Sync your builds: mysigner sync ios', :yellow
|
|
233
|
+
say ''
|
|
220
234
|
end
|
|
221
235
|
|
|
222
236
|
def show_build_processing_suggestions
|
|
223
|
-
say
|
|
224
|
-
say
|
|
225
|
-
say
|
|
226
|
-
say
|
|
227
|
-
say
|
|
228
|
-
say
|
|
229
|
-
say
|
|
237
|
+
say '💡 Build Still Processing: How to fix', :cyan
|
|
238
|
+
say ''
|
|
239
|
+
say ' → Apple typically takes 5-15 minutes to process builds', :yellow
|
|
240
|
+
say ' → Use --wait flag: mysigner ship appstore --wait', :yellow
|
|
241
|
+
say ' → Increase timeout: --asc-timeout-seconds 1800', :yellow
|
|
242
|
+
say ' → Check App Store Connect for processing status', :yellow
|
|
243
|
+
say ''
|
|
230
244
|
end
|
|
231
245
|
|
|
232
246
|
def show_expired_credential_suggestions
|
|
233
|
-
say
|
|
234
|
-
say
|
|
235
|
-
say
|
|
236
|
-
say
|
|
237
|
-
say
|
|
238
|
-
say
|
|
239
|
-
say
|
|
247
|
+
say '💡 Expired Profile or Certificate: How to fix', :cyan
|
|
248
|
+
say ''
|
|
249
|
+
say ' → List profiles with expiration dates: mysigner profiles', :yellow
|
|
250
|
+
say ' → Check status in My Signer dashboard', :yellow
|
|
251
|
+
say ' → Regenerate in Apple Developer Portal', :yellow
|
|
252
|
+
say ' → Download fresh profile: mysigner profile download <ID>', :yellow
|
|
253
|
+
say ''
|
|
240
254
|
end
|
|
241
255
|
|
|
242
256
|
def show_profile_not_found_suggestions
|
|
243
|
-
say
|
|
244
|
-
say
|
|
245
|
-
say
|
|
246
|
-
say
|
|
247
|
-
say
|
|
248
|
-
say
|
|
249
|
-
say
|
|
257
|
+
say '💡 Provisioning Profile Not Found: How to fix', :cyan
|
|
258
|
+
say ''
|
|
259
|
+
say ' → List available profiles: mysigner profiles', :yellow
|
|
260
|
+
say ' → Sync from Apple: mysigner sync ios', :yellow
|
|
261
|
+
say ' → Create profile in Apple Developer Portal', :yellow
|
|
262
|
+
say ' → Check if profile matches your Bundle ID', :yellow
|
|
263
|
+
say ''
|
|
250
264
|
end
|
|
251
265
|
|
|
252
266
|
def show_certificate_not_found_suggestions
|
|
253
|
-
say
|
|
254
|
-
say
|
|
255
|
-
say
|
|
256
|
-
say
|
|
257
|
-
say
|
|
258
|
-
say
|
|
259
|
-
say
|
|
267
|
+
say '💡 Signing Certificate Not Found: How to fix', :cyan
|
|
268
|
+
say ''
|
|
269
|
+
say ' → List certificates: mysigner certificates', :yellow
|
|
270
|
+
say ' → Download and install: mysigner certificate download <ID>', :yellow
|
|
271
|
+
say ' → Check Keychain Access for installed certificates', :yellow
|
|
272
|
+
say ' → Run: mysigner doctor (diagnose signing issues)', :yellow
|
|
273
|
+
say ''
|
|
260
274
|
end
|
|
261
275
|
|
|
262
276
|
def show_app_not_found_suggestions(bundle_id = nil)
|
|
263
|
-
say
|
|
264
|
-
say
|
|
265
|
-
say
|
|
266
|
-
say
|
|
267
|
-
say
|
|
268
|
-
say
|
|
269
|
-
say
|
|
277
|
+
say '💡 App Not Found: How to fix', :cyan
|
|
278
|
+
say ''
|
|
279
|
+
say ' → Ensure app exists in App Store Connect', :yellow
|
|
280
|
+
say ' → Create app in App Store Connect first', :yellow
|
|
281
|
+
say ' → Verify Bundle ID matches your Xcode project', :yellow if bundle_id
|
|
282
|
+
say ' → Sync from App Store Connect: mysigner sync ios', :yellow
|
|
283
|
+
say ''
|
|
270
284
|
end
|
|
271
285
|
|
|
272
286
|
def show_missing_metadata_suggestions
|
|
273
|
-
say
|
|
274
|
-
say
|
|
275
|
-
say
|
|
287
|
+
say '💡 Missing App Store Metadata: How to fix', :cyan
|
|
288
|
+
say ''
|
|
289
|
+
say ' → Configure release in My Signer dashboard', :yellow
|
|
276
290
|
say " → Provide What's New via CLI: --whats-new \"Your text\"", :yellow
|
|
277
|
-
say
|
|
278
|
-
say
|
|
279
|
-
say
|
|
291
|
+
say ' → Ensure support URL is set in App Store Connect', :yellow
|
|
292
|
+
say ' → Complete app information in App Store Connect', :yellow
|
|
293
|
+
say ''
|
|
280
294
|
end
|
|
281
295
|
|
|
282
296
|
def show_archive_not_found_suggestions
|
|
283
|
-
say
|
|
284
|
-
say
|
|
285
|
-
say
|
|
286
|
-
say
|
|
287
|
-
say
|
|
288
|
-
say
|
|
297
|
+
say '💡 Archive Not Found: How to fix', :cyan
|
|
298
|
+
say ''
|
|
299
|
+
say ' → Build first: mysigner build', :yellow
|
|
300
|
+
say ' → Or use: mysigner ship testflight (handles build)', :yellow
|
|
301
|
+
say ' → Check if Xcode build succeeded', :yellow
|
|
302
|
+
say ''
|
|
289
303
|
end
|
|
290
304
|
|
|
291
305
|
def show_ipa_not_found_suggestions
|
|
292
|
-
say
|
|
293
|
-
say
|
|
294
|
-
say
|
|
295
|
-
say
|
|
296
|
-
say
|
|
297
|
-
say
|
|
306
|
+
say '💡 IPA File Not Found: How to fix', :cyan
|
|
307
|
+
say ''
|
|
308
|
+
say ' → Export IPA: mysigner export <archive_path>', :yellow
|
|
309
|
+
say ' → Or use: mysigner ship testflight (handles export)', :yellow
|
|
310
|
+
say ' → Check export method matches profile type', :yellow
|
|
311
|
+
say ''
|
|
298
312
|
end
|
|
299
313
|
|
|
300
314
|
def show_generic_apple_suggestions
|
|
301
|
-
say
|
|
302
|
-
say
|
|
315
|
+
say '💡 General troubleshooting:', :cyan
|
|
316
|
+
say ''
|
|
303
317
|
say " → Run 'mysigner doctor' to check your setup", :yellow
|
|
304
|
-
say
|
|
305
|
-
say
|
|
306
|
-
say
|
|
318
|
+
say ' → Sync from Apple: mysigner sync ios', :yellow
|
|
319
|
+
say ' → Check App Store Connect: https://appstoreconnect.apple.com', :yellow
|
|
320
|
+
say ''
|
|
307
321
|
end
|
|
308
322
|
|
|
309
323
|
# Android-specific suggestion helpers
|
|
310
324
|
def show_keystore_not_found_suggestions
|
|
311
|
-
say
|
|
312
|
-
say
|
|
313
|
-
say
|
|
314
|
-
say
|
|
315
|
-
say
|
|
316
|
-
say
|
|
317
|
-
say
|
|
325
|
+
say '💡 Keystore Not Found: How to fix', :cyan
|
|
326
|
+
say ''
|
|
327
|
+
say ' → Upload keystore: mysigner keystore upload <path>', :yellow
|
|
328
|
+
say ' → List keystores: mysigner keystore list', :yellow
|
|
329
|
+
say ' → Download keystore: mysigner keystore download <ID>', :yellow
|
|
330
|
+
say ' → Check keystore path in build.gradle', :yellow
|
|
331
|
+
say ''
|
|
318
332
|
end
|
|
319
333
|
|
|
320
334
|
def show_keystore_password_suggestions
|
|
321
|
-
say
|
|
322
|
-
say
|
|
323
|
-
say
|
|
324
|
-
say
|
|
325
|
-
say
|
|
326
|
-
say
|
|
335
|
+
say '💡 Keystore Password Issue: How to fix', :cyan
|
|
336
|
+
say ''
|
|
337
|
+
say ' → Verify keystore password is correct', :yellow
|
|
338
|
+
say ' → Check password in My Signer dashboard', :yellow
|
|
339
|
+
say ' → Update password: mysigner keystore update <ID>', :yellow
|
|
340
|
+
say ''
|
|
327
341
|
end
|
|
328
342
|
|
|
329
|
-
def show_first_upload_suggestions(
|
|
330
|
-
say
|
|
331
|
-
say
|
|
332
|
-
say
|
|
333
|
-
say
|
|
334
|
-
say
|
|
335
|
-
say
|
|
343
|
+
def show_first_upload_suggestions(_package_name = nil)
|
|
344
|
+
say '💡 First Upload Required: How to fix', :cyan
|
|
345
|
+
say ''
|
|
346
|
+
say ' Google Play requires the FIRST build to be uploaded manually:', :yellow
|
|
347
|
+
say ''
|
|
348
|
+
say ' 1. Build AAB: mysigner android build', :yellow
|
|
349
|
+
say ' 2. Go to Play Console → Your App → Internal testing', :yellow
|
|
336
350
|
say " 3. Click 'Create release' and upload the AAB", :yellow
|
|
337
|
-
say
|
|
338
|
-
say
|
|
351
|
+
say ' 4. Save the release (no need to roll out)', :yellow
|
|
352
|
+
say ''
|
|
339
353
|
say " After that, 'mysigner ship' will work for future uploads.", :green
|
|
340
|
-
say
|
|
354
|
+
say ''
|
|
341
355
|
end
|
|
342
356
|
|
|
343
357
|
def show_version_code_conflict_suggestions
|
|
344
|
-
say
|
|
345
|
-
say
|
|
346
|
-
say
|
|
347
|
-
say
|
|
348
|
-
say
|
|
349
|
-
say
|
|
358
|
+
say '💡 Version Code Conflict: How to fix', :cyan
|
|
359
|
+
say ''
|
|
360
|
+
say ' → Version code already exists on Google Play', :yellow
|
|
361
|
+
say ' → Run the command again - mysigner auto-increments', :yellow
|
|
362
|
+
say ' → Or manually increment versionCode in build.gradle', :yellow
|
|
363
|
+
say ''
|
|
350
364
|
end
|
|
351
365
|
|
|
352
366
|
def show_service_account_missing_suggestions
|
|
353
|
-
say
|
|
354
|
-
say
|
|
355
|
-
say
|
|
356
|
-
say
|
|
357
|
-
say
|
|
358
|
-
say
|
|
359
|
-
say
|
|
360
|
-
say
|
|
361
|
-
say
|
|
367
|
+
say '💡 Service Account Not Found: How to fix', :cyan
|
|
368
|
+
say ''
|
|
369
|
+
say ' Set up Google Play credentials in My Signer dashboard:', :yellow
|
|
370
|
+
say ''
|
|
371
|
+
say ' 1. Go to Play Console → API access → Service accounts', :yellow
|
|
372
|
+
say ' 2. Create a service account with Editor access', :yellow
|
|
373
|
+
say ' 3. Download the JSON key', :yellow
|
|
374
|
+
say ' 4. Upload to My Signer dashboard → Google Play Settings', :yellow
|
|
375
|
+
say ''
|
|
362
376
|
end
|
|
363
377
|
|
|
364
378
|
def show_permission_denied_suggestions
|
|
365
|
-
say
|
|
366
|
-
say
|
|
367
|
-
say
|
|
368
|
-
say
|
|
369
|
-
say
|
|
379
|
+
say '💡 Service Account Permission Denied: How to fix', :cyan
|
|
380
|
+
say ''
|
|
381
|
+
say ' In Play Console → API access:', :yellow
|
|
382
|
+
say ''
|
|
383
|
+
say ' 1. Find your service account', :yellow
|
|
370
384
|
say " 2. Click 'Manage Play Console permissions'", :yellow
|
|
371
385
|
say " 3. Grant 'Admin' or 'Release manager' access", :yellow
|
|
372
|
-
say
|
|
373
|
-
say
|
|
374
|
-
say
|
|
386
|
+
say ''
|
|
387
|
+
say ' Note: Permission changes take ~15 minutes to propagate', :green
|
|
388
|
+
say ''
|
|
375
389
|
end
|
|
376
390
|
|
|
377
391
|
def show_track_not_setup_suggestions(track = nil)
|
|
378
|
-
|
|
379
|
-
say
|
|
380
|
-
say
|
|
381
|
-
say
|
|
382
|
-
say
|
|
383
|
-
say
|
|
384
|
-
say
|
|
385
|
-
say
|
|
386
|
-
say
|
|
387
|
-
say
|
|
388
|
-
say
|
|
389
|
-
say
|
|
390
|
-
say
|
|
391
|
-
say
|
|
392
|
-
say
|
|
393
|
-
say
|
|
394
|
-
say
|
|
392
|
+
track || 'this track'
|
|
393
|
+
say '💡 Track Not Set Up in Play Console: How to fix', :cyan
|
|
394
|
+
say ''
|
|
395
|
+
say ' Complete track setup in Google Play Console:', :yellow
|
|
396
|
+
say ''
|
|
397
|
+
say ' For PRODUCTION:', :yellow
|
|
398
|
+
say ' • Complete store listing, content rating, pricing', :yellow
|
|
399
|
+
say ''
|
|
400
|
+
say ' For BETA/ALPHA:', :yellow
|
|
401
|
+
say ' • Create testing track and add testers', :yellow
|
|
402
|
+
say ''
|
|
403
|
+
say ' For INTERNAL:', :yellow
|
|
404
|
+
say ' • Add internal testers', :yellow
|
|
405
|
+
say ''
|
|
406
|
+
say ' ✓ Your AAB was uploaded successfully!', :green
|
|
407
|
+
say ' → Go to Play Console to finish track setup', :green
|
|
408
|
+
say ''
|
|
395
409
|
end
|
|
396
410
|
|
|
397
411
|
def show_aab_not_found_suggestions
|
|
398
|
-
say
|
|
399
|
-
say
|
|
400
|
-
say
|
|
401
|
-
say
|
|
402
|
-
say
|
|
403
|
-
say
|
|
412
|
+
say '💡 AAB File Not Found: How to fix', :cyan
|
|
413
|
+
say ''
|
|
414
|
+
say ' → Build your app first: mysigner android build', :yellow
|
|
415
|
+
say ' → Or use: mysigner ship internal (handles build)', :yellow
|
|
416
|
+
say ' → Check if Gradle build succeeded', :yellow
|
|
417
|
+
say ''
|
|
404
418
|
end
|
|
405
419
|
|
|
406
420
|
def show_generic_android_suggestions
|
|
407
|
-
say
|
|
408
|
-
say
|
|
421
|
+
say '💡 General troubleshooting:', :cyan
|
|
422
|
+
say ''
|
|
409
423
|
say " → Run 'mysigner doctor' to check your setup", :yellow
|
|
410
|
-
say
|
|
411
|
-
say
|
|
412
|
-
say
|
|
424
|
+
say ' → List keystores: mysigner keystore list', :yellow
|
|
425
|
+
say ' → Check Play Console: https://play.google.com/console', :yellow
|
|
426
|
+
say ''
|
|
413
427
|
end
|
|
414
428
|
|
|
415
429
|
# Helper to show saved file paths
|
|
416
430
|
def show_saved_files(context)
|
|
417
|
-
if context[:archive_path] && File.exist?(context[:archive_path])
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
end
|
|
423
|
-
if context[:aab_path] && File.exist?(context[:aab_path])
|
|
424
|
-
say "📦 AAB saved at: #{context[:aab_path]}", :yellow
|
|
425
|
-
end
|
|
431
|
+
say "📦 Archive saved at: #{context[:archive_path]}", :yellow if context[:archive_path] && File.exist?(context[:archive_path])
|
|
432
|
+
say "📦 IPA saved at: #{context[:ipa_path]}", :yellow if context[:ipa_path] && File.exist?(context[:ipa_path])
|
|
433
|
+
return unless context[:aab_path] && File.exist?(context[:aab_path])
|
|
434
|
+
|
|
435
|
+
say "📦 AAB saved at: #{context[:aab_path]}", :yellow
|
|
426
436
|
end
|
|
427
437
|
|
|
428
438
|
# Helper to show debug info
|
|
429
439
|
def show_debug_info(error)
|
|
430
|
-
say
|
|
440
|
+
say ''
|
|
431
441
|
if ENV['DEBUG']
|
|
432
|
-
say
|
|
442
|
+
say 'Debug info:', :yellow
|
|
433
443
|
say " Error class: #{error.class}", :yellow
|
|
434
|
-
say
|
|
444
|
+
say ' Backtrace:', :yellow
|
|
435
445
|
error.backtrace&.first(5)&.each do |line|
|
|
436
446
|
say " #{line}", :yellow
|
|
437
447
|
end
|
|
438
448
|
else
|
|
439
|
-
say
|
|
449
|
+
say '💡 For more details, run with DEBUG=1', :yellow
|
|
440
450
|
end
|
|
441
|
-
say
|
|
451
|
+
say ''
|
|
442
452
|
end
|
|
443
453
|
end
|
|
444
454
|
end
|