class Supply::Uploader
Public Instance Methods
perform_upload()
click to toggle source
# File supply/lib/supply/uploader.rb, line 3 def perform_upload FastlaneCore::PrintTable.print_values(config: Supply.config, hide_keys: [:issuer], mask_keys: [:json_key_data], title: "Summary for supply #{Fastlane::VERSION}") client.begin_edit(package_name: Supply.config[:package_name]) verify_config! if metadata_path UI.user_error!("Could not find folder #{metadata_path}") unless File.directory?(metadata_path) all_languages.each do |language| next if language.start_with?('.') # e.g. . or .. or hidden folders UI.message("Preparing to upload for language '#{language}'...") listing = client.listing_for_language(language) upload_metadata(language, listing) unless Supply.config[:skip_upload_metadata] upload_images(language) unless Supply.config[:skip_upload_images] upload_screenshots(language) unless Supply.config[:skip_upload_screenshots] upload_changelogs(language) unless Supply.config[:skip_upload_metadata] end end apk_version_codes = [] apk_version_codes.concat(upload_apks) unless Supply.config[:skip_upload_apk] apk_version_codes.concat(upload_bundles) unless Supply.config[:skip_upload_aab] upload_mapping(apk_version_codes) apk_version_codes.concat(Supply.config[:version_codes_to_retain]) if Supply.config[:version_codes_to_retain] # Only update tracks if we have version codes # Updating a track with empty version codes can completely clear out a track update_track(apk_version_codes) unless apk_version_codes.empty? promote_track if Supply.config[:track_promote_to] if Supply.config[:validate_only] UI.message("Validating all changes with Google Play...") client.validate_current_edit! UI.success("Successfully validated the upload to Google Play") else UI.message("Uploading all changes to Google Play...") client.commit_current_edit! UI.success("Successfully finished the upload to Google Play") end end
promote_track()
click to toggle source
# File supply/lib/supply/uploader.rb, line 65 def promote_track version_codes = client.track_version_codes(Supply.config[:track]) # the actual value passed for the rollout argument does not matter because it will be ignored by the Google Play API # but it has to be between 0.0 and 1.0 to pass the validity check. So we are passing the default value 0.1 client.update_track(Supply.config[:track], 0.1, nil) if Supply.config[:deactivate_on_promote] client.update_track(Supply.config[:track_promote_to], Supply.config[:rollout] || 0.1, version_codes) end
upload_apks()
click to toggle source
# File supply/lib/supply/uploader.rb, line 134 def upload_apks apk_paths = [Supply.config[:apk]] unless (apk_paths = Supply.config[:apk_paths]) apk_paths.compact! apk_version_codes = [] apk_paths.each do |apk_path| apk_version_codes.push(upload_binary_data(apk_path)) end return apk_version_codes end
upload_bundles()
click to toggle source
# File supply/lib/supply/uploader.rb, line 156 def upload_bundles aab_paths = [Supply.config[:aab]] unless (aab_paths = Supply.config[:aab_paths]) return [] unless aab_paths aab_paths.compact! aab_version_codes = [] aab_paths.each do |aab_path| UI.message("Preparing aab at path '#{aab_path}' for upload...") bundle_version_code = client.upload_bundle(aab_path) if metadata_path all_languages.each do |language| next if language.start_with?('.') # e.g. . or .. or hidden folders upload_changelog(language, bundle_version_code) end end aab_version_codes.push(bundle_version_code) end return aab_version_codes end
upload_changelog(language, version_code)
click to toggle source
# File supply/lib/supply/uploader.rb, line 82 def upload_changelog(language, version_code) path = File.join(metadata_path, language, Supply::CHANGELOGS_FOLDER_NAME, "#{version_code}.txt") if File.exist?(path) UI.message("Updating changelog for code version '#{version_code}' and language '#{language}'...") apk_listing = ApkListing.new(File.read(path, encoding: 'UTF-8'), language, version_code) client.update_apk_listing_for_language(apk_listing) end end
upload_changelogs(language)
click to toggle source
# File supply/lib/supply/uploader.rb, line 73 def upload_changelogs(language) client.apks_version_codes.each do |apk_version_code| upload_changelog(language, apk_version_code) end client.aab_version_codes.each do |aab_version_code| upload_changelog(language, aab_version_code) end end
upload_images(language)
click to toggle source
# File supply/lib/supply/uploader.rb, line 104 def upload_images(language) Supply::IMAGES_TYPES.each do |image_type| search = File.join(metadata_path, language, Supply::IMAGES_FOLDER_NAME, image_type) + ".#{IMAGE_FILE_EXTENSIONS}" path = Dir.glob(search, File::FNM_CASEFOLD).last next unless path UI.message("Uploading image file #{path}...") client.upload_image(image_path: File.expand_path(path), image_type: image_type, language: language) end end
upload_mapping(apk_version_codes)
click to toggle source
# File supply/lib/supply/uploader.rb, line 147 def upload_mapping(apk_version_codes) mapping_paths = [Supply.config[:mapping]] unless (mapping_paths = Supply.config[:mapping_paths]) mapping_paths.zip(apk_version_codes).each do |mapping_path, version_code| if mapping_path client.upload_mapping(mapping_path, version_code) end end end
upload_metadata(language, listing)
click to toggle source
# File supply/lib/supply/uploader.rb, line 91 def upload_metadata(language, listing) Supply::AVAILABLE_METADATA_FIELDS.each do |key| path = File.join(metadata_path, language, "#{key}.txt") listing.send("#{key}=".to_sym, File.read(path, encoding: 'UTF-8')) if File.exist?(path) end begin listing.save rescue Encoding::InvalidByteSequenceError => ex message = (ex.message || '').capitalize UI.user_error!("Metadata must be UTF-8 encoded. #{message}") end end
upload_screenshots(language)
click to toggle source
# File supply/lib/supply/uploader.rb, line 117 def upload_screenshots(language) Supply::SCREENSHOT_TYPES.each do |screenshot_type| search = File.join(metadata_path, language, Supply::IMAGES_FOLDER_NAME, screenshot_type, "*.#{IMAGE_FILE_EXTENSIONS}") paths = Dir.glob(search, File::FNM_CASEFOLD) next unless paths.count > 0 client.clear_screenshots(image_type: screenshot_type, language: language) paths.sort.each do |path| UI.message("Uploading screenshot #{path}...") client.upload_image(image_path: File.expand_path(path), image_type: screenshot_type, language: language) end end end
verify_config!()
click to toggle source
# File supply/lib/supply/uploader.rb, line 50 def verify_config! unless metadata_path || Supply.config[:apk] || Supply.config[:apk_paths] || Supply.config[:aab] || Supply.config[:aab_paths] || (Supply.config[:track] && Supply.config[:track_promote_to]) UI.user_error!("No local metadata, apks, aab, or track to promote were found, make sure to run `fastlane supply init` to setup supply") end # Can't upload both at apk and aab at same time # Need to error out users when there both apks and aabs are detected apk_paths = [Supply.config[:apk], Supply.config[:apk_paths]].flatten.compact could_upload_apk = !apk_paths.empty? && !Supply.config[:skip_upload_apk] could_upload_aab = Supply.config[:aab] && !Supply.config[:skip_upload_aab] if could_upload_apk && could_upload_aab UI.user_error!("Cannot provide both apk(s) and aab - use `skip_upload_apk`, `skip_upload_aab`, or make sure to remove any existing .apk or .aab files that are no longer needed") end end
Private Instance Methods
all_languages()
click to toggle source
returns only language directories from metadata_path
# File supply/lib/supply/uploader.rb, line 285 def all_languages Dir.entries(metadata_path) .select { |f| File.directory?(File.join(metadata_path, f)) } .reject { |f| f.start_with?('.') } .sort { |x, y| x <=> y } end
check_superseded_tracks(apk_version_codes)
click to toggle source
Remove any version codes that is:
- Lesser than the greatest of any later (i.e. production) track - Or lesser than the currently being uploaded if it's in an earlier (i.e. alpha) track
# File supply/lib/supply/uploader.rb, line 246 def check_superseded_tracks(apk_version_codes) UI.message("Checking superseded tracks, uploading '#{apk_version_codes}' to '#{Supply.config[:track]}'...") max_apk_version_code = apk_version_codes.max max_tracks_version_code = nil tracks = ["production", "rollout", "beta", "alpha", "internal"] config_track_index = tracks.index(Supply.config[:track]) # Custom "closed" tracks are now allowed (https://support.google.com/googleplay/android-developer/answer/3131213) # Custom tracks have an equal level with alpha (alpha is considered a closed track as well) # If a track index is not found, we will assume is a custom track so an alpha index is given config_track_index = tracks.index("alpha") unless config_track_index tracks.each_index do |track_index| track = tracks[track_index] track_version_codes = client.track_version_codes(track).sort UI.verbose("Found '#{track_version_codes}' on track '#{track}'") next if track_index.eql?(config_track_index) next if track_version_codes.empty? if max_tracks_version_code.nil? max_tracks_version_code = track_version_codes.max end removed_version_codes = track_version_codes.take_while do |v| v < max_tracks_version_code || (v < max_apk_version_code && track_index > config_track_index) end next if removed_version_codes.empty? keep_version_codes = track_version_codes - removed_version_codes max_tracks_version_code = keep_version_codes[0] unless keep_version_codes.empty? client.update_track(track, 1.0, keep_version_codes) UI.message("Superseded track '#{track}', removed '#{removed_version_codes}'") end end
client()
click to toggle source
# File supply/lib/supply/uploader.rb, line 292 def client @client ||= Client.make_from_config end
find_obbs(apk_path)
click to toggle source
@return a map of the obb paths for that apk keyed by their detected expansion file type E.g. { 'main' => 'path/to/main.obb', 'patch' => 'path/to/patch.obb' }
# File supply/lib/supply/uploader.rb, line 316 def find_obbs(apk_path) search = File.join(File.dirname(apk_path), '*.obb') paths = Dir.glob(search, File::FNM_CASEFOLD) expansion_paths = {} paths.each do |path| type = obb_expansion_file_type(path) next unless type if expansion_paths[type] UI.important("Can only upload one '#{type}' apk expansion. Skipping obb upload entirely.") UI.important("If you'd like this to work differently, please submit an issue.") return {} end expansion_paths[type] = path end expansion_paths end
metadata_path()
click to toggle source
# File supply/lib/supply/uploader.rb, line 296 def metadata_path Supply.config[:metadata_path] end
obb_expansion_file_type(obb_file_path)
click to toggle source
# File supply/lib/supply/uploader.rb, line 340 def obb_expansion_file_type(obb_file_path) filename = File.basename(obb_file_path, ".obb") if filename.include?('main') 'main' elsif filename.include?('patch') 'patch' end end
update_obb(apk_version_code, expansion_file_type, references_version, file_size)
click to toggle source
# File supply/lib/supply/uploader.rb, line 224 def update_obb(apk_version_code, expansion_file_type, references_version, file_size) UI.message("Updating '#{expansion_file_type}' expansion file from version '#{references_version}'...") client.update_obb(apk_version_code, expansion_file_type, references_version, file_size) end
update_track(apk_version_codes)
click to toggle source
# File supply/lib/supply/uploader.rb, line 232 def update_track(apk_version_codes) UI.message("Updating track '#{Supply.config[:track]}'...") check_superseded_tracks(apk_version_codes) if Supply.config[:check_superseded_tracks] if Supply.config[:track].eql?("rollout") client.update_track(Supply.config[:track], Supply.config[:rollout] || 0.1, apk_version_codes) else client.update_track(Supply.config[:track], 1.0, apk_version_codes) end end
upload_binary_data(apk_path)
click to toggle source
Upload binary apk and obb and corresponding change logs with client
@param [String] apk_path
Path of the apk file to upload.
@return [Integer] The apk version code returned after uploading, or nil if there was a problem
# File supply/lib/supply/uploader.rb, line 189 def upload_binary_data(apk_path) apk_version_code = nil if apk_path UI.message("Preparing apk at path '#{apk_path}' for upload...") apk_version_code = client.upload_apk(apk_path) UI.user_error!("Could not upload #{apk_path}") unless apk_version_code if Supply.config[:obb_main_references_version] && Supply.config[:obb_main_file_size] update_obb(apk_version_code, 'main', Supply.config[:obb_main_references_version], Supply.config[:obb_main_file_size]) end if Supply.config[:obb_patch_references_version] && Supply.config[:obb_patch_file_size] update_obb(apk_version_code, 'patch', Supply.config[:obb_patch_references_version], Supply.config[:obb_patch_file_size]) end upload_obbs(apk_path, apk_version_code) if metadata_path all_languages.each do |language| next if language.start_with?('.') # e.g. . or .. or hidden folders upload_changelog(language, apk_version_code) end end else UI.message("No apk file found, you can pass the path to your apk using the `apk` option") end apk_version_code end
upload_obb(obb_path, expansion_file_type, apk_version_code)
click to toggle source
# File supply/lib/supply/uploader.rb, line 333 def upload_obb(obb_path, expansion_file_type, apk_version_code) UI.message("Uploading obb file #{obb_path}...") client.upload_obb(obb_file_path: obb_path, apk_version_code: apk_version_code, expansion_file_type: expansion_file_type) end
upload_obbs(apk_path, apk_version_code)
click to toggle source
searches for obbs in the directory where the apk is located and upload at most one main and one patch file. Do nothing if it finds more than one of either of them.
# File supply/lib/supply/uploader.rb, line 303 def upload_obbs(apk_path, apk_version_code) expansion_paths = find_obbs(apk_path) ['main', 'patch'].each do |type| if expansion_paths[type] upload_obb(expansion_paths[type], type, apk_version_code) end end end