From e0fd5780810a5a2f415ccad0ec9b94bb8137ee20 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:27:20 -0700 Subject: [PATCH 1/2] Add getLivePlayStoreVersion lane This lane checks for actually published (status 'completed') versions on Google Play rather than just approved versions. With managed publishing enabled, versions can be approved but not yet published to users. --- fastlane/Fastfile | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 36c8d5afbfc..b42340734f1 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -335,6 +335,83 @@ platform :android do UI.message("version_number: #{latest_version_number}") end + desc "Get the version that's actually live/published to users on Google Play" + lane :getLivePlayStoreVersion do |options| + package_name = options[:package_name] + track = options[:track] + + # Determine credentials file based on package name + case package_name + when "com.x8bit.bitwarden", "com.x8bit.bitwarden.beta" + json_key = "secrets/play_creds.json" + when "com.bitwarden.authenticator" + json_key = "secrets/authenticator_play_store-creds.json" + else + UI.important "Unexpected package name: #{package_name}, using default play store json key" + json_key = "secrets/play_creds.json" + end + + # Get release information for the track + releases = google_play_track_release_names( + package_name: package_name, + track: track, + json_key: json_key, + ) + + version_codes = google_play_track_version_codes( + package_name: package_name, + track: track, + json_key: json_key, + ) + + # Use supply to get detailed release status + require 'supply' + require 'supply/options' + + Supply.config = FastlaneCore::Configuration.create( + Supply::Options.available_options, + { + package_name: package_name, + track: track, + json_key: json_key + } + ) + + client = Supply::Client.make_from_config + track_info = client.track_version_codes(track: track) + + # Check if there's a completed release (status "completed" means it's live) + # With managed publishing, only completed releases are actually available to users + if track_info && track_info.releases + completed_release = track_info.releases.find { |r| r.status == "completed" } + + if completed_release && completed_release.version_codes && !completed_release.version_codes.empty? + # Get the highest version code from the completed release + live_version_code = completed_release.version_codes.max + + # Find the corresponding version name + # Note: version_codes and releases arrays should be parallel + index = version_codes.index(live_version_code) + live_version_name = index ? releases[index] : releases.first + + UI.message("Live version_name: #{live_version_name}") + UI.message("Live version_number: #{live_version_code}") + + # Output in the same format as getLatestPlayStoreVersion for compatibility + UI.message("version_name: #{live_version_name}") + UI.message("version_number: #{live_version_code}") + else + UI.message("No completed release found on track: #{track}") + UI.message("version_name: ") + UI.message("version_number: ") + end + else + UI.message("No releases found on track: #{track}") + UI.message("version_name: ") + UI.message("version_number: ") + end + end + desc "Assemble debug variants" lane :buildAuthenticatorDebug do gradle( From bc893fc97b45956ff0af538fd0aa3cc459a6a4b4 Mon Sep 17 00:00:00 2001 From: Amy Galles <9685081+AmyLGalles@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:15:52 -0700 Subject: [PATCH 2/2] Fix getLivePlayStoreVersion to correctly access Track object The previous implementation incorrectly called client.track_version_codes which returns an Array, not a Track object with .releases. Changes: - Use client.tracks(track) to get Track objects - Wrap in begin_edit/abort_current_edit as required by Supply client - Access releases directly from track_obj.releases - Get version name directly from completed_release.name instead of parallel array lookup This fixes the NoMethodError that would occur at runtime when trying to call .releases on an Array. --- fastlane/Fastfile | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index b42340734f1..3087c420890 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -351,19 +351,6 @@ platform :android do json_key = "secrets/play_creds.json" end - # Get release information for the track - releases = google_play_track_release_names( - package_name: package_name, - track: track, - json_key: json_key, - ) - - version_codes = google_play_track_version_codes( - package_name: package_name, - track: track, - json_key: json_key, - ) - # Use supply to get detailed release status require 'supply' require 'supply/options' @@ -378,21 +365,24 @@ platform :android do ) client = Supply::Client.make_from_config - track_info = client.track_version_codes(track: track) + + # Begin edit to access track information + client.begin_edit(package_name: package_name) + tracks = client.tracks(track) + track_obj = tracks.first + client.abort_current_edit # Check if there's a completed release (status "completed" means it's live) # With managed publishing, only completed releases are actually available to users - if track_info && track_info.releases - completed_release = track_info.releases.find { |r| r.status == "completed" } + if track_obj && track_obj.releases + completed_release = track_obj.releases.find { |r| r.status == "completed" } if completed_release && completed_release.version_codes && !completed_release.version_codes.empty? # Get the highest version code from the completed release live_version_code = completed_release.version_codes.max - # Find the corresponding version name - # Note: version_codes and releases arrays should be parallel - index = version_codes.index(live_version_code) - live_version_name = index ? releases[index] : releases.first + # Get the corresponding version name from the release + live_version_name = completed_release.name UI.message("Live version_name: #{live_version_name}") UI.message("Live version_number: #{live_version_code}")