Class: Supply::Uploader

Inherits:
Object
  • Object
show all
Defined in:
supply/lib/supply/uploader.rb

Instance Method Summary collapse

Instance Method Details

#fetch_track_and_release!(track, version_code, status = nil) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'supply/lib/supply/uploader.rb', line 80

def fetch_track_and_release!(track, version_code, status = nil)
  tracks = client.tracks(track)
  return nil, nil if tracks.empty?

  track = tracks.first
  releases = track.releases
  releases = releases.select { |r| r.status == status } if status

  if releases.size > 1
    UI.user_error!("More than one release found in this track. Please specify with the :version_code option to select a release.")
  end

  release = releases.first { |r| r.version_codes.include?(version_code) }

  return track, release
end

#perform_uploadObject



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 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!

  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?

  if !Supply.config[:rollout].nil? && Supply.config[:track].to_s != ""
    update_rollout
  end

  promote_track if Supply.config[:track_promote_to]

  if Supply.config[:validate_only]
    UI.message("Validating all track and release changes with Google Play...")
    client.validate_current_edit!
    UI.success("Successfully validated the upload to Google Play")
  else
    UI.message("Uploading all track and release changes to Google Play...")
    client.commit_current_edit!
    UI.success("Successfully finished the upload to Google Play")
  end

  perform_upload_meta(apk_version_codes)
end

#perform_upload_meta(version_codes) ⇒ Object



40
41
42
43
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
73
74
75
76
77
78
# File 'supply/lib/supply/uploader.rb', line 40

def perform_upload_meta(version_codes)
  client.begin_edit(package_name: Supply.config[:package_name])

  if (!Supply.config[:skip_upload_metadata] || !Supply.config[:skip_upload_images] || !Supply.config[:skip_upload_changelogs] || !Supply.config[:skip_upload_screenshots]) && 
    version_codes = [Supply.config[:version_code]] if version_codes.empty?
    version_codes.each do |version_code|
      UI.user_error!("Could not find folder #{}") unless File.directory?()

      track, release = fetch_track_and_release!(Supply.config[:track], version_code)
      UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track
      UI.user_error!("Coult not find release for version code '#{version_code}' to update changelog") unless release

      release_notes = []
      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)

        (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]
        release_notes << upload_changelog(language, release.name) unless Supply.config[:skip_upload_changelogs]
      end

      upload_changelogs(release_notes, release, track) unless release_notes.empty?
    end
  end

  if Supply.config[:validate_only]
    UI.message("Validating all meta changes with Google Play...")
    client.validate_current_edit!
    UI.success("Successfully validated the upload to Google Play")
  else
    UI.message("Uploading all meta changes to Google Play...")
    client.commit_current_edit!
    UI.success("Successfully finished the upload to Google Play")
  end
end

#promote_trackObject



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 'supply/lib/supply/uploader.rb', line 141

def promote_track
  track_from = client.tracks(Supply.config[:track]).first
  unless track_from
    UI.user_error!("Cannot promote from track '#{Supply.config[:track]}' - track doesn't exist")
  end

  releases = track_from.releases
  if Supply.config[:version_code].to_s != ""
    releases = releases.select do |release|
      release.version_codes.include?(Supply.config[:version_code])
    end
  end

  if releases.size == 0
    UI.user_error!("Track '#{Supply.config[:track]}' doesn't have any releases")
  elsif releases.size > 1
    UI.user_error!("Track '#{Supply.config[:track]}' has more than one release - use :version_code to filter the release to promote")
  end

  release = track_from.releases.first
  track_to = client.tracks(Supply.config[:track_promote_to]).first

  if track_to
    # Its okay to set releases to an array containing the newest release
    # Google Play will keep previous releases there this release is a partial rollout
    track_to.releases = [release]
  else
    track_to = AndroidPublisher::Track.new(
      track: Supply.config[:track_promote_to],
      releases: [release]
    )
  end

  client.update_track(Supply.config[:track_promote_to], track_to)
end

#update_rolloutObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'supply/lib/supply/uploader.rb', line 97

def update_rollout
  track, release = fetch_track_and_release!(Supply.config[:track], Supply.config[:version_code], Supply::ReleaseStatus::IN_PROGRESS)
  version_code = release.version_codes.first

  UI.message("Updating #{version_code}'s rollout to '#{Supply.config[:rollout]}' on track '#{Supply.config[:track]}'...")
  UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track

  if track && release
    completed = Supply.config[:rollout].to_f == 1
    release.user_fraction = completed ? nil : Supply.config[:rollout]
    release.status = Supply::ReleaseStatus::COMPLETED if completed

    # Deleted other version codes if completed because only allowed on completed version in a release
    track.releases.delete_if { |r| !(r.version_codes || []).include?(version_code) } if completed
  else
    UI.user_error!("Unable to find version to rollout in track '#{Supply.config[:track]}'")
  end

  client.update_track(Supply.config[:track], track)
end

#upload_apksObject



241
242
243
244
245
246
247
248
249
250
251
252
# File 'supply/lib/supply/uploader.rb', line 241

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_bundlesObject



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'supply/lib/supply/uploader.rb', line 263

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)
    aab_version_codes.push(bundle_version_code)
  end

  return aab_version_codes
end

#upload_changelog(language, version_name) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'supply/lib/supply/uploader.rb', line 177

def upload_changelog(language, version_name)
  UI.user_error!("Cannot find changelog because no version name given - please specify :version_name") unless version_name

  path = File.join(Supply.config[:metadata_path], language, Supply::CHANGELOGS_FOLDER_NAME, "#{version_name}.txt")
  changelog_text = ''
  if File.exist?(path)
    UI.message("Updating changelog for '#{version_name}' and language '#{language}'...")
    changelog_text = File.read(path, encoding: 'UTF-8')
  end

  AndroidPublisher::LocalizedText.new({
    language: language,
    text: changelog_text
  })
end

#upload_changelogs(release_notes, release, track) ⇒ Object



193
194
195
196
# File 'supply/lib/supply/uploader.rb', line 193

def upload_changelogs(release_notes, release, track)
  release.release_notes = release_notes
  client.upload_changelogs(track, Supply.config[:track])
end

#upload_images(language) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
# File 'supply/lib/supply/uploader.rb', line 211

def upload_images(language)
  Supply::IMAGES_TYPES.each do |image_type|
    search = File.join(, 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) ⇒ Object



254
255
256
257
258
259
260
261
# File 'supply/lib/supply/uploader.rb', line 254

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) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
# File 'supply/lib/supply/uploader.rb', line 198

def (language, listing)
  Supply::AVAILABLE_METADATA_FIELDS.each do |key|
    path = File.join(, 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) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'supply/lib/supply/uploader.rb', line 224

def upload_screenshots(language)
  Supply::SCREENSHOT_TYPES.each do |screenshot_type|
    search = File.join(, 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!Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'supply/lib/supply/uploader.rb', line 118

def verify_config!
  unless  || 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

  if Supply.config[:release_status] == 'draft' && Supply.config[:rollout]
    UI.user_error!(%(Cannot specify rollout percentage when the release status is set to 'draft'))
  end

  unless Supply.config[:version_codes_to_retain].nil?
    Supply.config[:version_codes_to_retain] = Supply.config[:version_codes_to_retain].map(&:to_i)
  end
end