diff --git a/proguard/rules/androidx_security.pro b/proguard/rules/androidx_security.pro new file mode 100644 index 0000000..0ceafee --- /dev/null +++ b/proguard/rules/androidx_security.pro @@ -0,0 +1,3 @@ +-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite { + ; +} diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index d502145..8e71145 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -241,7 +241,7 @@ custom_rules: redundant_type_annotation_bool: name: "Redundant type annotation for Bool" - regex: '((var|let)) *\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' + regex: '\s((var|let))\s{1,}\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' message: "Using a type annotation for Bool is redundant." severity: error diff --git a/xcode/build_phases/documentation_generator.sh b/xcode/build_phases/documentation_generator.sh index a5449b7..ffd4828 100644 --- a/xcode/build_phases/documentation_generator.sh +++ b/xcode/build_phases/documentation_generator.sh @@ -1 +1,2 @@ -. build-scripts/xcode/aux_scripts/certificates_readme_generator.sh > $PROJECT_DIR/Certificates/README.md \ No newline at end of file +readonly BUILD_SCRIPTS_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR +. $BUILD_SCRIPTS_DIR/build-scripts/xcode/aux_scripts/certificates_readme_generator.sh > $PROJECT_DIR/Certificates/README.md diff --git a/xcode/build_phases/multiple_swiftlint/array_extension.rb b/xcode/build_phases/multiple_swiftlint/array_extension.rb new file mode 100644 index 0000000..e5bebf6 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/array_extension.rb @@ -0,0 +1,5 @@ +class Array + def nilOrEmpty? + self.nil? or self.empty? + end +end diff --git a/xcode/build_phases/multiple_swiftlint/command_utils.rb b/xcode/build_phases/multiple_swiftlint/command_utils.rb new file mode 100644 index 0000000..cf12d07 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/command_utils.rb @@ -0,0 +1,6 @@ +class CommandUtils + def self.make_command(command) + command = command.to_s + return `#{command}` + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/git_caretaker.rb b/xcode/build_phases/multiple_swiftlint/git_caretaker.rb new file mode 100644 index 0000000..323464a --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/git_caretaker.rb @@ -0,0 +1,35 @@ +require_relative 'array_extension.rb' +require_relative 'command_utils.rb' +require_relative 'string_extension.rb' + +class GitСaretaker < CommandUtils + def self.get_modified_files + non_indexed_files = get_files_from('git diff --name-only | sed s/.*/"&,"/ ') + indexed_files = get_files_from('git diff --cached --name-only | sed s/.*/"&,"/ ') + + modified_files = non_indexed_files + indexed_files + unique_modified_files = modified_files.uniq + + unique_modified_swift_files = [] + if not unique_modified_files.nilOrEmpty? + unique_modified_swift_files = unique_modified_files.select { |file_path| + file_path.to_s.filter_allowed_symbol_into_path + file_path.to_s.include? '.swift' + } + end + + return unique_modified_swift_files + end + + def self.get_creation_date(file_path) + git_command = 'git log --follow --format=%cD --reverse -- ' + file_path + ' | head -1' + return make_command(git_command) + end + + private + + def self.get_files_from(command) + files_as_string = make_command(command) + return files_as_string.split(',') + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb new file mode 100644 index 0000000..44b8d7e --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -0,0 +1,65 @@ +require 'optparse' +require 'ostruct' + +require_relative 'array_extension.rb' + +class SettingOption + def initialize + @options = OpenStruct.new + OptionParser.new do |opt| + opt.on('-p', '--project_root_path STRING', 'The path of project directory and contains *.xcodeproj file always. ' + + 'Example: project_root_path=~/Projects/MyProject/Source/..') { |option| @options.project_root_path = option } + opt.on('-r', '--source_root_path STRING', 'The path of source directory and may not contains *.xcodeproj file in some cases. ' + + 'Example: source_root_path=~/Projects/MyProject/') { |option| @options.source_root_path = option } + opt.on('-s', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } + opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } + opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } + opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } + opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } + end.parse! + + if @options.check_mode.to_s.nilOrEmpty? + @options.check_mode = 'fully' + end + + if @options.use_multiple.to_s.nilOrEmpty? + @options.use_multiple = 'false' + end + + if @options.source_root_path.to_s.nilOrEmpty? + @options.source_root_path = @options.project_root_path + end + + if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? + @options.touchin_swiftlint_yaml_path = '/build-scripts/xcode/.swiftlint.yml' + end + end + + def project_root_path + @options.project_root_path + end + + def source_date + @options.source_date + end + + def swiftlint_executable_path + @options.swiftlint_executable_path + end + + def check_mode + @options.check_mode + end + + def use_multiple + @options.use_multiple + end + + def source_root_path + @options.source_root_path + end + + def touchin_swiftlint_yaml_path + @options.touchin_swiftlint_yaml_path + end +end diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb new file mode 100644 index 0000000..a677892 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -0,0 +1,160 @@ +require 'fileutils' + +require_relative 'array_extension.rb' +require_relative 'git_caretaker.rb' +require_relative 'string_extension.rb' +require_relative 'swift_file_manager.rb' +require_relative 'yaml_manager.rb' + +class StrategyMaker + def initialize(project_root_path, swiftlint_executable_path, touchin_swiftlint_yaml_path) + @project_root_path = project_root_path + @touchin_swiftlint_yaml_path = project_root_path + touchin_swiftlint_yaml_path + @old_swiftlint_yaml_path = project_root_path + '/.swiftlint.yml' + + @temporary_swiftlint_folder_name = project_root_path + '/temporary_swiftlint' + @touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml' + @old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml' + + @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_root_path + ' --config ' + @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_root_path + ' --config ' + end + + def run_fully_multiple_strategy(source_date) + create_yaml_managers_and_copy_temporary_files + + exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) + + swift_files = SwiftFileManager.new(exclude_files, source_date) + swift_files.find_list_file_paths(@project_root_path) + + total_touchin_excluded_files = exclude_files + swift_files.old_files + total_old_excluded_files = exclude_files + swift_files.new_files + + @touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files) + @old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files) + + run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + end + + def run_simplified_multiple_strategy(source_date, source_root_path) + included_files = GitСaretaker.get_modified_files + + if included_files.nilOrEmpty? + puts 'Git did not found swift files to check' + return + end + + create_yaml_managers_and_copy_temporary_files + + exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) + included_files = included_files.map { |file_path| source_root_path + file_path } + + swift_file_manager = SwiftFileManager.new(exclude_files, source_date) + swift_file_manager.find_list_file_paths_from(included_files) + + total_touchin_included_files = swift_file_manager.new_files + total_old_included_files = swift_file_manager.old_files + + @touchin_swiftlint_yaml_manager.update('excluded', []) + @old_swiftlint_yaml_manager.update('excluded', []) + + @touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files) + @old_swiftlint_yaml_manager.update('included', total_old_included_files) + + is_exist_total_touchin_included_files = (not total_touchin_included_files.nilOrEmpty?) + is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?) + + if is_exist_total_touchin_included_files and is_exist_total_old_included_files + run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + elsif is_exist_total_touchin_included_files and not is_exist_total_old_included_files + run_single_strategy(@touchin_swiftlint_yaml_temporary_path) + elsif not is_exist_total_touchin_included_files and is_exist_total_old_included_files + run_single_strategy(@old_swiftlint_yaml_temporary_path) + else + puts 'Git did not found swift files to check' + end + end + + def run_fully_single_strategy + run_single_strategy(@touchin_swiftlint_yaml_path) + end + + def run_simplified_single_strategy(source_root_path) + included_files = GitСaretaker.get_modified_files + + if included_files.nilOrEmpty? + puts 'Git did not found swift files to check' + return + end + + create_copy_temporary_touchin_files + + touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + swift_files = SwiftFileManager.new(touchin_excluded_files, '') + + included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) } + included_files = included_files.map { |file_path| source_root_path + file_path } + + touchin_swiftlint_yaml_manager.update('excluded', []) + touchin_swiftlint_yaml_manager.update('included', included_files) + + if not included_files.nilOrEmpty? + run_single_strategy(@touchin_swiftlint_yaml_temporary_path) + else + puts 'Git found the swift files to check, but they are excluded in yaml' + end + end + + private + + def run_single_strategy(swiftlint_yaml_path) + result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path) + puts result_swiftlint_command + run_bash_command(result_swiftlint_command) + end + + def run_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path) + touchin_swiftlint_command = get_swiftlint_command(touchin_swiftlint_yaml_temporary_path) + old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path) + result_swiftlint_command = touchin_swiftlint_command + ' && ' + old_swiftlint_command + puts result_swiftlint_command + run_bash_command(result_swiftlint_command) + end + + def get_swiftlint_command(swiftlint_yaml_path) + autocorrect_command = @swiftlint_autocorrect_command + swiftlint_yaml_path + lint_command = @swiftlint_lint_command + swiftlint_yaml_path + return autocorrect_command + ' && ' + lint_command + end + + def run_bash_command(bash_command) + exit (exec bash_command) + end + + def create_yaml_managers_and_copy_temporary_files + create_copy_temporary_files + + @touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + @old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + end + + def create_copy_temporary_files + create_copy_temporary_touchin_files + FileUtils.cp @old_swiftlint_yaml_path, @old_swiftlint_yaml_temporary_path + end + + def create_copy_temporary_touchin_files + Dir.mkdir(@temporary_swiftlint_folder_name) unless Dir.exist?(@temporary_swiftlint_folder_name) + FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path + end + + def unique_exclude_files(touchin_swiftlint_yaml_manager, old_swiftlint_yaml_manager) + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') + common_exclude_files = touchin_excluded_files + old_excluded_files + unique_exclude_files = common_exclude_files.uniq + return unique_exclude_files + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/string_extension.rb b/xcode/build_phases/multiple_swiftlint/string_extension.rb new file mode 100644 index 0000000..33a6357 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/string_extension.rb @@ -0,0 +1,17 @@ +class String + def with_wrapped_whitespace + self.gsub(/\s+/, '\ ') + end + + def filter_allowed_symbol_into_path + self.gsub!(/[^0-9A-Za-z \-+.\/]/, '') + end + + def true? + self.to_s.downcase == "true" + end + + def nilOrEmpty? + self.nil? or self.empty? + end +end diff --git a/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb new file mode 100644 index 0000000..b8edf6c --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb @@ -0,0 +1,68 @@ +require 'fileutils' +require 'date' + +require_relative 'git_caretaker.rb' + +class SwiftFileManager + def initialize(excluded_files, source_date) + if not source_date.nilOrEmpty? + @source_date = Date.parse(source_date) + end + @excluded_files = excluded_files + @new_files = [] + @old_files = [] + end + + def old_files + @old_files + end + + def new_files + @new_files + end + + def find_list_file_paths(start_folder) + swift_files = File.join('**', '*.swift') + Dir.glob(swift_files, base: start_folder) { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def find_list_file_paths_from(files_path) + files_path.each { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def is_excluded_file(file_path) + @excluded_files.each do |exclude_file_path| + if file_path.include? exclude_file_path + return true + end + end + return false + end + + private + + def compare_timestamp(file_path) + wrapped_whitespace_file_path = file_path.with_wrapped_whitespace + creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path) + if creation_date_string.nilOrEmpty? + @old_files.push(file_path) + puts ('Creation date of ' + file_path + ' was not found') + else + creation_date = Date.parse(creation_date_string) + puts ('Creation date of ' + file_path + ' is ' + creation_date.to_s) + if @source_date < creation_date + @new_files.push(file_path) + else + @old_files.push(file_path) + end + end + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb new file mode 100644 index 0000000..17f8383 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -0,0 +1,16 @@ +#https://github.com/TouchInstinct/Styleguide/blob/multiple_swiftlint/IOS/Guides/BuildScripts/Multiple_Swiftlint_Guide.md +require_relative 'setting_option.rb' +require_relative 'strategy_maker.rb' + +setting = SettingOption.new +strategy_maker = StrategyMaker.new(setting.project_root_path, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) + +if setting.check_mode.eql? 'fully' and setting.use_multiple.true? + strategy_maker.run_fully_multiple_strategy(setting.source_date) +elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? + strategy_maker.run_fully_single_strategy +elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? + strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.source_root_path) +elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? + strategy_maker.run_simplified_single_strategy(setting.source_root_path) +end diff --git a/xcode/build_phases/multiple_swiftlint/yaml_manager.rb b/xcode/build_phases/multiple_swiftlint/yaml_manager.rb new file mode 100644 index 0000000..cb3bbd8 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/yaml_manager.rb @@ -0,0 +1,24 @@ +require 'yaml' +require 'fileutils' + +class YamlManager + def initialize(swiftlint_yaml_path) + @swiftlint_yaml_path = swiftlint_yaml_path + @configuration ||= YAML.load(File.read(@swiftlint_yaml_path)) + end + + def get_configuration(key) + @configuration[key] + end + + def update(key, new_configuration_values) + @configuration[key] = new_configuration_values + save_settings(@configuration) + end + + private + + def save_settings(settings) + File.write(@swiftlint_yaml_path, settings.to_yaml) + end +end diff --git a/xcode/commonFastfile b/xcode/commonFastfile index d903469..8564ade 100644 --- a/xcode/commonFastfile +++ b/xcode/commonFastfile @@ -91,7 +91,7 @@ private_lane :addShield do |options| .split(/(?=[A-Z])/) # -> ["Enterprise", "Customer", "Dev1", "Without", "S", "S", "L", "Pinning", "Release"] .map { |v| v.gsub(/[[:lower:]]+/, "") }[1..2] # -> ["E", "C", "D1", "W", "S", "S", "L", "P", "R"] -> ["C", "D1"] .join # -> "CD1" - + begin add_badge( shield: "#{buildDescription}-#{buildNumber}-green", @@ -168,7 +168,9 @@ private_lane :buildArchive do |options| configuration = options[:configuration] xcodeproj_path = options[:xcodeproj_path] - set_xcconfig_for_configuration_of_project(xcconfig_name, configuration, xcodeproj_path) + if configuration != "AppStore" # AppStore uses xcconfig choosen in Xcode + set_xcconfig_for_configuration_of_project(xcconfig_name, configuration, xcodeproj_path) + end gym( clean: true, @@ -186,7 +188,10 @@ private_lane :buildArchive do |options| ) end -lane :createPushCertificate do |options| +lane :CreatePushCertificate do |options| + configuration = get_configuration_for_type(options[:type] || "development") + options = configuration.to_options.merge(options) + certificates_path = File.expand_path "../Certificates" Dir.mkdir(certificates_path) unless File.directory?(certificates_path) diff --git a/xcode/config_generator/render_xcconfigs.rb b/xcode/config_generator/render_xcconfigs.rb index 64d6b8e..e08f18a 100755 --- a/xcode/config_generator/render_xcconfigs.rb +++ b/xcode/config_generator/render_xcconfigs.rb @@ -2,15 +2,13 @@ require 'json' require 'mustache' require 'yaml' -# Usage: render_xcconfigs.rb # -# Result: Adds .xcconfig files to $configs_folder_name directory. +# Usage: render_xcconfigs.rb [] +# +# Result: Adds .xcconfig files to ouptut folder. # Files are only being added and changed, not removed! # It is recommended to remove old .xcconfig files before running this script. - - -# Constants -$configs_folder_name = "TargetConfigurations" +# class String def in_current_dir @@ -23,10 +21,11 @@ configurations_file_path = ARGV[0] temp_configs_data_file_path = "configs_data.json".in_current_dir generator_path = "build_options_helper/helper.py".in_current_dir template_path = "target_xcconfig.mustache".in_current_dir -build_parameters_path = ARGV[1] || "build_parameters.yaml".in_current_dir +build_parameters_path = ARGV[1] +configs_folder_name = ARGV[2] || "TargetConfigurations" # Create config directory if needed -Dir.mkdir($configs_folder_name) unless Dir.exist?($configs_folder_name) +Dir.mkdir(configs_folder_name) unless Dir.exist?(configs_folder_name) # Call python script and generate configs to config file system("python #{generator_path} -bp #{build_parameters_path} -o #{__dir__} -r ios_build_settings -p ios") @@ -147,7 +146,7 @@ targets.each do |target_name, target| } # Create file for every setting in loop - File.open($configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file| + File.open(configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file| file.puts(Mustache.render(target_xcconfig_tempate, config_data)) } end