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_codelookup 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.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 84 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).
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 73 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 45 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
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 206 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
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 176 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 120 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)
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/mysigner/upload/play_store_uploader.rb', line 179 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 |