mysigner 0.3.4 → 0.3.7

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/CHANGELOG.md +47 -0
  4. data/Gemfile +0 -1
  5. data/Gemfile.lock +2 -6
  6. data/README.md +16 -16
  7. data/lib/mysigner/build/android_executor.rb +16 -21
  8. data/lib/mysigner/build/detector.rb +3 -1
  9. data/lib/mysigner/build/executor.rb +6 -1
  10. data/lib/mysigner/cli/auth_commands.rb +14 -3
  11. data/lib/mysigner/cli/build_commands.rb +14 -11
  12. data/lib/mysigner/cli/concerns/actionable_suggestions.rb +1 -2
  13. data/lib/mysigner/cli/concerns/api_helpers.rb +16 -3
  14. data/lib/mysigner/cli/concerns/error_handlers.rb +0 -1
  15. data/lib/mysigner/cli/concerns/helpers.rb +14 -14
  16. data/lib/mysigner/cli/diagnostic_commands.rb +16 -5
  17. data/lib/mysigner/cli/resource_commands.rb +8 -1
  18. data/lib/mysigner/client.rb +52 -0
  19. data/lib/mysigner/config.rb +9 -4
  20. data/lib/mysigner/export/exporter.rb +6 -1
  21. data/lib/mysigner/formatting.rb +23 -0
  22. data/lib/mysigner/signing/certificate_checker.rb +6 -6
  23. data/lib/mysigner/signing/keystore_manager.rb +2 -0
  24. data/lib/mysigner/signing/wizard.rb +2 -0
  25. data/lib/mysigner/upload/app_store_automation.rb +13 -1
  26. data/lib/mysigner/upload/app_store_submission.rb +2 -14
  27. data/lib/mysigner/upload/asc_rest_uploader.rb +44 -3
  28. data/lib/mysigner/upload/asc_submitter.rb +5 -0
  29. data/lib/mysigner/upload/play_store_uploader.rb +2 -7
  30. data/lib/mysigner/upload/uploader.rb +9 -366
  31. data/lib/mysigner/version.rb +1 -1
  32. data/lib/mysigner.rb +1 -0
  33. data/mysigner.gemspec +6 -2
  34. metadata +2 -20
  35. data/.travis.yml +0 -7
  36. data/MANUAL_TEST.md +0 -341
  37. data/bin/console +0 -15
  38. data/bin/setup +0 -11
  39. data/test_manual.rb +0 -103
