Class: Mysigner::Upload::PlayStoreUploader
- Inherits:
-
Object
- Object
- Mysigner::Upload::PlayStoreUploader
- Defined in:
- lib/mysigner/upload/play_store_uploader.rb
Defined Under Namespace
Classes: CredentialsError, MissingLocalCredentialsError, PartialUploadError, TrackError, UploadError
Constant Summary collapse
- VALID_TRACKS =
%w[internal alpha beta production].freeze
- SCOPE =
'https://www.googleapis.com/auth/androidpublisher'
Class Method Summary collapse
-
.fetch_highest_version_code(package_name:, access_token:) ⇒ Object
mysigner-22 follow-up — pre-check the user’s project versionCode against what’s already on Google Play in local-only mode, where the MySigner server’s ‘highest_version_code` lookup is bypassed.
Instance Method Summary collapse
-
#assign_existing_to_track!(version_code, track:, release_notes: nil, user_fraction: nil) ⇒ Object
Assign an existing version code to a track.
-
#initialize(aab_path:, package_name:, access_token: nil, local_only: false, play_creds: nil) ⇒ PlayStoreUploader
constructor
Phase 0: accepts a short-lived OAuth2 access_token (minted server-side from the customer’s service-account JSON).
-
#upload!(track: 'internal', release_notes: nil, user_fraction: nil, status: nil, in_app_update_priority: nil, release_name: nil, country_targeting: nil, changes_not_sent_for_review: nil) ⇒ Hash
Upload AAB and optionally assign to a track.
-
#upload_bundle_only! ⇒ Object
Upload AAB only (without assigning to track).
Constructor Details
#initialize(aab_path:, package_name:, access_token: nil, local_only: false, play_creds: nil) ⇒ PlayStoreUploader
Phase 0: accepts a short-lived OAuth2 access_token (minted server-side from the customer’s service-account JSON). The JSON no longer leaves the server. google-api-ruby-client accepts a bare string for authorization= and sends it as ‘Authorization: Bearer <token>`.
mysigner-43: when ‘local_only: true`, `access_token` is optional —the uploader mints one locally from Keychain-backed SA-JSON. The SA-JSON never leaves the user’s machine, and no MySigner server credential endpoints are contacted.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 83 def initialize(aab_path:, package_name:, access_token: nil, local_only: false, play_creds: nil) @aab_path = File.(aab_path) @access_token = access_token @package_name = package_name @local_only = local_only # mysigner-22 Phase 5 — pre-resolved PlayCreds Struct from the # CredentialResolver cascade. When nil (legacy / unit tests), we fall # back to the resolver with default args (Keychain only) inside # local_access_token — preserving existing spec invariants. @play_creds = play_creds if @local_only # Mint immediately so missing-credentials errors surface at # construction time (same DX as the server path's # CredentialsError) rather than mid-upload. @access_token = local_access_token elsif @access_token.nil? || @access_token.to_s.empty? raise CredentialsError, 'access_token is required' end validate_aab! setup_google_client! end |
Class Method Details
.fetch_highest_version_code(package_name:, access_token:) ⇒ Object
mysigner-22 follow-up — pre-check the user’s project versionCode against what’s already on Google Play in local-only mode, where the MySigner server’s ‘highest_version_code` lookup is bypassed. The cheapest authenticated way to ask Google “what’s already there” is to insert an edit, list all uploaded bundles (which carry their versionCode), and discard the edit. Inserting an edit is free and has no side effect when never committed.
Returns the maximum versionCode across all bundles (Integer), or nil when the app has no bundles yet (very first upload).
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 44 def self.fetch_highest_version_code(package_name:, access_token:) require 'google/apis/androidpublisher_v3' service = Google::Apis::AndroidpublisherV3::AndroidPublisherService.new service. = access_token edit = service.insert_edit(package_name, Google::Apis::AndroidpublisherV3::AppEdit.new) begin bundles_response = service.list_edit_bundles(package_name, edit.id) version_codes = Array(bundles_response&.bundles).map(&:version_code).compact return nil if version_codes.empty? version_codes.max ensure # Best-effort cleanup — the edit auto-expires after a week if we # leak one, but tidiness is cheap. Swallow errors so a transient # cleanup failure can't mask the real return value. begin service.delete_edit(package_name, edit.id) rescue StandardError nil end end rescue Google::Apis::ClientError # We treat a lookup failure (auth issue, package-not-found) as # "unknown" rather than fatal — Google will still reject at upload # time with a useful message. This pre-check is best-effort. nil end |
Instance Method Details
#assign_existing_to_track!(version_code, track:, release_notes: nil, user_fraction: nil) ⇒ Object
Assign an existing version code to a track
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 205 def assign_existing_to_track!(version_code, track:, release_notes: nil, user_fraction: nil) @current_track = track # Store for error messages begin edit = create_edit assign_to_track(edit.id, track, version_code, release_notes: release_notes, user_fraction: user_fraction) commit_edit(edit.id) { success: true, version_code: version_code, track: track, package_name: @package_name } rescue Google::Apis::ClientError => e = parse_google_error(e) raise TrackError, "Failed to assign to track: #{}" end end |
#upload!(track: 'internal', release_notes: nil, user_fraction: nil, status: nil, in_app_update_priority: nil, release_name: nil, country_targeting: nil, changes_not_sent_for_review: nil) ⇒ Hash
Upload AAB and optionally assign to a track
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 119 def upload!(track: 'internal', release_notes: nil, user_fraction: nil, status: nil, in_app_update_priority: nil, release_name: nil, country_targeting: nil, changes_not_sent_for_review: nil) @current_track = track # Store for error messages say_uploading(track) version_code = nil begin # 1. Create an edit edit = create_edit # 2. Upload the AAB bundle = upload_bundle(edit.id) version_code = bundle.version_code say_upload_success(version_code) # 3. Assign to track with release if track assign_to_track( edit.id, track, version_code, release_notes: release_notes, user_fraction: user_fraction, status: status, in_app_update_priority: in_app_update_priority, release_name: release_name, country_targeting: country_targeting ) end # 4. Commit the edit commit_edit(edit.id, changes_not_sent_for_review: changes_not_sent_for_review) say_success(track, version_code) { success: true, version_code: version_code, track: track, package_name: @package_name } rescue Google::Apis::ClientError => e = parse_google_error(e) # If AAB was uploaded, raise PartialUploadError so CLI can save the version raise PartialUploadError.new("Google Play API error: #{}", version_code: version_code) if version_code raise UploadError, "Google Play API error: #{}" rescue PartialUploadError # Re-raise as-is raise rescue StandardError => e raise PartialUploadError.new("Upload failed: #{e.}", version_code: version_code) if version_code raise UploadError, "Upload failed: #{e.}" end end |
#upload_bundle_only! ⇒ Object
Upload AAB only (without assigning to track)
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 178 def upload_bundle_only! say_uploading(nil) begin edit = create_edit bundle = upload_bundle(edit.id) version_code = bundle.version_code say_upload_success(version_code) # Don't assign to track, just commit commit_edit(edit.id) { success: true, version_code: version_code, package_name: @package_name } rescue Google::Apis::ClientError => e = parse_google_error(e) raise UploadError, "Google Play API error: #{}" rescue StandardError => e raise UploadError, "Upload failed: #{e.}" end end |