From 05730ee314e7d1943aa63c88cdc43a3a1403a490 Mon Sep 17 00:00:00 2001 From: Alexey Alter-Pesotskiy Date: Tue, 13 Aug 2024 16:10:42 +0100 Subject: [PATCH] [CI] Share fastlane lanes across platforms --- .github/workflows/cron-checks.yml | 4 +- .gitignore | 2 +- Gemfile.lock | 4 +- fastlane/Fastfile | 186 +++--------------------------- fastlane/Pluginfile | 2 +- 5 files changed, 22 insertions(+), 176 deletions(-) diff --git a/.github/workflows/cron-checks.yml b/.github/workflows/cron-checks.yml index 9446524c..c358d703 100644 --- a/.github/workflows/cron-checks.yml +++ b/.github/workflows/cron-checks.yml @@ -2,8 +2,8 @@ name: Cron Checks on: schedule: - # Runs "At 02:00 every night" - - cron: '0 2 * * *' + # Runs "At 02:00 every night except weekends" + - cron: '0 2 * * 1-5' workflow_dispatch: diff --git a/.gitignore b/.gitignore index 7e8e9234..4b393755 100644 --- a/.gitignore +++ b/.gitignore @@ -71,7 +71,7 @@ fastlane/screenshots fastlane/test_output fastlane/allurectl fastlane/xcresults -fastlane/metrics +**/metrics/ fastlane/recordings StreamChatCore.framework.coverage.txt StreamChatCoreTests.xctest.coverage.txt diff --git a/Gemfile.lock b/Gemfile.lock index bccc5fad..27213d17 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -199,7 +199,7 @@ GEM fastlane pry fastlane-plugin-sonarcloud_metric_kit (0.2.1) - fastlane-plugin-stream_actions (0.3.38) + fastlane-plugin-stream_actions (0.3.57) xctest_list (= 1.2.1) fastlane-plugin-versioning (0.5.2) ffi (1.17.0) @@ -427,7 +427,7 @@ DEPENDENCIES fastlane-plugin-create_xcframework fastlane-plugin-lizard fastlane-plugin-sonarcloud_metric_kit - fastlane-plugin-stream_actions (= 0.3.38) + fastlane-plugin-stream_actions (= 0.3.57) fastlane-plugin-versioning jazzy json diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 0c58410b..d963760b 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -13,22 +13,15 @@ sdk_names = ['StreamChatSwiftUI'] github_repo = ENV['GITHUB_REPOSITORY'] || 'GetStream/stream-chat-swiftui' derived_data_path = 'derived_data' source_packages_path = 'spm_cache' -metrics_git = 'git@github.com:GetStream/stream-internal-metrics.git' -sdk_size_path = "metrics/#{github_repo.split('/').last}-size.json" buildcache_xcargs = 'CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++' is_localhost = !is_ci project_package_resolved = "#{xcode_project}/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" @force_check = false -warning_status = '🟡' # Warning if a branch is #{max_tolerance} less performant than the benchmark -fail_status = '🔴' # Failure if a branch is more than #{max_tolerance} less performant than the benchmark -success_status = '🟢' # Success if a branch is more performant or equals to the benchmark -outstanding_status = '🚀' # Outstanding performance - before_all do |lane| if is_ci setup_ci - sh('git config --global user.name "Stream Bot"') + setup_git_config xcversion(version: xcode_version) unless [:publish_release, :allure_launch, :allure_upload, :copyright, :pod_lint].include?(lane) end end @@ -152,7 +145,7 @@ lane :merge_release_to_main do |options| comment = "[Publication of the release](https://github.com/#{github_repo}/actions/workflows/release-publish.yml) has been launched 👍" UI.important(comment) - create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: comment) + pr_comment(text: comment) end lane :merge_main_to_develop do @@ -234,7 +227,7 @@ lane :test_ui do |options| png_files.each { |png| sh("git add #{png}") || true } sh('git restore .') - create_pr( + pr_create( title: '[CI] Snapshots', base_branch: current_branch, head_branch: "#{current_branch}-snapshots" @@ -448,21 +441,7 @@ lane :rubocop do end lane :install_runtime do |options| - runtimes = `xcrun simctl runtime list -j` - UI.message("👉 Runtime list:\n#{runtimes}") - simulators = JSON.parse(runtimes).select do |_, sim| - sim['platformIdentifier'].end_with?('iphonesimulator') && sim['version'] == options[:ios] && sim['state'] == 'Ready' - end - - if simulators.empty? - Dir.chdir('..') do - sh("echo 'iOS #{options[:ios]} Simulator' | ipsw download xcode --sim") if Dir['*.dmg'].first.nil? - sh("./Scripts/install_ios_runtime.sh #{Dir['*.dmg'].first}") - UI.success("iOS #{options[:ios]} Runtime successfuly installed") - end - else - UI.important("iOS #{options[:ios]} Runtime already exists") - end + install_ios_runtime(version: options[:ios], custom_script: 'Scripts/install_ios_runtime.sh') end desc 'Remove UI Snapshots' @@ -492,92 +471,26 @@ lane :copyright do update_copyright(ignore: [derived_data_path, source_packages_path, 'vendor/']) next unless is_ci - create_pr( + pr_create( title: '[CI] Update Copyright', head_branch: "ci/update-copyright-#{Time.now.to_i}" ) end -desc 'Show current frameworks size' lane :show_frameworks_sizes do |options| next unless is_check_required(sources: sources_matrix[:size], force_check: @force_check) - ['metrics/'].each { |dir| FileUtils.remove_dir(dir, force: true) } - - sh("git clone #{metrics_git} #{File.dirname(sdk_size_path)}") - is_release = current_branch.include?('release/') - benchmark_config = JSON.parse(File.read(sdk_size_path)) - benchmark_key = is_release ? 'release' : 'develop' - benchmark_sizes = benchmark_config[benchmark_key] - branch_sizes = options[:sizes] || frameworks_sizes - - table_header = '## SDK Size' - markdown_table = "#{table_header}\n| `title` | `#{is_release ? 'previous release' : 'develop'}` | `#{is_release ? 'current release' : 'branch'}` | `diff` | `status` |\n| - | - | - | - | - |\n" - sdk_names.each do |title| - benchmark_value = benchmark_sizes[title] - branch_value = branch_sizes[title.to_sym] - max_tolerance = 0.5 # Max Tolerance is 0.5MB - fine_tolerance = 0.25 # Fine Tolerance is 0.25MB - - diff = (branch_value - benchmark_value).round(2) - - status_emoji = - if diff < 0 - outstanding_status - elsif diff >= max_tolerance - fail_status - elsif diff >= fine_tolerance - warning_status - else - success_status - end - - markdown_table << "|#{title}|#{benchmark_value}MB|#{branch_value}MB|#{diff}MB|#{status_emoji}|\n" - end - - FastlaneCore::PrintTable.print_values(title: 'Benchmark', config: benchmark_sizes) - FastlaneCore::PrintTable.print_values(title: 'SDK Size', config: branch_sizes) - - if is_ci - if is_release || ENV['GITHUB_EVENT_NAME'].to_s == 'push' - benchmark_config[benchmark_key] = branch_sizes - File.write(sdk_size_path, JSON.pretty_generate(benchmark_config)) - Dir.chdir(File.dirname(sdk_size_path)) do - if sh('git status -s', log: false).to_s.empty? - UI.important('No changes in SDK sizes benchmarks.') - else - sh('git add -A') - sh("git commit -m 'Update #{sdk_size_path}'") - sh('git push') - end - end - end - - create_pr_comment(pr_num: ENV.fetch('GITHUB_PR_NUM'), text: markdown_table, edit_last_comment_with_text: table_header) - end - - UI.user_error!("#{table_header} benchmark failed.") if markdown_table.include?(fail_status) + sizes = options[:sizes] || frameworks_sizes + show_sdk_size(branch_sizes: sizes, github_repo: github_repo) + update_img_shields_sdk_sizes(sizes: sizes, open_pr: options[:open_pr]) if options[:update_readme] end -desc 'Update img shields SDK size labels' -lane :update_img_shields_sdk_sizes do - sizes = frameworks_sizes - - # Read the file into a string - readme_path = '../README.md' - readme_content = File.read(readme_path) - - # Define the new value for the badge - stream_chat_swiftui_size = "#{sizes[:StreamChatSwiftUI]}MB" - - # Replace the value in the badge URL - readme_content.gsub!(%r{(https://img.shields.io/badge/StreamChatSwiftUI-)(.*?)(-blue)}, "\\1#{stream_chat_swiftui_size}\\3") - - # Write the updated content back to the file - File.write(readme_path, readme_content) - - # Notify success - UI.success('Successfully updated the SDK size labels in README.md!') +lane :update_img_shields_sdk_sizes do |options| + update_sdk_size_in_readme( + open_pr: options[:open_pr] || false, + readme_path: 'README.md', + sizes: options[:sizes] || frameworks_sizes + ) end def frameworks_sizes @@ -603,74 +516,7 @@ def frameworks_sizes frameworks_path = "../#{archive_dir}/Products/Applications/DemoAppSwiftUI.app/Frameworks" stream_chat_swiftui_size = File.size("#{frameworks_path}/StreamChatSwiftUI.framework/StreamChatSwiftUI") - stream_chat_swiftui_size_mb = ((stream_chat_swiftui_size + assets_thinned_size).to_f / 1024 / 1024).round(2) - - { - StreamChatSwiftUI: stream_chat_swiftui_size_mb - } -end - -private_lane :create_pr do |options| - options[:base_branch] ||= 'develop' - sh("git checkout -b #{options[:head_branch]}") - sh('git add -A') - sh("git commit -m '#{options[:title]}'") - push_to_git_remote(tags: false) - - create_pull_request( - api_token: ENV.fetch('GITHUB_TOKEN', nil), - repo: github_repo, - title: options[:title], - head: options[:head_branch], - base: options[:base_branch], - body: 'This PR was created automatically by CI.' - ) -end - -private_lane :create_pr_comment do |options| - if is_ci && !options[:pr_num].to_s.empty? - last_comment = sh("gh pr view #{options[:pr_num]} --json comments --jq '.comments | map(select(.author.login == \"Stream-SDK-Bot\")) | last'") - edit_last_comment = options[:edit_last_comment_with_text] && last_comment.include?(options[:edit_last_comment_with_text]) ? '--edit-last' : '' - sh("gh pr comment #{options[:pr_num]} #{edit_last_comment} -b '#{options[:text]}'") - end -end - -lane :current_branch do - branch = if ENV['GITHUB_PR_NUM'].to_s.empty? - git_branch - else - sh("gh pr view #{ENV.fetch('GITHUB_PR_NUM')} --json headRefName -q .headRefName").strip - end - - UI.important("Current branch: #{branch} 🕊️") - branch -end - -private_lane :git_status do |options| - UI.user_error!('Extension should be provided') unless options[:ext] - - untracked_files = sh('git status -s', log: false).split("\n").map(&:strip) - UI.important("Git Status: #{untracked_files}") + stream_chat_swiftui_size_kb = ((stream_chat_swiftui_size + assets_thinned_size).to_f / 1024) - deleted_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'D') - added_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: ['A', '??']) - renamed_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'R') - modified_files = select_files_from(files: untracked_files, with_extension: options[:ext], that_start_with: 'M') - - renamed_files.each do |renamed_file| - content = renamed_file.split.drop(1).join.split('->').map(&:strip) - deleted_files << content.first - added_files << content.last - end - { a: added_files, d: deleted_files, m: modified_files } -end - -def select_files_from(files:, with_extension:, that_start_with:) - files.select do |f| - f.start_with?(*that_start_with) - end.map do |f| - f.split.drop(1).join(' ') - end.select do |f| - f.gsub(/['"]/, '').end_with?(with_extension) - end + { StreamChatSwiftUI: stream_chat_swiftui_size_kb } end diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile index 68e7b187..14c5e972 100644 --- a/fastlane/Pluginfile +++ b/fastlane/Pluginfile @@ -4,5 +4,5 @@ gem 'fastlane-plugin-versioning' gem 'fastlane-plugin-sonarcloud_metric_kit' -gem 'fastlane-plugin-stream_actions', '0.3.38' +gem 'fastlane-plugin-stream_actions', '0.3.57' gem 'fastlane-plugin-create_xcframework'