fastlane 2.132.0 → 2.135.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +74 -74
- data/fastlane/lib/fastlane/action.rb +1 -1
- data/fastlane/lib/fastlane/actions/actions_helper.rb +1 -1
- data/fastlane/lib/fastlane/actions/carthage.rb +7 -0
- data/fastlane/lib/fastlane/actions/cocoapods.rb +24 -2
- data/fastlane/lib/fastlane/actions/deploygate.rb +1 -1
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +4 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +26 -2
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +26 -3
- data/fastlane/lib/fastlane/actions/download_from_play_store.rb +1 -1
- data/fastlane/lib/fastlane/actions/get_version_number.rb +10 -4
- data/fastlane/lib/fastlane/actions/google_play_track_version_codes.rb +5 -1
- data/fastlane/lib/fastlane/actions/sonar.rb +16 -0
- data/fastlane/lib/fastlane/actions/testfairy.rb +1 -1
- data/fastlane/lib/fastlane/actions/update_fastlane.rb +9 -49
- data/fastlane/lib/fastlane/actions/update_keychain_access_groups.rb +94 -0
- data/fastlane/lib/fastlane/environment_printer.rb +9 -3
- data/fastlane/lib/fastlane/fast_file.rb +3 -2
- data/fastlane/lib/fastlane/lane_manager.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +12 -2
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
- data/fastlane/lib/fastlane/runner.rb +2 -2
- data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +10 -2
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +72 -3
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +121 -1
- data/fastlane/swift/Fastlane.swift +3900 -16
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +81 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +60 -2
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +15 -2
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +109 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +39 -2
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +69 -1
- data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +3 -3
- data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +1 -1
- data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
- data/fastlane_core/lib/fastlane_core/swag.rb +1 -1
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +1 -1
- data/match/lib/match/importer.rb +1 -1
- data/match/lib/match/storage/google_cloud_storage.rb +3 -0
- data/scan/lib/scan/error_handler.rb +9 -4
- data/scan/lib/scan/runner.rb +1 -1
- data/sigh/lib/assets/resign.sh +2 -2
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +1 -1
- data/spaceship/lib/spaceship/client.rb +2 -2
- data/supply/lib/supply.rb +23 -0
- data/supply/lib/supply/.options.rb.swp +0 -0
- data/supply/lib/supply/.uploader.rb.swp +0 -0
- data/supply/lib/supply/client.rb +101 -55
- data/supply/lib/supply/options.rb +50 -14
- data/supply/lib/supply/release_listing.rb +18 -0
- data/supply/lib/supply/setup.rb +42 -34
- data/supply/lib/supply/uploader.rb +171 -93
- metadata +36 -41
- data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/gym/lib/gym/.runner.rb.swp +0 -0
- data/pilot/lib/pilot/.manager.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
- data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
@@ -5,7 +5,6 @@ module Supply
|
|
5
5
|
class Options
|
6
6
|
# rubocop:disable Metrics/PerceivedComplexity
|
7
7
|
def self.available_options
|
8
|
-
default_tracks = %w(production beta alpha internal rollout)
|
9
8
|
@options ||= [
|
10
9
|
FastlaneCore::ConfigItem.new(key: :package_name,
|
11
10
|
env_name: "SUPPLY_PACKAGE_NAME",
|
@@ -14,11 +13,37 @@ module Supply
|
|
14
13
|
code_gen_sensitive: true,
|
15
14
|
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:package_name),
|
16
15
|
default_value_dynamic: true),
|
16
|
+
FastlaneCore::ConfigItem.new(key: :version_name,
|
17
|
+
env_name: "SUPPLY_VERSION_NAME",
|
18
|
+
short_option: "-n",
|
19
|
+
optional: true,
|
20
|
+
description: "Version name (used when uploading new apks/aabs) - defaults to 'versionName' in build.gradle or AndroidManifest.xml",
|
21
|
+
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:version_name),
|
22
|
+
default_value_dynamic: true),
|
23
|
+
FastlaneCore::ConfigItem.new(key: :version_code,
|
24
|
+
env_name: "SUPPLY_VERSION_CODE",
|
25
|
+
short_option: "-C",
|
26
|
+
optional: true,
|
27
|
+
type: Integer,
|
28
|
+
description: "Version code (used when updating rollout or promoting specific versions)",
|
29
|
+
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:version_code),
|
30
|
+
default_value_dynamic: true),
|
31
|
+
FastlaneCore::ConfigItem.new(key: :release_status,
|
32
|
+
env_name: "SUPPLY_RELEASE_STATUS",
|
33
|
+
short_option: "-e",
|
34
|
+
optional: true,
|
35
|
+
description: "Release status (used when uploading new apks/aabs) - valid values are #{Supply::ReleaseStatus::ALL.join(', ')}",
|
36
|
+
default_value: Supply::ReleaseStatus::COMPLETED,
|
37
|
+
default_value_dynamic: true,
|
38
|
+
verify_block: proc do |value|
|
39
|
+
UI.user_error!("Value must be one of '#{Supply::RELEASE_STATUS}'") unless Supply::ReleaseStatus::ALL.include?(value)
|
40
|
+
end),
|
17
41
|
FastlaneCore::ConfigItem.new(key: :track,
|
18
42
|
short_option: "-a",
|
19
43
|
env_name: "SUPPLY_TRACK",
|
20
|
-
description: "The track of the application to use. The default available tracks are: #{
|
21
|
-
default_value:
|
44
|
+
description: "The track of the application to use. The default available tracks are: #{Supply::Tracks::DEFAULTS.join(', ')}",
|
45
|
+
default_value: Supply::Tracks::DEFAULT,
|
46
|
+
type: String),
|
22
47
|
FastlaneCore::ConfigItem.new(key: :rollout,
|
23
48
|
short_option: "-r",
|
24
49
|
description: "The percentage of the user fraction when uploading to the rollout track",
|
@@ -104,6 +129,7 @@ module Supply
|
|
104
129
|
FastlaneCore::ConfigItem.new(key: :apk_paths,
|
105
130
|
env_name: "SUPPLY_APK_PATHS",
|
106
131
|
conflicting_options: [:apk, :aab, :aab_paths],
|
132
|
+
code_gen_sensitive: true,
|
107
133
|
optional: true,
|
108
134
|
type: Array,
|
109
135
|
description: "An array of paths to APK files to upload",
|
@@ -131,6 +157,7 @@ module Supply
|
|
131
157
|
FastlaneCore::ConfigItem.new(key: :aab_paths,
|
132
158
|
env_name: "SUPPLY_AAB_PATHS",
|
133
159
|
conflicting_options: [:apk, :apk_paths, :aab],
|
160
|
+
code_gen_sensitive: true,
|
134
161
|
optional: true,
|
135
162
|
type: Array,
|
136
163
|
description: "An array of paths to AAB files to upload",
|
@@ -146,41 +173,47 @@ module Supply
|
|
146
173
|
env_name: "SUPPLY_SKIP_UPLOAD_APK",
|
147
174
|
optional: true,
|
148
175
|
description: "Whether to skip uploading APK",
|
149
|
-
|
176
|
+
type: Boolean,
|
150
177
|
default_value: false),
|
151
178
|
FastlaneCore::ConfigItem.new(key: :skip_upload_aab,
|
152
179
|
env_name: "SUPPLY_SKIP_UPLOAD_AAB",
|
153
180
|
optional: true,
|
154
181
|
description: "Whether to skip uploading AAB",
|
155
|
-
|
182
|
+
type: Boolean,
|
156
183
|
default_value: false),
|
157
184
|
FastlaneCore::ConfigItem.new(key: :skip_upload_metadata,
|
158
185
|
env_name: "SUPPLY_SKIP_UPLOAD_METADATA",
|
159
186
|
optional: true,
|
160
|
-
description: "Whether to skip uploading metadata",
|
161
|
-
|
187
|
+
description: "Whether to skip uploading metadata, changelogs not included",
|
188
|
+
type: Boolean,
|
189
|
+
default_value: false),
|
190
|
+
FastlaneCore::ConfigItem.new(key: :skip_upload_changelogs,
|
191
|
+
env_name: "SUPPLY_SKIP_UPLOAD_CHANGELOGS",
|
192
|
+
optional: true,
|
193
|
+
description: "Whether to skip uploading changelogs",
|
194
|
+
type: Boolean,
|
162
195
|
default_value: false),
|
163
196
|
FastlaneCore::ConfigItem.new(key: :skip_upload_images,
|
164
197
|
env_name: "SUPPLY_SKIP_UPLOAD_IMAGES",
|
165
198
|
optional: true,
|
166
199
|
description: "Whether to skip uploading images, screenshots not included",
|
167
|
-
|
200
|
+
type: Boolean,
|
168
201
|
default_value: false),
|
169
202
|
FastlaneCore::ConfigItem.new(key: :skip_upload_screenshots,
|
170
203
|
env_name: "SUPPLY_SKIP_UPLOAD_SCREENSHOTS",
|
171
204
|
optional: true,
|
172
205
|
description: "Whether to skip uploading SCREENSHOTS",
|
173
|
-
|
206
|
+
type: Boolean,
|
174
207
|
default_value: false),
|
175
208
|
FastlaneCore::ConfigItem.new(key: :track_promote_to,
|
176
209
|
env_name: "SUPPLY_TRACK_PROMOTE_TO",
|
177
210
|
optional: true,
|
178
|
-
description: "The track to promote to. The default available tracks are: #{
|
211
|
+
description: "The track to promote to. The default available tracks are: #{Supply::Tracks::DEFAULTS.join(', ')}"),
|
179
212
|
FastlaneCore::ConfigItem.new(key: :validate_only,
|
180
213
|
env_name: "SUPPLY_VALIDATE_ONLY",
|
181
214
|
optional: true,
|
182
215
|
description: "Only validate changes with Google Play rather than actually publish",
|
183
|
-
|
216
|
+
type: Boolean,
|
184
217
|
default_value: false),
|
185
218
|
FastlaneCore::ConfigItem.new(key: :mapping,
|
186
219
|
env_name: "SUPPLY_MAPPING",
|
@@ -215,7 +248,8 @@ module Supply
|
|
215
248
|
env_name: "SUPPLY_CHECK_SUPERSEDED_TRACKS",
|
216
249
|
optional: true,
|
217
250
|
description: "Check the other tracks for superseded versions and disable them",
|
218
|
-
|
251
|
+
deprecated: "Google Play does this automatically now",
|
252
|
+
type: Boolean,
|
219
253
|
default_value: false),
|
220
254
|
FastlaneCore::ConfigItem.new(key: :timeout,
|
221
255
|
env_name: "SUPPLY_TIMEOUT",
|
@@ -227,16 +261,18 @@ module Supply
|
|
227
261
|
env_name: "SUPPLY_DEACTIVATE_ON_PROMOTE",
|
228
262
|
optional: true,
|
229
263
|
description: "When promoting to a new track, deactivate the binary in the origin track",
|
230
|
-
|
264
|
+
deprecated: "Google Play does this automatically now",
|
265
|
+
type: Boolean,
|
231
266
|
default_value: true),
|
232
267
|
FastlaneCore::ConfigItem.new(key: :version_codes_to_retain,
|
233
268
|
optional: true,
|
234
269
|
type: Array,
|
235
270
|
description: "An array of version codes to retain when publishing a new APK",
|
236
271
|
verify_block: proc do |version_codes|
|
272
|
+
version_codes = version_codes.map(&:to_i)
|
237
273
|
UI.user_error!("Could not evaluate array from '#{version_codes}'") unless version_codes.kind_of?(Array)
|
238
274
|
version_codes.each do |version_code|
|
239
|
-
UI.user_error!("Version code '#{version_code}' is not an integer")
|
275
|
+
UI.user_error!("Version code '#{version_code}' is not an integer") if version_code == 0
|
240
276
|
end
|
241
277
|
end),
|
242
278
|
FastlaneCore::ConfigItem.new(key: :obb_main_references_version,
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Supply
|
2
|
+
class ReleaseListing
|
3
|
+
attr_accessor :track
|
4
|
+
attr_accessor :version
|
5
|
+
attr_accessor :versioncodes
|
6
|
+
attr_accessor :language
|
7
|
+
attr_accessor :release_notes
|
8
|
+
|
9
|
+
# Initializes the release listing with the current listing if available
|
10
|
+
def initialize(track, version, versioncodes, language, text)
|
11
|
+
self.track = track
|
12
|
+
self.version = version
|
13
|
+
self.versioncodes = versioncodes
|
14
|
+
self.language = language
|
15
|
+
self.release_notes = text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/supply/lib/supply/setup.rb
CHANGED
@@ -12,16 +12,22 @@ module Supply
|
|
12
12
|
|
13
13
|
client.listings.each do |listing|
|
14
14
|
store_metadata(listing)
|
15
|
-
create_screenshots_folder(listing)
|
16
15
|
download_images(listing)
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
client.
|
21
|
-
|
18
|
+
if Supply.config[:version_name].to_s == ""
|
19
|
+
latest_version = client.latest_version(Supply.config[:track])
|
20
|
+
if latest_version
|
21
|
+
Supply.config[:version_name] = latest_version.name
|
22
|
+
else
|
23
|
+
UI.user_error!("Could not find the latest version to download metadata, images, and screenshots from")
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
27
|
+
client.release_listings(Supply.config[:version_name]).each do |release_listing|
|
28
|
+
store_release_listing(release_listing)
|
29
|
+
end
|
30
|
+
|
25
31
|
client.abort_current_edit
|
26
32
|
|
27
33
|
UI.success("✅ Successfully stored metadata in '#{metadata_path}'")
|
@@ -43,25 +49,40 @@ module Supply
|
|
43
49
|
def download_images(listing)
|
44
50
|
UI.message("🖼️ Downloading images (#{listing.language})")
|
45
51
|
|
46
|
-
# We cannot download existing screenshots as they are compressed
|
47
|
-
# But we can at least download the images
|
48
52
|
require 'net/http'
|
49
53
|
|
50
|
-
IMAGES_TYPES.
|
51
|
-
if ['featureGraphic'].include?(image_type)
|
52
|
-
# we don't get all files in full resolution :(
|
53
|
-
UI.message("📵 Due to a limitation of the Google Play API, there is no way for `supply` to download your existing feature graphic. Please copy your feature graphic to `metadata/android/#{listing.language}/images/featureGraphic.png`")
|
54
|
-
next
|
55
|
-
end
|
54
|
+
allowed_imagetypes = [Supply::IMAGES_TYPES, Supply::SCREENSHOT_TYPES].flatten
|
56
55
|
|
56
|
+
allowed_imagetypes.each do |image_type|
|
57
57
|
begin
|
58
|
+
path = File.join(metadata_path, listing.language, IMAGES_FOLDER_NAME, image_type)
|
59
|
+
|
60
|
+
p = Pathname.new(path)
|
61
|
+
if IMAGES_TYPES.include?(image_type) # IMAGE_TYPES are stored in locale/images location
|
62
|
+
FileUtils.mkdir_p(p.dirname.to_s)
|
63
|
+
else # SCREENSHOT_TYPES go under their respective folders.
|
64
|
+
FileUtils.mkdir_p(p.to_s)
|
65
|
+
end
|
66
|
+
|
58
67
|
UI.message("Downloading `#{image_type}` for #{listing.language}...")
|
59
68
|
|
60
|
-
|
61
|
-
next
|
69
|
+
urls = client.fetch_images(image_type: image_type, language: listing.language)
|
70
|
+
next if urls.nil? || urls.empty?
|
71
|
+
|
72
|
+
image_counter = 1 # Used to prefix the downloaded files, so order is preserved.
|
73
|
+
urls.each do |url|
|
74
|
+
if IMAGES_TYPES.include?(image_type) # IMAGE_TYPES are stored in locale/images
|
75
|
+
file_path = "#{path}.#{FastImage.type(url)}"
|
76
|
+
else # SCREENSHOT_TYPES are stored in locale/images/<screensho_types>
|
77
|
+
file_path = File.join(path, "#{image_counter}_#{listing.language}.#{FastImage.type(url)}")
|
78
|
+
end
|
79
|
+
|
80
|
+
File.binwrite(file_path, Net::HTTP.get(URI.parse(url)))
|
81
|
+
|
82
|
+
UI.message("\tDownloaded - #{file_path}")
|
62
83
|
|
63
|
-
|
64
|
-
|
84
|
+
image_counter += 1
|
85
|
+
end
|
65
86
|
rescue => ex
|
66
87
|
UI.error(ex.to_s)
|
67
88
|
UI.error("Error downloading '#{image_type}' for #{listing.language}...")
|
@@ -69,30 +90,17 @@ module Supply
|
|
69
90
|
end
|
70
91
|
end
|
71
92
|
|
72
|
-
def
|
73
|
-
UI.message("
|
74
|
-
|
75
|
-
containing = File.join(metadata_path, listing.language)
|
76
|
-
|
77
|
-
FileUtils.mkdir_p(File.join(containing, IMAGES_FOLDER_NAME))
|
78
|
-
Supply::SCREENSHOT_TYPES.each do |screenshot_type|
|
79
|
-
FileUtils.mkdir_p(File.join(containing, IMAGES_FOLDER_NAME, screenshot_type))
|
80
|
-
end
|
81
|
-
|
82
|
-
UI.message("📵 Due to a limitation of the Google Play API, there is no way for `supply` to download your existing screenshots. Please copy your screenshots into `metadata/android/#{listing.language}/images/`")
|
83
|
-
end
|
84
|
-
|
85
|
-
def store_apk_listing(apk_listing)
|
86
|
-
UI.message("🔨 Downloading changelogs (#{apk_listing.language}, #{apk_listing.apk_version_code})")
|
93
|
+
def store_release_listing(release_listing)
|
94
|
+
UI.message("🔨 Downloading changelogs (#{release_listing.language}, #{release_listing.version})")
|
87
95
|
|
88
|
-
containing = File.join(metadata_path,
|
96
|
+
containing = File.join(metadata_path, release_listing.language, CHANGELOGS_FOLDER_NAME)
|
89
97
|
unless File.exist?(containing)
|
90
98
|
FileUtils.mkdir_p(containing)
|
91
99
|
end
|
92
100
|
|
93
|
-
path = File.join(containing, "#{
|
101
|
+
path = File.join(containing, "#{release_listing.version}.txt")
|
94
102
|
UI.message("Writing to #{path}...")
|
95
|
-
File.write(path,
|
103
|
+
File.write(path, release_listing.release_notes)
|
96
104
|
end
|
97
105
|
|
98
106
|
private
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Supply
|
2
|
+
# rubocop:disable Metrics/ClassLength
|
2
3
|
class Uploader
|
3
4
|
def perform_upload
|
4
5
|
FastlaneCore::PrintTable.print_values(config: Supply.config, hide_keys: [:issuer], mask_keys: [:json_key_data], title: "Summary for supply #{Fastlane::VERSION}")
|
@@ -7,22 +8,6 @@ module Supply
|
|
7
8
|
|
8
9
|
verify_config!
|
9
10
|
|
10
|
-
if metadata_path
|
11
|
-
UI.user_error!("Could not find folder #{metadata_path}") unless File.directory?(metadata_path)
|
12
|
-
|
13
|
-
all_languages.each do |language|
|
14
|
-
next if language.start_with?('.') # e.g. . or .. or hidden folders
|
15
|
-
UI.message("Preparing to upload for language '#{language}'...")
|
16
|
-
|
17
|
-
listing = client.listing_for_language(language)
|
18
|
-
|
19
|
-
upload_metadata(language, listing) unless Supply.config[:skip_upload_metadata]
|
20
|
-
upload_images(language) unless Supply.config[:skip_upload_images]
|
21
|
-
upload_screenshots(language) unless Supply.config[:skip_upload_screenshots]
|
22
|
-
upload_changelogs(language) unless Supply.config[:skip_upload_metadata]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
11
|
apk_version_codes = []
|
27
12
|
apk_version_codes.concat(upload_apks) unless Supply.config[:skip_upload_apk]
|
28
13
|
apk_version_codes.concat(upload_bundles) unless Supply.config[:skip_upload_aab]
|
@@ -34,19 +19,102 @@ module Supply
|
|
34
19
|
# Updating a track with empty version codes can completely clear out a track
|
35
20
|
update_track(apk_version_codes) unless apk_version_codes.empty?
|
36
21
|
|
22
|
+
if !Supply.config[:rollout].nil? && Supply.config[:track].to_s != ""
|
23
|
+
update_rollout
|
24
|
+
end
|
25
|
+
|
37
26
|
promote_track if Supply.config[:track_promote_to]
|
38
27
|
|
39
28
|
if Supply.config[:validate_only]
|
40
|
-
UI.message("Validating all changes with Google Play...")
|
29
|
+
UI.message("Validating all track and release changes with Google Play...")
|
30
|
+
client.validate_current_edit!
|
31
|
+
UI.success("Successfully validated the upload to Google Play")
|
32
|
+
else
|
33
|
+
UI.message("Uploading all track and release changes to Google Play...")
|
34
|
+
client.commit_current_edit!
|
35
|
+
UI.success("Successfully finished the upload to Google Play")
|
36
|
+
end
|
37
|
+
|
38
|
+
perform_upload_meta(apk_version_codes)
|
39
|
+
end
|
40
|
+
|
41
|
+
def perform_upload_meta(version_codes)
|
42
|
+
client.begin_edit(package_name: Supply.config[:package_name])
|
43
|
+
|
44
|
+
if (!Supply.config[:skip_upload_metadata] || !Supply.config[:skip_upload_images] || !Supply.config[:skip_upload_changelogs] || !Supply.config[:skip_upload_screenshots]) && metadata_path
|
45
|
+
version_codes = [Supply.config[:version_code]] if version_codes.empty?
|
46
|
+
version_codes.each do |version_code|
|
47
|
+
UI.user_error!("Could not find folder #{metadata_path}") unless File.directory?(metadata_path)
|
48
|
+
|
49
|
+
track, release = fetch_track_and_release!(Supply.config[:track], version_code)
|
50
|
+
UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track
|
51
|
+
UI.user_error!("Could not find release for version code '#{version_code}' to update changelog") unless release
|
52
|
+
|
53
|
+
release_notes = []
|
54
|
+
all_languages.each do |language|
|
55
|
+
next if language.start_with?('.') # e.g. . or .. or hidden folders
|
56
|
+
UI.message("Preparing to upload for language '#{language}'...")
|
57
|
+
|
58
|
+
listing = client.listing_for_language(language)
|
59
|
+
|
60
|
+
upload_metadata(language, listing) unless Supply.config[:skip_upload_metadata]
|
61
|
+
upload_images(language) unless Supply.config[:skip_upload_images]
|
62
|
+
upload_screenshots(language) unless Supply.config[:skip_upload_screenshots]
|
63
|
+
release_notes << upload_changelog(language, release.name) unless Supply.config[:skip_upload_changelogs]
|
64
|
+
end
|
65
|
+
|
66
|
+
upload_changelogs(release_notes, release, track) unless release_notes.empty?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if Supply.config[:validate_only]
|
71
|
+
UI.message("Validating all meta changes with Google Play...")
|
41
72
|
client.validate_current_edit!
|
42
73
|
UI.success("Successfully validated the upload to Google Play")
|
43
74
|
else
|
44
|
-
UI.message("Uploading all changes to Google Play...")
|
75
|
+
UI.message("Uploading all meta changes to Google Play...")
|
45
76
|
client.commit_current_edit!
|
46
77
|
UI.success("Successfully finished the upload to Google Play")
|
47
78
|
end
|
48
79
|
end
|
49
80
|
|
81
|
+
def fetch_track_and_release!(track, version_code, status = nil)
|
82
|
+
tracks = client.tracks(track)
|
83
|
+
return nil, nil if tracks.empty?
|
84
|
+
|
85
|
+
track = tracks.first
|
86
|
+
releases = track.releases
|
87
|
+
releases = releases.select { |r| r.status == status } if status
|
88
|
+
releases = releases.select { |r| r.version_codes.map(&:to_s).include?(version_code.to_s) }
|
89
|
+
|
90
|
+
if releases.size > 1
|
91
|
+
UI.user_error!("More than one release found in this track. Please specify with the :version_code option to select a release.")
|
92
|
+
end
|
93
|
+
|
94
|
+
return track, releases.first
|
95
|
+
end
|
96
|
+
|
97
|
+
def update_rollout
|
98
|
+
track, release = fetch_track_and_release!(Supply.config[:track], Supply.config[:version_code], Supply::ReleaseStatus::IN_PROGRESS)
|
99
|
+
version_code = release.version_codes.first
|
100
|
+
|
101
|
+
UI.message("Updating #{version_code}'s rollout to '#{Supply.config[:rollout]}' on track '#{Supply.config[:track]}'...")
|
102
|
+
UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track
|
103
|
+
|
104
|
+
if track && release
|
105
|
+
completed = Supply.config[:rollout].to_f == 1
|
106
|
+
release.user_fraction = completed ? nil : Supply.config[:rollout]
|
107
|
+
release.status = Supply::ReleaseStatus::COMPLETED if completed
|
108
|
+
|
109
|
+
# Deleted other version codes if completed because only allowed on completed version in a release
|
110
|
+
track.releases.delete_if { |r| !(r.version_codes || []).map(&:to_s).include?(version_code) } if completed
|
111
|
+
else
|
112
|
+
UI.user_error!("Unable to find version to rollout in track '#{Supply.config[:track]}'")
|
113
|
+
end
|
114
|
+
|
115
|
+
client.update_track(Supply.config[:track], track)
|
116
|
+
end
|
117
|
+
|
50
118
|
def verify_config!
|
51
119
|
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])
|
52
120
|
UI.user_error!("No local metadata, apks, aab, or track to promote were found, make sure to run `fastlane supply init` to setup supply")
|
@@ -60,32 +128,73 @@ module Supply
|
|
60
128
|
if could_upload_apk && could_upload_aab
|
61
129
|
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")
|
62
130
|
end
|
131
|
+
|
132
|
+
if Supply.config[:release_status] == Supply::ReleaseStatus::DRAFT && Supply.config[:rollout]
|
133
|
+
UI.user_error!(%(Cannot specify rollout percentage when the release status is set to 'draft'))
|
134
|
+
end
|
135
|
+
|
136
|
+
unless Supply.config[:version_codes_to_retain].nil?
|
137
|
+
Supply.config[:version_codes_to_retain] = Supply.config[:version_codes_to_retain].map(&:to_i)
|
138
|
+
end
|
63
139
|
end
|
64
140
|
|
65
141
|
def promote_track
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
142
|
+
track_from = client.tracks(Supply.config[:track]).first
|
143
|
+
unless track_from
|
144
|
+
UI.user_error!("Cannot promote from track '#{Supply.config[:track]}' - track doesn't exist")
|
145
|
+
end
|
146
|
+
|
147
|
+
releases = track_from.releases
|
148
|
+
if Supply.config[:version_code].to_s != ""
|
149
|
+
releases = releases.select do |release|
|
150
|
+
release.version_codes.include?(Supply.config[:version_code].to_s)
|
151
|
+
end
|
152
|
+
end
|
72
153
|
|
73
|
-
|
74
|
-
|
75
|
-
|
154
|
+
if releases.size == 0
|
155
|
+
UI.user_error!("Track '#{Supply.config[:track]}' doesn't have any releases")
|
156
|
+
elsif releases.size > 1
|
157
|
+
UI.user_error!("Track '#{Supply.config[:track]}' has more than one release - use :version_code to filter the release to promote")
|
76
158
|
end
|
77
|
-
|
78
|
-
|
159
|
+
|
160
|
+
release = track_from.releases.first
|
161
|
+
track_to = client.tracks(Supply.config[:track_promote_to]).first
|
162
|
+
|
163
|
+
if track_to
|
164
|
+
# Its okay to set releases to an array containing the newest release
|
165
|
+
# Google Play will keep previous releases there this release is a partial rollout
|
166
|
+
track_to.releases = [release]
|
167
|
+
else
|
168
|
+
track_to = AndroidPublisher::Track.new(
|
169
|
+
track: Supply.config[:track_promote_to],
|
170
|
+
releases: [release]
|
171
|
+
)
|
79
172
|
end
|
173
|
+
|
174
|
+
client.update_track(Supply.config[:track_promote_to], track_to)
|
80
175
|
end
|
81
176
|
|
82
|
-
def upload_changelog(language,
|
83
|
-
|
177
|
+
def upload_changelog(language, version_name)
|
178
|
+
UI.user_error!("Cannot find changelog because no version name given - please specify :version_name") unless version_name
|
179
|
+
|
180
|
+
path = File.join(Supply.config[:metadata_path], language, Supply::CHANGELOGS_FOLDER_NAME, "#{version_name}.txt")
|
181
|
+
changelog_text = ''
|
84
182
|
if File.exist?(path)
|
85
|
-
UI.message("Updating changelog for
|
86
|
-
|
87
|
-
|
183
|
+
UI.message("Updating changelog for '#{version_name}' and language '#{language}'...")
|
184
|
+
changelog_text = File.read(path, encoding: 'UTF-8')
|
185
|
+
else
|
186
|
+
UI.message("Could not find changelog for '#{version_name}' and language '#{language}' at path #{path}...")
|
88
187
|
end
|
188
|
+
|
189
|
+
AndroidPublisher::LocalizedText.new({
|
190
|
+
language: language,
|
191
|
+
text: changelog_text
|
192
|
+
})
|
193
|
+
end
|
194
|
+
|
195
|
+
def upload_changelogs(release_notes, release, track)
|
196
|
+
release.release_notes = release_notes
|
197
|
+
client.upload_changelogs(track, Supply.config[:track])
|
89
198
|
end
|
90
199
|
|
91
200
|
def upload_metadata(language, listing)
|
@@ -163,14 +272,6 @@ module Supply
|
|
163
272
|
aab_paths.each do |aab_path|
|
164
273
|
UI.message("Preparing aab at path '#{aab_path}' for upload...")
|
165
274
|
bundle_version_code = client.upload_bundle(aab_path)
|
166
|
-
|
167
|
-
if metadata_path
|
168
|
-
all_languages.each do |language|
|
169
|
-
next if language.start_with?('.') # e.g. . or .. or hidden folders
|
170
|
-
upload_changelog(language, bundle_version_code)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
275
|
aab_version_codes.push(bundle_version_code)
|
175
276
|
end
|
176
277
|
|
@@ -188,6 +289,7 @@ module Supply
|
|
188
289
|
# @return [Integer] The apk version code returned after uploading, or nil if there was a problem
|
189
290
|
def upload_binary_data(apk_path)
|
190
291
|
apk_version_code = nil
|
292
|
+
|
191
293
|
if apk_path
|
192
294
|
UI.message("Preparing apk at path '#{apk_path}' for upload...")
|
193
295
|
apk_version_code = client.upload_apk(apk_path)
|
@@ -208,16 +310,11 @@ module Supply
|
|
208
310
|
end
|
209
311
|
|
210
312
|
upload_obbs(apk_path, apk_version_code)
|
211
|
-
|
212
|
-
if metadata_path
|
213
|
-
all_languages.each do |language|
|
214
|
-
next if language.start_with?('.') # e.g. . or .. or hidden folders
|
215
|
-
upload_changelog(language, apk_version_code)
|
216
|
-
end
|
217
|
-
end
|
218
313
|
else
|
219
314
|
UI.message("No apk file found, you can pass the path to your apk using the `apk` option")
|
220
315
|
end
|
316
|
+
|
317
|
+
UI.message("\tVersion Code: #{apk_version_code}")
|
221
318
|
apk_version_code
|
222
319
|
end
|
223
320
|
|
@@ -230,55 +327,35 @@ module Supply
|
|
230
327
|
end
|
231
328
|
|
232
329
|
def update_track(apk_version_codes)
|
233
|
-
|
234
|
-
check_superseded_tracks(apk_version_codes) if Supply.config[:check_superseded_tracks]
|
235
|
-
|
236
|
-
if Supply.config[:track].eql?("rollout")
|
237
|
-
client.update_track(Supply.config[:track], Supply.config[:rollout] || 0.1, apk_version_codes)
|
238
|
-
else
|
239
|
-
client.update_track(Supply.config[:track], 1.0, apk_version_codes)
|
240
|
-
end
|
241
|
-
end
|
330
|
+
return if apk_version_codes.empty?
|
242
331
|
|
243
|
-
|
244
|
-
# - Lesser than the greatest of any later (i.e. production) track
|
245
|
-
# - Or lesser than the currently being uploaded if it's in an earlier (i.e. alpha) track
|
246
|
-
def check_superseded_tracks(apk_version_codes)
|
247
|
-
UI.message("Checking superseded tracks, uploading '#{apk_version_codes}' to '#{Supply.config[:track]}'...")
|
248
|
-
max_apk_version_code = apk_version_codes.max
|
249
|
-
max_tracks_version_code = nil
|
250
|
-
|
251
|
-
tracks = ["production", "rollout", "beta", "alpha", "internal"]
|
252
|
-
config_track_index = tracks.index(Supply.config[:track])
|
253
|
-
|
254
|
-
# Custom "closed" tracks are now allowed (https://support.google.com/googleplay/android-developer/answer/3131213)
|
255
|
-
# Custom tracks have an equal level with alpha (alpha is considered a closed track as well)
|
256
|
-
# If a track index is not found, we will assume is a custom track so an alpha index is given
|
257
|
-
config_track_index = tracks.index("alpha") unless config_track_index
|
258
|
-
|
259
|
-
tracks.each_index do |track_index|
|
260
|
-
track = tracks[track_index]
|
261
|
-
track_version_codes = client.track_version_codes(track).sort
|
262
|
-
UI.verbose("Found '#{track_version_codes}' on track '#{track}'")
|
263
|
-
|
264
|
-
next if track_index.eql?(config_track_index)
|
265
|
-
next if track_version_codes.empty?
|
266
|
-
|
267
|
-
if max_tracks_version_code.nil?
|
268
|
-
max_tracks_version_code = track_version_codes.max
|
269
|
-
end
|
332
|
+
UI.message("Updating track '#{Supply.config[:track]}'...")
|
270
333
|
|
271
|
-
|
272
|
-
|
273
|
-
|
334
|
+
track_release = AndroidPublisher::TrackRelease.new(
|
335
|
+
name: Supply.config[:version_name],
|
336
|
+
status: Supply.config[:release_status],
|
337
|
+
version_codes: apk_version_codes
|
338
|
+
)
|
274
339
|
|
275
|
-
|
340
|
+
if Supply.config[:rollout]
|
341
|
+
track_release.status = Supply::ReleaseStatus::IN_PROGRESS
|
342
|
+
track_release.user_fraction = Supply.config[:rollout].to_f
|
343
|
+
end
|
276
344
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
345
|
+
tracks = client.tracks(Supply.config[:track])
|
346
|
+
track = tracks.first
|
347
|
+
if track
|
348
|
+
# Its okay to set releases to an array containing the newest release
|
349
|
+
# Google Play will keep previous releases there this release is a partial rollout
|
350
|
+
track.releases = [track_release]
|
351
|
+
else
|
352
|
+
track = AndroidPublisher::Track.new(
|
353
|
+
track: Supply.config[:track],
|
354
|
+
releases: [track_release]
|
355
|
+
)
|
281
356
|
end
|
357
|
+
|
358
|
+
client.update_track(Supply.config[:track], track)
|
282
359
|
end
|
283
360
|
|
284
361
|
# returns only language directories from metadata_path
|
@@ -346,4 +423,5 @@ module Supply
|
|
346
423
|
end
|
347
424
|
end
|
348
425
|
end
|
426
|
+
# rubocop:enable Metrics/ClassLength
|
349
427
|
end
|