data/MANUAL_TEST.md DELETED
@@ -1,341 +0,0 @@
1
- # Manual Testing Guide
2
-
3
- ## Prerequisites
4
-
5
- 1. Ruby 3.4.5 installed via rbenv
6
- 2. Bundle install completed (`bundle install`)
7
- 3. My Signer API running at `http://localhost:3000` (for Client tests)
8
- 4. Valid API token (get from My Signer dashboard)
9
-
10
- ## Running Automated Tests
11
-
12
- ```bash
13
- # Run all tests
14
- bundle exec rspec
15
-
16
- # Run specific tests
17
- bundle exec rspec spec/config_spec.rb # Config tests (18 examples)
18
- bundle exec rspec spec/client_spec.rb # Client tests (15 examples)
19
-
20
- # With documentation format
21
- bundle exec rspec --format documentation
22
- ```
23
-
24
- ## Test 1: Config Management
25
-
26
- ```bash
27
- # In the my-signer-cli directory
28
- bundle exec irb
29
- ```
30
-
31
- ```ruby
32
- require_relative 'lib/mysigner'
33
-
34
- # Create config
35
- config = Mysigner::Config.new
36
-
37
- # Set values
38
- config.api_url = "http://localhost:3000"
39
- config.current_organization_id = 1
40
- config.save_token_for_org(1, 'My Organization', 'your_token_here')
41
-
42
- # Save config (creates ~/.mysigner/config.yml)
43
- config.save
44
-
45
- # Display config (token is masked)
46
- config.display
47
- # => {:api_url=>"http://localhost:3000", :current_organization=>"My Organization (ID: 1)", :current_token=>"your...here"}
48
-
49
- # Check if valid
50
- config.valid?
51
- # => true
52
-
53
- # Load config in new instance
54
- new_config = Mysigner::Config.new
55
- new_config.api_url
56
- # => "http://localhost:3000"
57
-
58
- # Clear config
59
- config.clear
60
- ```
61
-
62
- ## Test 2: API Client
63
-
64
- **⚠️ Requires My Signer API running on http://localhost:3000**
65
-
66
- ```bash
67
- bundle exec irb
68
- ```
69
-
70
- ```ruby
71
- require_relative 'lib/mysigner'
72
-
73
- # Create client
74
- client = Mysigner::Client.new(
75
- api_url: 'http://localhost:3000',
76
- api_token: 'your_actual_token' # Get from My Signer dashboard
77
- )
78
-
79
- # Test connection
80
- response = client.test_connection
81
- puts response[:data]
82
- # => {"status"=>"ok", "message"=>"My Signer API v1"}
83
-
84
- # List organizations
85
- response = client.get('/api/v1/organizations')
86
- orgs = response[:data]['organizations']
87
- puts orgs.first
88
- # => {"id"=>1, "name"=>"My Org", ...}
89
-
90
- # List devices for organization #1
91
- response = client.get('/api/v1/organizations/1/devices')
92
- devices = response[:data]['devices']
93
- puts "Found #{devices.count} devices"
94
-
95
- # Register a new device
96
- response = client.post('/api/v1/organizations/1/devices', body: {
97
- name: 'Test iPhone',
98
- udid: '00008030-001A1B2C3D4E567F',
99
- platform: 'IOS'
100
- })
101
- puts response[:data]
102
- # => {"message"=>"Device registered successfully", "device"=>{...}}
103
-
104
- # Error handling
105
- begin
106
- client.get('/api/v1/organizations/999') # Non-existent org
107
- rescue Mysigner::NotFoundError => e
108
- puts "Caught error: #{e.message}"
109
- end
110
- # => "Caught error: Not found: Organization not found"
111
- ```
112
-
113
- ## Test Results ✅
114
-
115
- **All tests passing:**
116
- - ✅ Total: 87 examples, 0 failures (16 pending)
117
- - ✅ Ship tests: 34 examples, 0 failures
118
- - ✅ Config: 18 examples, 0 failures
119
- - ✅ Client: 15 examples, 0 failures
120
-
121
- Note: 16 tests are pending because they require specific test project setups (tvOS, watchOS, macOS platforms, etc.)
122
-
123
- ## What's Working
124
-
125
- ### Config Class (`lib/mysigner/config.rb`)
126
- - ✅ Save/load YAML configuration
127
- - ✅ Store API credentials securely (600 permissions)
128
- - ✅ Validate required fields
129
- - ✅ Mask sensitive tokens in display
130
- - ✅ Clear configuration
131
-
132
- ### Client Class (`lib/mysigner/client.rb`)
133
- - ✅ GET/POST/PATCH/DELETE HTTP methods
134
- - ✅ Bearer token authentication
135
- - ✅ Automatic JSON encoding/decoding
136
- - ✅ Retry with exponential backoff (3 attempts)
137
- - ✅ Custom error classes:
138
- - `UnauthorizedError` (401)
139
- - `ForbiddenError` (403)
140
- - `NotFoundError` (404)
141
- - `ValidationError` (422) - with details
142
- - `RateLimitError` (429) - with retry_after
143
- - `ServerError` (500+)
144
- - `ConnectionError` - network issues
145
- - `TimeoutError` - request timeouts
146
-
147
- ## iOS Ship/Submit Commands
148
-
149
- ### Ship Targets
150
-
151
- | Command | What it does |
152
- |---------|--------------|
153
- | `mysigner ship testflight` | Full workflow: Build → Export → Upload to TestFlight |
154
- | `mysigner ship appstore` | Full workflow: Build → Export → Upload → Wait for processing → Submit for App Store review |
155
-
156
- ### Testing iOS Ship Commands
157
-
158
- **Prerequisites:**
159
- 1. Logged in with `mysigner login`
160
- 2. App Store Connect credentials configured in dashboard
161
- 3. Navigate to an iOS project directory
162
-
163
- ```bash
164
- # Navigate to iOS project
165
- cd ~/path/to/your/ios-project
166
-
167
- # Check project is detected
168
- mysigner doctor
169
-
170
- # Ship to TestFlight (beta testing)
171
- mysigner ship testflight
172
-
173
- # Ship to App Store (production)
174
- mysigner ship appstore
175
-
176
- # Ship with options
177
- mysigner ship testflight --team YOUR_TEAM_ID # Override team
178
- mysigner ship testflight --bundle-id com.app.id # Override bundle ID
179
- mysigner ship testflight --scheme MyScheme # Specify scheme
180
- mysigner ship appstore --wait # Wait for processing
181
-
182
- # Advanced: Release type options (App Store only)
183
- mysigner ship appstore --release-type AFTER_APPROVAL # Auto-release after approval
184
- mysigner ship appstore --release-type MANUAL # Hold for manual release
185
- mysigner ship appstore --release-type SCHEDULED --scheduled-date 2026-02-01T10:00:00Z
186
- ```
187
-
188
- ### Submit Command (No Build)
189
-
190
- Submit an existing build that's already uploaded:
191
-
192
- ```bash
193
- # Submit latest iOS build for review
194
- mysigner submit
195
-
196
- # Submit specific build
197
- mysigner submit --build-number 123
198
-
199
- # Submit with metadata overrides
200
- mysigner submit --whats-new "Bug fixes" --support-url https://example.com/support
201
-
202
- # Submit with release type
203
- mysigner submit --release-type MANUAL
204
- ```
205
-
206
- ### Error Handling
207
-
208
- The CLI provides actionable error messages:
209
-
210
- ```
211
- ✗ App Store Connect credentials not configured
212
-
213
- Quick fix:
214
- mysigner doctor # Auto-configure now
215
-
216
- Or manually:
217
- 1. Run: mysigner onboard
218
- 2. Follow Step 5 to add credentials
219
- ```
220
-
221
- ### Workflow Steps
222
-
223
- **TestFlight (3 steps):**
224
- 1. Build xcarchive
225
- 2. Export IPA
226
- 3. Upload to TestFlight
227
-
228
- **App Store (5 steps):**
229
- 1. Build xcarchive
230
- 2. Export IPA
231
- 3. Upload to App Store Connect
232
- 4. Wait for Apple to process build
233
- 5. Submit for App Store review
234
-
235
- ## Android Ship/Submit Commands
236
-
237
- ### Ship vs Submit
238
-
239
- | Command | What it does |
240
- |---------|--------------|
241
- | `mysigner ship internal --platform android` | Full workflow: Build → Sign → Upload → Assign to track |
242
- | `mysigner submit beta --platform android` | Promote existing version to different track (no build) |
243
-
244
- ### Auto-Increment Behavior
245
-
246
- The CLI automatically increments version codes:
247
-
248
- 1. **Queries backend** for highest version code recorded for the app
249
- 2. **Increments** if local version ≤ highest
250
- 3. **Regenerates android folder** (for Expo projects) with new version
251
- 4. **Saves build record** to backend after successful upload
252
-
253
- ### Build Record Auto-Save
254
-
255
- After successful upload, the CLI saves a build record to MySigner backend. This ensures:
256
- - Next upload knows the correct version to use
257
- - No "version code already used" errors
258
- - Dashboard shows accurate version history
259
-
260
- ### Partial Failure Handling
261
-
262
- When AAB uploads but track assignment fails (e.g., Play Console not configured):
263
-
264
- ```
265
- ✗ Upload Failed
266
- Error: Google Play API error: Precondition check failed
267
-
268
- 💡 Google Play Console requires setup before publishing to beta:
269
- For BETA/ALPHA tracks:
270
- • Create a closed/open testing track in Play Console
271
- • Add at least one tester email
272
-
273
- ✅ Your AAB was uploaded successfully!
274
- → Go to Play Console to complete track setup, then use:
275
- mysigner submit beta --platform android --version-code VERSION
276
-
277
- 📝 Build v8 recorded (prevents version conflicts on retry)
278
- ```
279
-
280
- The build record is still saved so your next `ship` command will use the next version code.
281
-
282
- ### Manual Testing Android Commands
283
-
284
- ```bash
285
- # Navigate to an Android/Expo project
286
- cd ~/path/to/your/app
287
-
288
- # Ship to internal track
289
- mysigner ship internal --platform android
290
-
291
- # Ship to other tracks
292
- mysigner ship alpha --platform android
293
- mysigner ship beta --platform android
294
- mysigner ship production --platform android
295
-
296
- # Promote existing build to different track
297
- mysigner submit beta --platform android --version-code 7
298
-
299
- # List Android apps
300
- mysigner android list
301
-
302
- # Register app from current project
303
- mysigner android init
304
-
305
- # Manually add an app
306
- mysigner android add com.example.app --name "My App"
307
- ```
308
-
309
- ## Implemented Commands
310
-
311
- All major commands are implemented:
312
-
313
- ### Authentication
314
- - `mysigner login` - Login with API token
315
- - `mysigner logout` - Clear saved credentials
316
- - `mysigner status` - Show current login status
317
- - `mysigner switch` - Switch organizations
318
-
319
- ### iOS Commands
320
- - `mysigner ship testflight` - Build and upload to TestFlight
321
- - `mysigner ship appstore` - Build, upload, and submit to App Store
322
- - `mysigner submit` - Submit existing build for review
323
- - `mysigner build` - Build xcarchive only
324
- - `mysigner export` - Export archive to IPA
325
- - `mysigner upload testflight` - Upload existing IPA
326
-
327
- ### Android Commands
328
- - `mysigner ship internal/alpha/beta/production --platform android`
329
- - `mysigner submit TRACK --platform android`
330
- - `mysigner keystore upload/download`
331
-
332
- ### Resource Management
333
- - `mysigner devices` - List/add/update devices
334
- - `mysigner profiles` - List/download profiles
335
- - `mysigner certificates` - List/download certificates
336
- - `mysigner orgs` - List organizations
337
-
338
- ### Diagnostics
339
- - `mysigner doctor` - Health check and auto-fix
340
- - `mysigner onboard` - Interactive setup wizard
341
-
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'mysigner'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Install git hooks
9
- git config core.hooksPath .githooks
10
-
11
- # Do any other automated setup that you need to do here
data/test_manual.rb DELETED
@@ -1,103 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Manual test script to verify Config and Client work
5
- # Run with: bundle exec ruby test_manual.rb
6
-
7
- require_relative 'lib/mysigner'
8
-
9
- puts '=' * 60
10
- puts 'My Signer CLI - Manual Test'
11
- puts '=' * 60
12
- puts
13
-
14
- # Test 1: Config Management
15
- puts '1. Testing Config Management'
16
- puts '-' * 60
17
-
18
- config = Mysigner::Config.new
19
- puts '✅ Config instance created'
20
-
21
- # Set some values
22
- config.api_url = 'http://localhost:3000'
23
- config.user_email = 'test@example.com'
24
- config.current_organization_id = 1
25
- config.save_token_for_org(1, 'Test Org', 'test_token_12345678')
26
-
27
- puts '✅ Config values set:'
28
- puts " - API URL: #{config.api_url}"
29
- puts " - User Email: #{config.user_email}"
30
- puts " - Current Token: #{config.display[:current_token]}"
31
- puts " - Org ID: #{config.current_organization_id}"
32
-
33
- # Save config
34
- config.save
35
- puts "✅ Config saved to #{Mysigner::Config::CONFIG_FILE}"
36
-
37
- # Load config
38
- new_config = Mysigner::Config.new
39
- puts '✅ Config loaded from file'
40
- puts " - API URL: #{new_config.api_url}"
41
- puts " - Valid?: #{new_config.valid?}"
42
-
43
- # Clean up
44
- new_config.clear
45
- puts '✅ Config cleared'
46
- puts
47
-
48
- # Test 2: API Client (requires running API server)
49
- puts '2. Testing API Client'
50
- puts '-' * 60
51
-
52
- puts
53
- puts '⚠️ Note: To test the API client, you need:'
54
- puts ' 1. My Signer API running at http://localhost:3000'
55
- puts ' 2. A valid API token'
56
- puts
57
- puts 'Example usage:'
58
- puts
59
-
60
- puts '# Create client'
61
- puts 'client = Mysigner::Client.new('
62
- puts " api_url: 'http://localhost:3000',"
63
- puts " api_token: 'your_token_here'"
64
- puts ')'
65
- puts
66
-
67
- puts '# Test connection'
68
- puts 'response = client.test_connection'
69
- puts "puts response[:data] # => { 'status' => 'ok', 'message' => '...' }"
70
- puts
71
-
72
- puts '# List organizations'
73
- puts "response = client.get('/api/v1/organizations')"
74
- puts "organizations = response[:data]['organizations']"
75
- puts
76
-
77
- puts '# List devices for org #1'
78
- puts "response = client.get('/api/v1/organizations/1/devices')"
79
- puts "devices = response[:data]['devices']"
80
- puts
81
-
82
- puts '# Register a new device'
83
- puts "response = client.post('/api/v1/organizations/1/devices', body: {"
84
- puts " name: 'Test iPhone',"
85
- puts " udid: '00008030-001A1B2C3D4E567F',"
86
- puts " platform: 'IOS'"
87
- puts '})'
88
- puts
89
-
90
- puts '# Error handling'
91
- puts 'begin'
92
- puts " client.get('/api/v1/organizations/999') # Non-existent org"
93
- puts 'rescue Mysigner::NotFoundError => e'
94
- puts " puts \"Error: \#{e.message}\""
95
- puts 'end'
96
- puts
97
-
98
- puts '=' * 60
99
- puts '✅ All basic tests completed!'
100
- puts '=' * 60
101
- puts
102
- puts 'To run automated tests: bundle exec rspec'
103
- puts