deliver/lib/deliver/loader.rb in fastlane_hotfix-2.165.1 vs deliver/lib/deliver/loader.rb in fastlane_hotfix-2.187.0
- old
+ new
@@ -1,9 +1,8 @@
-require 'fastlane_core/languages'
-require 'spaceship/tunes/tunes'
-
require_relative 'module'
+require_relative 'app_screenshot'
+require_relative 'app_screenshot_validator'
require_relative 'upload_metadata'
require_relative 'languages'
module Deliver
module Loader
@@ -11,43 +10,146 @@
# through it as well searching for language folders.
APPLE_TV_DIR_NAME = "appleTV".freeze
IMESSAGE_DIR_NAME = "iMessage".freeze
DEFAULT_DIR_NAME = "default".freeze
+ EXPANDABLE_DIR_NAMES = [APPLE_TV_DIR_NAME, IMESSAGE_DIR_NAME].freeze
SPECIAL_DIR_NAMES = [APPLE_TV_DIR_NAME, IMESSAGE_DIR_NAME, DEFAULT_DIR_NAME].freeze
# Some exception directories may exist from other actions that should not be iterated through
SUPPLY_DIR_NAME = "android".freeze
FRAMEIT_FONTS_DIR_NAME = "fonts".freeze
META_DIR_NAMES = UploadMetadata::ALL_META_SUB_DIRS.map(&:downcase)
- EXCEPTION_DIRECTORIES = (META_DIR_NAMES << SUPPLY_DIR_NAME << FRAMEIT_FONTS_DIR_NAME).freeze
+ EXCEPTION_DIRECTORIES = (META_DIR_NAMES << SUPPLY_DIR_NAME << FRAMEIT_FONTS_DIR_NAME).freeze
- def self.language_folders(root, ignore_validation)
- folders = Dir.glob(File.join(root, '*'))
+ # A class that represents language folder under screenshots or metadata folder
+ class LanguageFolder
+ attr_reader :path
- # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
- # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
- available_languages = Deliver::Languages::ALL_LANGUAGES
+ # @return [String] A normalized language name that corresponds to the directory's name
+ attr_reader :language
- allowed_directory_names_with_case = (available_languages + SPECIAL_DIR_NAMES)
- allowed_directory_names = allowed_directory_names_with_case.map(&:downcase).freeze
+ def self.available_languages
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
+ Deliver::Languages::ALL_LANGUAGES
+ end
- selected_folders = folders.select do |path|
- File.directory?(path) && allowed_directory_names.include?(File.basename(path).downcase)
- end.sort
+ def self.allowed_directory_names_with_case
+ available_languages + SPECIAL_DIR_NAMES
+ end
- # Gets list of folders that are not supported languages
- rejected_folders = folders.select do |path|
- normalized_path = File.basename(path).downcase
- File.directory?(path) && !allowed_directory_names.include?(normalized_path) && !EXCEPTION_DIRECTORIES.include?(normalized_path)
- end.sort
+ # @param path [String] A directory path otherwise this initializer fails
+ # @param nested [Boolan] Whether given path is nested of another special directory.
+ # This affects `expandable?` to return `false` when this set to `true`.
+ def initialize(path, nested: false)
+ raise(ArgumentError, "Given path must be a directory path - #{path}") unless File.directory?(path)
+ @path = path
+ @language = self.class.available_languages.find { |lang| basename.casecmp?(lang) }
+ @nested = nested
+ end
+ def nested?
+ @nested
+ end
+
+ def valid?
+ self.class.allowed_directory_names_with_case.any? { |name| name.casecmp?(basename) }
+ end
+
+ def expandable?
+ !nested? && EXPANDABLE_DIR_NAMES.any? { |name| name.casecmp?(basename) }
+ end
+
+ def skip?
+ EXCEPTION_DIRECTORIES.map(&:downcase).include?(basename.downcase)
+ end
+
+ def file_paths(extensions = '{png,jpg,jpeg}')
+ Dir.glob(File.join(path, "*.#{extensions}"), File::FNM_CASEFOLD).sort
+ end
+
+ def framed_file_paths(extensions = '{png,jpg,jpeg}')
+ Dir.glob(File.join(path, "*_framed.#{extensions}"), File::FNM_CASEFOLD).sort
+ end
+
+ def basename
+ File.basename(@path)
+ end
+ end
+
+ # Returns the list of valid app screenshot. When detecting invalid screenshots, this will cause an error.
+ #
+ # @param root [String] A directory path
+ # @param ignore_validation [String] Set false not to raise the error when finding invalid folder name
+ # @return [Array<AppScreenshot>] The list of AppScreenshot that exist under given `root` directory
+ def self.load_app_screenshots(root, ignore_validation)
+ screenshots = language_folders(root, ignore_validation, true).flat_map do |language_folder|
+ paths = if language_folder.framed_file_paths.count > 0
+ UI.important("Framed screenshots are detected! 🖼 Non-framed screenshot files may be skipped. 🏃")
+ # watchOS screenshots can be picked up even when framed ones were found since frameit doesn't support watchOS screenshots
+ framed_or_watch, skipped = language_folder.file_paths.partition { |path| path.downcase.include?('framed') || path.downcase.include?('watch') }
+ skipped.each { |path| UI.important("🏃 Skipping screenshot file: #{path}") }
+ framed_or_watch
+ else
+ language_folder.file_paths
+ end
+ paths.map { |path| AppScreenshot.new(path, language_folder.language) }
+ end
+
+ errors = []
+ valid_screenshots = screenshots.select { |screenshot| Deliver::AppScreenshotValidator.validate(screenshot, errors) }
+
+ errors_to_skip, errors_to_crash = errors.partition(&:to_skip)
+
+ unless errors_to_skip.empty?
+ UI.important("🏃 Screenshots to be skipped are detected!")
+ errors_to_skip.each { |error| UI.message(error) }
+ end
+
+ unless errors_to_crash.empty?
+ UI.important("🚫 Invalid screenshots were detected! Here are the reasons:")
+ errors_to_crash.each { |error| UI.error(error) }
+ UI.user_error!("Canceled uploading screenshots. Please check the error messages above and fix the screenshots.")
+ end
+
+ valid_screenshots
+ end
+
+ # Returns the list of language folders
+ #
+ # @param roort [String] A directory path to get the list of language folders
+ # @param ignore_validation [Boolean] Set false not to raise the error when finding invalid folder name
+ # @param expand_sub_folders [Boolean] Set true to expand special folders; such as "iMessage" to nested language folders
+ # @return [Array<LanguageFolder>] The list of LanguageFolder whose each of them
+ def self.language_folders(root, ignore_validation, expand_sub_folders = false)
+ folders = Dir.glob(File.join(root, '*'))
+ .select { |path| File.directory?(path) }
+ .map { |path| LanguageFolder.new(path, nested: false) }
+ .reject(&:skip?)
+
+ selected_folders, rejected_folders = folders.partition(&:valid?)
+
if !ignore_validation && !rejected_folders.empty?
- rejected_folders = rejected_folders.map { |path| File.basename(path) }
+ rejected_folders = rejected_folders.map(&:basename)
UI.user_error!("Unsupported directory name(s) for screenshots/metadata in '#{root}': #{rejected_folders.join(', ')}" \
- "\nValid directory names are: #{allowed_directory_names_with_case}" \
+ "\nValid directory names are: #{LanguageFolder.allowed_directory_names_with_case}" \
"\n\nEnable 'ignore_language_directory_validation' to prevent this validation from happening")
+ end
+
+ # Expand selected_folders for the special directories
+ if expand_sub_folders
+ selected_folders = selected_folders.flat_map do |folder|
+ if folder.expandable?
+ Dir.glob(File.join(folder.path, '*'))
+ .select { |p| File.directory?(p) }
+ .map { |p| LanguageFolder.new(p, nested: true) }
+ .select(&:valid?)
+ else
+ folder
+ end
+ end
end
selected_folders
end
end