From 68c80e641682a6360918693348ad7a4a45c17406 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 1 Oct 2025 13:37:58 +0300 Subject: [PATCH 1/5] Implement Fastlane build pipeline --- .gitignore | 5 + README.md | 14 + fastlane/Fastfile | 9 + fastlane/Gemfile | 13 + fastlane/Gemfile.lock | 308 +++++++++++++++ fastlane/Matchfile | 5 + fastlane/Pluginfile | 5 + fastlane/build_xcframework.sh | 24 ++ fastlane/lanes/gclient | 66 ++++ fastlane/lanes/ios | 370 ++++++++++++++++++ fastlane/lanes/utilities | 69 ++++ fastlane/report.xml | 168 ++++++++ .../peerconnection/RTCAudioDeviceModule.mm | 40 +- 13 files changed, 1076 insertions(+), 20 deletions(-) create mode 100644 fastlane/Fastfile create mode 100644 fastlane/Gemfile create mode 100644 fastlane/Gemfile.lock create mode 100644 fastlane/Matchfile create mode 100644 fastlane/Pluginfile create mode 100755 fastlane/build_xcframework.sh create mode 100644 fastlane/lanes/gclient create mode 100644 fastlane/lanes/ios create mode 100644 fastlane/lanes/utilities create mode 100644 fastlane/report.xml diff --git a/.gitignore b/.gitignore index 3ff72b28b1..277e4d3b9b 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,8 @@ /node_modules /libwebrtc /args.txt + + +# Stream specifics +fastlane/vendor +out_ios_libs diff --git a/README.md b/README.md index f35e1cf6da..9a93dca1ed 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,20 @@ This repository is a fork of the WebRTC project. The original README can be found [here](README_webrtc.md). +### Fork Specifics + +#### `.gitignore` + +Due to the fork specifics, the repo's `.gitignore` has been updated to match the fork's requirements. + +#### Building Tools + +The fork contains a `fastlane` pipeline to produce builds for iOS. To access the pipeline you need to switch into `src/fastlane` and execute `bundle exec fastlane lanes` to see the available lanes. + +##### Building for iOS + +- Build the WebRTC library for iOS `bundle exec fastlane ios build` + ### License - [WebRTC](https://webrtc.org) software is licensed under the [BSD license](https://github.com/GetStream/webrtc/blob/main/LICENSE). - Includes patches from [shiguredo-webrtc-build](https://github.com/shiguredo-webrtc-build), licensed under the [Apache 2.0](https://github.com/shiguredo-webrtc-build/webrtc-build/blob/master/LICENSE). diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000000..b8ef179df1 --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,9 @@ +skip_docs + +require 'json' +require 'net/http' +require 'fileutils' + +import "./lanes/utilities" +import "./lanes/gclient" +import "./lanes/ios" \ No newline at end of file diff --git a/fastlane/Gemfile b/fastlane/Gemfile new file mode 100644 index 0000000000..86eea32460 --- /dev/null +++ b/fastlane/Gemfile @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +gem 'cocoapods' +gem 'fastlane' +gem 'json' +gem 'plist' + +plugins_path = File.join(File.dirname(__FILE__), 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) \ No newline at end of file diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock new file mode 100644 index 0000000000..a01c301f46 --- /dev/null +++ b/fastlane/Gemfile.lock @@ -0,0 +1,308 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + activesupport (7.2.2.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + artifactory (3.0.17) + atomos (0.1.3) + aws-eventstream (1.4.0) + aws-partitions (1.1131.0) + aws-sdk-core (3.226.3) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 + jmespath (~> 1, >= 1.6.1) + logger + aws-sdk-kms (1.106.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.193.0) + aws-sdk-core (~> 3, >= 3.225.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.12.1) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.3.0) + benchmark (0.4.1) + bigdecimal (3.2.2) + claide (1.1.0) + cocoapods (1.16.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.16.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.27.0, < 2.0) + cocoapods-core (1.16.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) + declarative (0.0.20) + digest-crc (0.7.0) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.6.20240107) + dotenv (2.8.1) + drb (2.2.3) + emoji_regex (3.2.3) + escape (0.0.4) + ethon (0.16.0) + ffi (>= 1.15.0) + excon (0.112.0) + faraday (1.10.4) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.1) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.1.1) + multipart-post (~> 2.0) + faraday-net_http (1.0.2) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.1) + faraday (~> 1.0) + fastimage (2.4.0) + fastlane (2.228.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored (~> 1.2) + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (>= 0.1.1, < 1.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.5) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.4.1) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-plugin-stream_actions (0.3.90) + xctest_list (= 1.2.1) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) + ffi (1.17.2-arm64-darwin) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.54.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.3) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.31.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.8.0) + google-cloud-env (>= 1.0, < 3.a) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.5.0) + google-cloud-storage (1.47.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.31.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.8) + domain_name (~> 0.5) + httpclient (2.9.0) + mutex_m + i18n (1.14.7) + concurrent-ruby (~> 1.0) + jmespath (1.6.2) + json (2.13.0) + jwt (2.10.2) + base64 + logger (1.7.0) + mini_magick (4.13.2) + mini_mime (1.1.5) + minitest (5.25.5) + molinillo (0.8.0) + multi_json (1.17.0) + multipart-post (2.4.1) + mutex_m (0.3.0) + nanaimo (0.4.0) + nap (1.1.0) + naturally (2.3.0) + netrc (0.11.0) + nkf (0.2.0) + optparse (0.6.0) + os (1.1.4) + plist (3.7.2) + public_suffix (4.0.7) + rake (13.3.0) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.4.1) + rouge (3.28.0) + ruby-macho (2.5.1) + ruby2_keywords (0.0.5) + rubyzip (2.4.1) + securerandom (0.4.1) + security (0.1.5) + signet (0.20.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + sysrandom (1.0.5) + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.2) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + typhoeus (1.4.1) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uber (0.1.0) + unicode-display_width (2.6.0) + word_wrap (1.0.0) + xcodeproj (1.27.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) + xcpretty (0.4.1) + rouge (~> 3.28.0) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + xctest_list (1.2.1) + +PLATFORMS + arm64-darwin-24 + +DEPENDENCIES + cocoapods + fastlane + fastlane-plugin-stream_actions (= 0.3.90) + json + plist + +BUNDLED WITH + 2.3.3 diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 0000000000..f26ef457be --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,5 @@ +git_url("git@github.com:GetStream/ios-certificates.git") + +storage_mode("git") + +team_id("EHV7XZLAHA") diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 0000000000..76c87679b1 --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-stream_actions', '0.3.90' \ No newline at end of file diff --git a/fastlane/build_xcframework.sh b/fastlane/build_xcframework.sh new file mode 100755 index 0000000000..a26887ea72 --- /dev/null +++ b/fastlane/build_xcframework.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +gclient root +gclient config --spec 'solutions = [ +{ + "name": "src", + "url": "git@github.com:GetStream/webrtc.git", + "deps_file": "DEPS", + "managed": False, + "custom_deps": {}, +}, +] +target_os = ["ios", "mac"] +' +gclient sync -j8 -v + +cd src +./tools_webrtc/ios/build_ios_libs.py \ + --deployment-target 13.0 \ + --extra-gn-args \ + is_debug=false \ + use_goma=false \ + use_rtti=false \ + rtc_libvpx_build_vp9=true \ No newline at end of file diff --git a/fastlane/lanes/gclient b/fastlane/lanes/gclient new file mode 100644 index 0000000000..53609d16fe --- /dev/null +++ b/fastlane/lanes/gclient @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'fileutils' + +private_lane :configure_gclient do |options| + log_debug( + message: "Configuring gclient...", + verbose: options[:verbose] + ) + + base_root = File.expand_path('../../../', __dir__) + root = if options[:output] + File.expand_path(options[:output], base_root) + else + File.join(base_root, '.output') + end + FileUtils.mkdir_p(root) + + Dir.chdir(root) do + # Set gclient root + execute_command(command: "gclient root", verbose: options[:verbose]) + + # Configure gclient with the spec + target_oses = Array(options[:target_os]).compact.map(&:to_s) + target_os_entries = target_oses.map { |os| "\"#{os}\"" }.join(', ') + gclient_spec = <<~SPEC + solutions = [ + { + "name": "src", + "url": "git@github.com:GetStream/webrtc.git", + "deps_file": "DEPS", + "managed": False, + "custom_deps": {}, + }, + ] + target_os = [#{target_os_entries}] + SPEC + + # Write spec to temporary file and configure + execute_command( + command: "gclient config --spec '#{gclient_spec.gsub("'", "'\"'\"'")}'", + verbose: options[:verbose] + ) + + UI.success("gclient configured successfully") + + sync_dependencies( + number_of_jobs: options[:number_of_jobs], + verbose: options[:verbose] + ) + end +end + +private_lane :sync_dependencies do |options| + jobs = options[:number_of_jobs] || 8 + log_debug( + message: "Syncing dependencies...", + verbose: options[:verbose] + ) + + command = "gclient sync -j#{jobs}" + command += " -v" if options[:verbose] + + execute_command(command: command, verbose: options[:verbose]) + UI.success("Dependencies synced successfully") +end diff --git a/fastlane/lanes/ios b/fastlane/lanes/ios new file mode 100644 index 0000000000..e475e3284f --- /dev/null +++ b/fastlane/lanes/ios @@ -0,0 +1,370 @@ +# frozen_string_literal: true + +require 'fileutils' +require 'pathname' +require 'shellwords' +fastlane_require "fastlane-plugin-stream_actions" + +platform :ios do + desc "Sync dependencies and build the WebRTC iOS libraries" + + lane :build do |options| + options[:root] = Pathname.new(__dir__).join('..', '..', '..').expand_path + options[:build_root] = File.join(options[:root], ".output") + options[:products_root] = File.join(options[:root], ".products") + options[:sdk_name] = "WebRTC" + options[:product_source] = File.join(options[:root], "src/out_ios_libs/#{options[:sdk_name]}.xcframework") + options[:build_tool] = File.join(options[:root], "src/tools_webrtc/ios/build_ios_libs.py") + options[:rename_to_sdk_name] = "Stream#{options[:sdk_name]}" + options[:product] = File.join(options[:products_root], "#{options[:rename_to_sdk_name]}.xcframework") + options[:match_file] = File.join(options[:root], "src/fastlane/Matchfile") + catalyst_option = options.key?(:maccatalyst_support) ? options[:maccatalyst_support] : true + options[:maccatalyst_support] = !%w[false 0 off no].include?(catalyst_option.to_s.downcase) + + log_info(message: "Root: #{options[:root]}") + log_info(message: "Build root: #{options[:build_root]}") + log_info(message: "Products root: #{options[:products_root]}") + log_info(message: "Product source: #{options[:product_source]}") + log_info(message: "Build tool: #{options[:build_tool]}") + log_info(message: "Matchfile: #{options[:match_file]}") + log_info(message: "Product: #{options[:product]}") + log_info(message: "Mac Catalyst support: #{options[:maccatalyst_support]}") + + setup_ci if is_ci + clean_up_products(options) + verify_environment(options) + configure_google_client(options) + build_product(options) + move_product(options) + rename_product(options) + prepare_signing(options) + sign_product(options) + verify_signatures(options) + zip_product(options) + end + + lane :clean_up_products do |options| + lane_options = extract_prefixed_options(options, "clean_up_products") + next unless lane_options[:skip] != true + log_debug(message: "Cleaning up products", verbose: options[:verbose]) + + products_root = options[:products_root] + assert(message: "Missing required option :products_root") if products_root.to_s.strip.empty? + + unless Dir.exist?(products_root) + return + end + + log_info(message: "Cleaning products directory at #{products_root}") + Dir.children(products_root).each do |entry| + FileUtils.rm_rf(File.join(products_root, entry)) + end + end + + lane :verify_environment do |options| + lane_options = extract_prefixed_options(options, "verify_environment") + next unless lane_options[:skip] != true + + verify_build_environment(verbose: options[:verbose]) + + ensure_required_tool(tool: "xcodebuild", verbose: options[:verbose]) + + # Check if we're on macOS + unless RUBY_PLATFORM.include?('darwin') + log_error(message: "iOS builds require macOS") + end + + # Check if Xcode is installed + unless system("xcode-select -p > /dev/null 2>&1") + log_error(message: "Xcode command line tools not found") + end + end + + lane :configure_google_client do |options| + lane_options = extract_prefixed_options(options, "configure_google_client") + next if lane_options[:skip] == true + + target_os = ["ios"] + target_os << "mac" if options[:maccatalyst_support] + log_info(message: "Configuring gclient target_os: #{target_os.join(', ')}") + + configure_gclient( + target_os: target_os, + verbose: options[:verbose], + number_of_jobs: options[:number_of_jobs], + output: options[:build_root] + ) + end + + lane :build_product do |options| + lane_options = extract_prefixed_options(options, "build_product") + next if lane_options[:skip] == true + + deployment_target = options[:deployment_target] || "13.0" + maccatalyst_support = options[:maccatalyst_support] + + args_list = resolve_build_product_args( + args: extract_prefixed_options(lane_options, "arg"), + verbose: options[:verbose] + ) + + script_path = options[:build_tool] + Dir.chdir(options[:build_root]) do + command_parts = ["\"#{script_path}\""] + command_parts << "--deployment-target #{deployment_target}" + archs = ["device:arm64", "simulator:arm64", "simulator:x64"] + archs += ["catalyst:arm64", "catalyst:x64"] if maccatalyst_support + command_parts << "--arch" + command_parts.concat(archs) + command_parts << "--extra-gn-args" + command_parts.concat(args_list) + + execute_command( + command: command_parts.join(' '), + verbose: options[:verbose] + ) + end + end + + lane :move_product do |options| + lane_options = extract_prefixed_options(options, "move_product") + next if lane_options[:skip] == true + + product_source = options[:product_source] + assert(message: "Missing required option :product_source") if product_source.to_s.strip.empty? + assert(message: "Product not found at #{product_source}") unless File.exist?(product_source) + + product_destination = options[:products_root] + assert(message: "Missing required option :products_root") if product_destination.to_s.strip.empty? + + FileUtils.mkdir_p(product_destination) + + destination_path = File.join(product_destination, File.basename(product_source)) + log_info(message: "Moving product from #{product_source} to #{destination_path}") + FileUtils.mv(product_source, destination_path) + + File.expand_path(destination_path) + end + + lane :rename_product do |options| + lane_options = extract_prefixed_options(options, "rename_product") + next if lane_options[:skip] == true + + product_source = options[:product_source] + assert(message: "Missing required option :product_source") if product_source.to_s.strip.empty? + products_root = options[:products_root] + assert(message: "Missing required option :products_root") if products_root.to_s.strip.empty? + product_destination = File.join(products_root, File.basename(product_source)) + assert(message: "Missing required option :product_destination") if product_destination.to_s.strip.empty? + assert(message: "Product not found at #{product_destination}") unless File.exist?(product_destination) + sdk_name = options[:sdk_name] + assert(message: "Missing required option :sdk_name") if sdk_name.to_s.strip.empty? + modified_sdk_name = options[:rename_to_sdk_name] + assert(message: "Missing required option :rename_to_sdk_name") if modified_sdk_name.to_s.strip.empty? + + old_framework_path = product_destination + new_framework_path = File.join(products_root, "#{modified_sdk_name}.xcframework") + + # Rename the framework itself + sh("cp -R #{old_framework_path} #{new_framework_path}") + + # Rename all files with the old framework name with the new one + ["#{sdk_name}.framework", "#{sdk_name}.h", sdk_name].each do |file_name| + Dir.glob("#{new_framework_path}/**/*").each do |old_file_path| + next unless File.basename(old_file_path) == file_name + + new_file_path = old_file_path.reverse.sub(sdk_name.reverse, modified_sdk_name.reverse).reverse + File.rename(old_file_path, new_file_path) + end + end + + # Replace all occurrences of the old framework name with the new one in the plist and modulemap files + Dir.glob(["#{new_framework_path}/**/Info.plist", "#{new_framework_path}/**/module.modulemap"]).each do |file| + sh("plutil -convert xml1 #{file}") if file.include?('Info.plist') + old_text = File.read(file) + new_text = old_text.gsub(/#{sdk_name}/, modified_sdk_name) + File.open(file, 'w') { |f| f.puts(new_text) } if old_text != new_text + end + + # Replace all imports of the old framework with the new one + Dir.glob("#{new_framework_path}/**/*.h").each do |file| + old_text = File.read(file) + new_text = old_text.gsub(/import <#{sdk_name}/, "import <#{modified_sdk_name}") + File.open(file, 'w') { |f| f.puts(new_text) } if old_text != new_text + end + + # Rename the rpath for all the frameworks and update symlinks if required + framework_paths = new_framework_path.include?('.xcframework') ? Dir.glob("#{new_framework_path}/**/*.framework") : [new_framework_path] + framework_paths.each do |path| + Dir.chdir(path) do + if File.symlink?(modified_sdk_name) + old_symlink = File.readlink(modified_sdk_name) + new_symlink = old_symlink.reverse.sub(sdk_name.reverse, modified_sdk_name.reverse).reverse + + File.delete(modified_sdk_name) + File.symlink(new_symlink, modified_sdk_name) + end + + sh("install_name_tool -id @rpath/#{modified_sdk_name}.framework/#{modified_sdk_name} #{modified_sdk_name}") + end + end + new_framework_path + end + + lane :prepare_signing do |options| + lane_options = extract_prefixed_options(options, "prepare_signing") + next unless lane_options[:skip] == true + + custom_match( + api_key: appstore_api_key, + app_identifier: ['io.getstream.iOS.VideoDemoApp'], # dummy app to get the certificates + readonly: true + ) + end + + lane :sign_product do |options| + lane_options = extract_prefixed_options(options, "sign_product") + next if lane_options[:skip] == true + + matchfile = options[:match_file] + assert(message: "Missing required option :match_file") if matchfile.to_s.strip.empty? + + team_id = File.read(matchfile).match(/team_id\("(.*)"\)/)[1] + frameworks = Dir.glob("#{options[:product]}/**/*.framework") + frameworks.each do |framework| + execute_command( + command: "/usr/bin/codesign --force --timestamp --deep -v --sign 'Apple Distribution: Stream.io Inc (#{team_id})' \"#{framework}\"", + verbose: options[:verbose] + ) + end + end + + lane :verify_signatures do |options| + lane_options = extract_prefixed_options(options, "verify_signatures") + next if lane_options[:skip] == true + + product_path = options[:product] + assert(message: "Missing required option :product") if product_path.to_s.strip.empty? + assert(message: "Product not found at #{product_path}") unless File.exist?(product_path) + + frameworks = Dir.glob("#{product_path}/**/*.framework") + assert(message: "No frameworks found to validate signatures") if frameworks.empty? + + log_info(message: "Validating code signatures for #{frameworks.count} frameworks") + + frameworks.each do |framework| + execute_command( + command: "/usr/bin/codesign --verify --deep --strict --verbose=2 \"#{framework}\"", + verbose: options[:verbose] + ) + end + end + + lane :zip_product do |options| + lane_options = extract_prefixed_options(options, "zip_product") + next if lane_options[:skip] == true + + file_path = options[:product] + zip_path = File.join(options[:products_root], "#{options[:rename_to_sdk_name]}.zip") + execute_command( + command: "ditto -c -k --sequesterRsrc --keepParent #{file_path} #{zip_path}", + verbose: options[:verbose] + ) + zip_path + end + + desc "Compute a checksum for the packaged xcframework zip" + lane :compute_zip_checksum do |options| + lane_options = extract_prefixed_options(options, "compute_zip_checksum") + next if lane_options[:skip] == true + + ensure_required_tool(tool: "swift", verbose: options[:verbose]) + + zip_path = lane_options[:zip_path] || options[:zip_path] + if zip_path.to_s.strip.empty? + products_root = options[:products_root] + rename_to_sdk_name = options[:rename_to_sdk_name] + zip_path = File.join(products_root, "#{rename_to_sdk_name}.zip") unless products_root.to_s.strip.empty? || rename_to_sdk_name.to_s.strip.empty? + end + + assert(message: "Missing required option :zip_path") if zip_path.to_s.strip.empty? + assert(message: "Zip file not found at #{zip_path}") unless File.exist?(zip_path) + + command = "swift package compute-checksum #{Shellwords.escape(zip_path)}" + checksum = execute_command( + command: command, + verbose: options[:verbose] + ).to_s.strip + + log_info(message: "Checksum for #{zip_path}: #{checksum}") + checksum + end + + private_lane :resolve_build_product_args do |options| + args = options[:args] || {} + + provided_args = [] + + arg_options = args.each_with_object({}) do |(key, value), memo| + key_str = key.to_s + + next if value.nil? + + memo[key_str] = value + end + + arg_options.each do |key, value| + value_str = value.is_a?(TrueClass) || value.is_a?(FalseClass) ? value.to_s : value.to_s + provided_args << "#{key}=#{value_str}" + end + + default_args = { + "is_debug" => "false", + "use_goma" => "false", + "use_rtti" => "false", + "rtc_libvpx_build_vp9" => "true" + } + + args_map = default_args.dup + additional_args = {} + + provided_args.each do |arg| + next if arg.to_s.strip.empty? + + key, value = arg.split('=', 2) + next if key.nil? || key.strip.empty? + + key = key.strip + value = value.nil? ? '' : value.strip + value = 'true' if value.empty? + + if args_map.key?(key) + args_map[key] = value + else + additional_args[key] = value + end + end + + args_list = default_args.keys.map do |key| + value = args_map[key] + value.nil? || value.empty? ? key : "#{key}=#{value}" + end + + additional_args.each do |key, value| + args_list << (value.nil? || value.empty? ? key : "#{key}=#{value}") + end + + log_info(message: "Resolved GN args: #{args_list.join(', ')}") + + args_list + end + + private_lane :appstore_api_key do + @appstore_api_key ||= app_store_connect_api_key( + key_id: 'MT3PRT8TB7', + issuer_id: '69a6de96-0738-47e3-e053-5b8c7c11a4d1', + key_content: ENV.fetch('APPSTORE_API_KEY', nil), + in_house: false + ) + end +end diff --git a/fastlane/lanes/utilities b/fastlane/lanes/utilities new file mode 100644 index 0000000000..3b6992ea5d --- /dev/null +++ b/fastlane/lanes/utilities @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +private_lane :verify_build_environment do |options| + log_debug( + message: "Verifying build environment...", + verbose: options[:verbose] + ) + + # Check if required tools are available + ensure_required_tool(tool: "gclient", verbose: options[:verbose]) + ensure_required_tool(tool: "python3", verbose: options[:verbose]) + + UI.success("Build environment verified successfully") +end + +private_lane :log_debug do |options| + UI.message(options[:message]) if options[:verbose] +end + +private_lane :log_info do |options| + UI.message(options[:message]) +end + +private_lane :log_success do |options| + UI.success(options[:message]) +end + +private_lane :log_error do |options| + UI.error(options[:message]) +end + +private_lane :assert do |options| + UI.abort_with_message!(options[:message]) +end + +private_lane :ensure_required_tool do |options| + tool = options[:tool] + unless system("which #{tool} > /dev/null 2>&1") + UI.user_error!("Required tool '#{tool}' not found in PATH") + end +end + +private_lane :execute_command do |options| + sh( + options[:command], + print_command: true, + print_command_output: options[:verbose] + ) +end + +def extract_prefixed_options(options, prefix) + return {} if options.nil? + + prefix = prefix.to_s + return {} if prefix.empty? + + prefix = prefix.end_with?('_') ? prefix : "#{prefix}_" + + options.each_with_object({}) do |(key, value), extracted| + next if value.nil? + + key_str = key.to_s + next unless key_str.start_with?(prefix) + + stripped_key = key_str.sub(prefix, '') + extracted[stripped_key.to_sym] = value + end +end + diff --git a/fastlane/report.xml b/fastlane/report.xml new file mode 100644 index 0000000000..34e6fc0c18 --- /dev/null +++ b/fastlane/report.xml @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/objc/api/peerconnection/RTCAudioDeviceModule.mm b/sdk/objc/api/peerconnection/RTCAudioDeviceModule.mm index aad4b2abed..8d64119630 100644 --- a/sdk/objc/api/peerconnection/RTCAudioDeviceModule.mm +++ b/sdk/objc/api/peerconnection/RTCAudioDeviceModule.mm @@ -299,7 +299,7 @@ - (NSInteger)initRecording { - (NSInteger)initAndStartRecording { return _workerThread->BlockingCall([self] { webrtc::AudioEngineDevice *engine_device = - dynamic_cast(_native.get()); + static_cast(_native.get()); if (engine_device != nullptr) { return engine_device->InitAndStartRecording(); } else { @@ -326,7 +326,7 @@ - (BOOL)isRecording { } - (BOOL)isEngineRunning { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return false; return _workerThread->BlockingCall([module] { return module->IsEngineRunning(); }); @@ -344,7 +344,7 @@ - (NSInteger)setMicrophoneMuted:(BOOL)muted { } - (RTC_OBJC_TYPE(RTCAudioEngineState))engineState { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return RTC_OBJC_TYPE(RTCAudioEngineState)(); return _workerThread->BlockingCall([module] { @@ -363,7 +363,7 @@ - (NSInteger)setMicrophoneMuted:(BOOL)muted { } - (void)setEngineState:(RTC_OBJC_TYPE(RTCAudioEngineState))state { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return; _workerThread->BlockingCall([module, state] { @@ -382,7 +382,7 @@ - (void)setEngineState:(RTC_OBJC_TYPE(RTCAudioEngineState))state { #pragma mark - Unique to AudioEngineDevice - (BOOL)isRecordingAlwaysPreparedMode { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -392,7 +392,7 @@ - (BOOL)isRecordingAlwaysPreparedMode { } - (NSInteger)setRecordingAlwaysPreparedMode:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return -1; return _workerThread->BlockingCall( @@ -400,7 +400,7 @@ - (NSInteger)setRecordingAlwaysPreparedMode:(BOOL)enabled { } - (BOOL)isManualRenderingMode { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -410,7 +410,7 @@ - (BOOL)isManualRenderingMode { } - (NSInteger)setManualRenderingMode:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return -1; return _workerThread->BlockingCall( @@ -418,7 +418,7 @@ - (NSInteger)setManualRenderingMode:(BOOL)enabled { } - (BOOL)isAdvancedDuckingEnabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -428,7 +428,7 @@ - (BOOL)isAdvancedDuckingEnabled { } - (void)setAdvancedDuckingEnabled:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return; _workerThread->BlockingCall( @@ -436,7 +436,7 @@ - (void)setAdvancedDuckingEnabled:(BOOL)enabled { } - (NSInteger)duckingLevel { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return 0; return _workerThread->BlockingCall([module] { @@ -446,14 +446,14 @@ - (NSInteger)duckingLevel { } - (void)setDuckingLevel:(NSInteger)value { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return; _workerThread->BlockingCall([module, value] { return module->SetDuckingLevel(value) == 0; }); } - (RTC_OBJC_TYPE(RTCAudioEngineMuteMode))muteMode { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return RTC_OBJC_TYPE(RTCAudioEngineMuteModeUnknown); return _workerThread->BlockingCall([module] { @@ -464,7 +464,7 @@ - (void)setDuckingLevel:(NSInteger)value { } - (NSInteger)setMuteMode:(RTC_OBJC_TYPE(RTCAudioEngineMuteMode))mode { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return -1; return _workerThread->BlockingCall( @@ -472,7 +472,7 @@ - (NSInteger)setMuteMode:(RTC_OBJC_TYPE(RTCAudioEngineMuteMode))mode { } - (BOOL)isVoiceProcessingEnabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -482,7 +482,7 @@ - (BOOL)isVoiceProcessingEnabled { } - (NSInteger)setVoiceProcessingEnabled:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return -1; return _workerThread->BlockingCall( @@ -490,7 +490,7 @@ - (NSInteger)setVoiceProcessingEnabled:(BOOL)enabled { } - (BOOL)isVoiceProcessingBypassed { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -500,7 +500,7 @@ - (BOOL)isVoiceProcessingBypassed { } - (void)setVoiceProcessingBypassed:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return; _workerThread->BlockingCall( @@ -508,7 +508,7 @@ - (void)setVoiceProcessingBypassed:(BOOL)enabled { } - (BOOL)isVoiceProcessingAGCEnabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return NO; return _workerThread->BlockingCall([module] { @@ -518,7 +518,7 @@ - (BOOL)isVoiceProcessingAGCEnabled { } - (void)setVoiceProcessingAGCEnabled:(BOOL)enabled { - webrtc::AudioEngineDevice *module = dynamic_cast(_native.get()); + webrtc::AudioEngineDevice *module = static_cast(_native.get()); if (module == nullptr) return; _workerThread->BlockingCall( From fdb145f2e7070b327135481eff47c8d4172cd6ba Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 1 Oct 2025 14:26:36 +0300 Subject: [PATCH 2/5] Address pr comments --- .gitignore | 2 + fastlane/Fastfile | 8 +- fastlane/Gemfile | 3 +- fastlane/Gemfile.lock | 27 ++++ fastlane/lanes/gclient | 66 --------- fastlane/lanes/gclient.rb | 68 +++++++++ fastlane/lanes/{ios => ios.rb} | 133 ++++++++--------- fastlane/lanes/utilities | 69 --------- fastlane/lanes/utilities.rb | 68 +++++++++ fastlane/report.xml | 251 +++++++++++++++++++++++++++++---- 10 files changed, 464 insertions(+), 231 deletions(-) delete mode 100644 fastlane/lanes/gclient create mode 100644 fastlane/lanes/gclient.rb rename fastlane/lanes/{ios => ios.rb} (73%) delete mode 100644 fastlane/lanes/utilities create mode 100644 fastlane/lanes/utilities.rb diff --git a/.gitignore b/.gitignore index 277e4d3b9b..a0394baba1 100644 --- a/.gitignore +++ b/.gitignore @@ -83,4 +83,6 @@ # Stream specifics fastlane/vendor +fastlane/Gemfile.lock +fastlane/*.xml out_ios_libs diff --git a/fastlane/Fastfile b/fastlane/Fastfile index b8ef179df1..1dd49ed40e 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,9 +1,11 @@ +# frozen_string_literal: true + skip_docs require 'json' require 'net/http' require 'fileutils' -import "./lanes/utilities" -import "./lanes/gclient" -import "./lanes/ios" \ No newline at end of file +import './lanes/utilities.rb' +import './lanes/gclient.rb' +import './lanes/ios.rb' diff --git a/fastlane/Gemfile b/fastlane/Gemfile index 86eea32460..3e35d8127c 100644 --- a/fastlane/Gemfile +++ b/fastlane/Gemfile @@ -8,6 +8,7 @@ gem 'cocoapods' gem 'fastlane' gem 'json' gem 'plist' +gem 'rubocop' plugins_path = File.join(File.dirname(__FILE__), 'Pluginfile') -eval_gemfile(plugins_path) if File.exist?(plugins_path) \ No newline at end of file +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock index a01c301f46..a870259fac 100644 --- a/fastlane/Gemfile.lock +++ b/fastlane/Gemfile.lock @@ -23,6 +23,7 @@ GEM httpclient (~> 2.8, >= 2.8.3) json (>= 1.5.1) artifactory (3.0.17) + ast (2.4.3) atomos (0.1.3) aws-eventstream (1.4.0) aws-partitions (1.1131.0) @@ -227,6 +228,8 @@ GEM json (2.13.0) jwt (2.10.2) base64 + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) logger (1.7.0) mini_magick (4.13.2) mini_mime (1.1.5) @@ -242,9 +245,17 @@ GEM nkf (0.2.0) optparse (0.6.0) os (1.1.4) + parallel (1.27.0) + parser (3.3.9.0) + ast (~> 2.4.1) + racc plist (3.7.2) + prism (1.5.1) public_suffix (4.0.7) + racc (1.8.1) + rainbow (3.1.1) rake (13.3.0) + regexp_parser (2.11.3) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) @@ -252,7 +263,22 @@ GEM retriable (3.1.2) rexml (3.4.1) rouge (3.28.0) + rubocop (1.81.1) + json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.47.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.47.1) + parser (>= 3.3.7.2) + prism (~> 1.4) ruby-macho (2.5.1) + ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.4.1) securerandom (0.4.1) @@ -303,6 +329,7 @@ DEPENDENCIES fastlane-plugin-stream_actions (= 0.3.90) json plist + rubocop BUNDLED WITH 2.3.3 diff --git a/fastlane/lanes/gclient b/fastlane/lanes/gclient deleted file mode 100644 index 53609d16fe..0000000000 --- a/fastlane/lanes/gclient +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -require 'fileutils' - -private_lane :configure_gclient do |options| - log_debug( - message: "Configuring gclient...", - verbose: options[:verbose] - ) - - base_root = File.expand_path('../../../', __dir__) - root = if options[:output] - File.expand_path(options[:output], base_root) - else - File.join(base_root, '.output') - end - FileUtils.mkdir_p(root) - - Dir.chdir(root) do - # Set gclient root - execute_command(command: "gclient root", verbose: options[:verbose]) - - # Configure gclient with the spec - target_oses = Array(options[:target_os]).compact.map(&:to_s) - target_os_entries = target_oses.map { |os| "\"#{os}\"" }.join(', ') - gclient_spec = <<~SPEC - solutions = [ - { - "name": "src", - "url": "git@github.com:GetStream/webrtc.git", - "deps_file": "DEPS", - "managed": False, - "custom_deps": {}, - }, - ] - target_os = [#{target_os_entries}] - SPEC - - # Write spec to temporary file and configure - execute_command( - command: "gclient config --spec '#{gclient_spec.gsub("'", "'\"'\"'")}'", - verbose: options[:verbose] - ) - - UI.success("gclient configured successfully") - - sync_dependencies( - number_of_jobs: options[:number_of_jobs], - verbose: options[:verbose] - ) - end -end - -private_lane :sync_dependencies do |options| - jobs = options[:number_of_jobs] || 8 - log_debug( - message: "Syncing dependencies...", - verbose: options[:verbose] - ) - - command = "gclient sync -j#{jobs}" - command += " -v" if options[:verbose] - - execute_command(command: command, verbose: options[:verbose]) - UI.success("Dependencies synced successfully") -end diff --git a/fastlane/lanes/gclient.rb b/fastlane/lanes/gclient.rb new file mode 100644 index 0000000000..be51556f2e --- /dev/null +++ b/fastlane/lanes/gclient.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'fileutils' + +# rubocop:disable Metrics/BlockLength +private_lane :configure_gclient do |options| + log_debug( + message: 'Configuring gclient...', + verbose: options[:verbose] + ) + + base_root = File.expand_path('../../../', __dir__) + root = if options[:output] + File.expand_path(options[:output], base_root) + else + File.join(base_root, '.output') + end + FileUtils.mkdir_p(root) + + Dir.chdir(root) do + # Set gclient root + execute_command(command: 'gclient root', verbose: options[:verbose]) + + # Configure gclient with the spec + target_oses = Array(options[:target_os]).compact.map(&:to_s) + target_os_entries = target_oses.map { |os| "\"#{os}\"" }.join(', ') + gclient_spec = <<~SPEC + solutions = [ + { + "name": "src", + "url": "git@github.com:GetStream/webrtc.git", + "deps_file": "DEPS", + "managed": False, + "custom_deps": {}, + }, + ] + target_os = [#{target_os_entries}] + SPEC + + # Write spec to temporary file and configure + execute_command( + command: "gclient config --spec '#{gclient_spec.gsub("'", "'\"'\"'")}'", + verbose: options[:verbose] + ) + + UI.success('gclient configured successfully') + + sync_dependencies( + number_of_jobs: options[:number_of_jobs], + verbose: options[:verbose] + ) + end +end +# rubocop:enable Metrics/BlockLength + +private_lane :sync_dependencies do |options| + jobs = options[:number_of_jobs] || 8 + log_debug( + message: 'Syncing dependencies...', + verbose: options[:verbose] + ) + + command = "gclient sync -j#{jobs}" + command += ' -v' if options[:verbose] + + execute_command(command: command, verbose: options[:verbose]) + UI.success('Dependencies synced successfully') +end diff --git a/fastlane/lanes/ios b/fastlane/lanes/ios.rb similarity index 73% rename from fastlane/lanes/ios rename to fastlane/lanes/ios.rb index e475e3284f..03b16f28e5 100644 --- a/fastlane/lanes/ios +++ b/fastlane/lanes/ios.rb @@ -3,21 +3,22 @@ require 'fileutils' require 'pathname' require 'shellwords' -fastlane_require "fastlane-plugin-stream_actions" +fastlane_require 'fastlane-plugin-stream_actions' +# rubocop:disable Metrics/BlockLength platform :ios do - desc "Sync dependencies and build the WebRTC iOS libraries" + desc 'Sync dependencies and build the WebRTC iOS libraries' lane :build do |options| options[:root] = Pathname.new(__dir__).join('..', '..', '..').expand_path - options[:build_root] = File.join(options[:root], ".output") - options[:products_root] = File.join(options[:root], ".products") - options[:sdk_name] = "WebRTC" + options[:build_root] = File.join(options[:root], '.output') + options[:products_root] = File.join(options[:root], '.products') + options[:sdk_name] = 'WebRTC' options[:product_source] = File.join(options[:root], "src/out_ios_libs/#{options[:sdk_name]}.xcframework") - options[:build_tool] = File.join(options[:root], "src/tools_webrtc/ios/build_ios_libs.py") + options[:build_tool] = File.join(options[:root], 'src/tools_webrtc/ios/build_ios_libs.py') options[:rename_to_sdk_name] = "Stream#{options[:sdk_name]}" options[:product] = File.join(options[:products_root], "#{options[:rename_to_sdk_name]}.xcframework") - options[:match_file] = File.join(options[:root], "src/fastlane/Matchfile") + options[:match_file] = File.join(options[:root], 'src/fastlane/Matchfile') catalyst_option = options.key?(:maccatalyst_support) ? options[:maccatalyst_support] : true options[:maccatalyst_support] = !%w[false 0 off no].include?(catalyst_option.to_s.downcase) @@ -31,6 +32,8 @@ log_info(message: "Mac Catalyst support: #{options[:maccatalyst_support]}") setup_ci if is_ci + setup_git_config if is_ci + clean_up_products(options) verify_environment(options) configure_google_client(options) @@ -44,16 +47,15 @@ end lane :clean_up_products do |options| - lane_options = extract_prefixed_options(options, "clean_up_products") + lane_options = extract_prefixed_options(options, 'clean_up_products') next unless lane_options[:skip] != true - log_debug(message: "Cleaning up products", verbose: options[:verbose]) + + log_debug(message: 'Cleaning up products', verbose: options[:verbose]) products_root = options[:products_root] - assert(message: "Missing required option :products_root") if products_root.to_s.strip.empty? + assert(message: 'Missing required option :products_root') if products_root.to_s.strip.empty? - unless Dir.exist?(products_root) - return - end + return unless Dir.exist?(products_root) log_info(message: "Cleaning products directory at #{products_root}") Dir.children(products_root).each do |entry| @@ -62,30 +64,26 @@ end lane :verify_environment do |options| - lane_options = extract_prefixed_options(options, "verify_environment") + lane_options = extract_prefixed_options(options, 'verify_environment') next unless lane_options[:skip] != true verify_build_environment(verbose: options[:verbose]) - ensure_required_tool(tool: "xcodebuild", verbose: options[:verbose]) - + ensure_required_tool(tool: 'xcodebuild', verbose: options[:verbose]) + # Check if we're on macOS - unless RUBY_PLATFORM.include?('darwin') - log_error(message: "iOS builds require macOS") - end + log_error(message: 'iOS builds require macOS') unless RUBY_PLATFORM.include?('darwin') # Check if Xcode is installed - unless system("xcode-select -p > /dev/null 2>&1") - log_error(message: "Xcode command line tools not found") - end + log_error(message: 'Xcode command line tools not found') unless system('xcode-select -p > /dev/null 2>&1') end lane :configure_google_client do |options| - lane_options = extract_prefixed_options(options, "configure_google_client") + lane_options = extract_prefixed_options(options, 'configure_google_client') next if lane_options[:skip] == true - target_os = ["ios"] - target_os << "mac" if options[:maccatalyst_support] + target_os = ['ios'] + target_os << 'mac' if options[:maccatalyst_support] log_info(message: "Configuring gclient target_os: #{target_os.join(', ')}") configure_gclient( @@ -97,14 +95,14 @@ end lane :build_product do |options| - lane_options = extract_prefixed_options(options, "build_product") + lane_options = extract_prefixed_options(options, 'build_product') next if lane_options[:skip] == true - deployment_target = options[:deployment_target] || "13.0" + deployment_target = options[:deployment_target] || '13.0' maccatalyst_support = options[:maccatalyst_support] args_list = resolve_build_product_args( - args: extract_prefixed_options(lane_options, "arg"), + args: extract_prefixed_options(lane_options, 'arg'), verbose: options[:verbose] ) @@ -112,11 +110,11 @@ Dir.chdir(options[:build_root]) do command_parts = ["\"#{script_path}\""] command_parts << "--deployment-target #{deployment_target}" - archs = ["device:arm64", "simulator:arm64", "simulator:x64"] - archs += ["catalyst:arm64", "catalyst:x64"] if maccatalyst_support - command_parts << "--arch" + archs = ['device:arm64', 'simulator:arm64', 'simulator:x64'] + archs += ['catalyst:arm64', 'catalyst:x64'] if maccatalyst_support + command_parts << '--arch' command_parts.concat(archs) - command_parts << "--extra-gn-args" + command_parts << '--extra-gn-args' command_parts.concat(args_list) execute_command( @@ -127,15 +125,15 @@ end lane :move_product do |options| - lane_options = extract_prefixed_options(options, "move_product") + lane_options = extract_prefixed_options(options, 'move_product') next if lane_options[:skip] == true product_source = options[:product_source] - assert(message: "Missing required option :product_source") if product_source.to_s.strip.empty? + assert(message: 'Missing required option :product_source') if product_source.to_s.strip.empty? assert(message: "Product not found at #{product_source}") unless File.exist?(product_source) product_destination = options[:products_root] - assert(message: "Missing required option :products_root") if product_destination.to_s.strip.empty? + assert(message: 'Missing required option :products_root') if product_destination.to_s.strip.empty? FileUtils.mkdir_p(product_destination) @@ -147,21 +145,21 @@ end lane :rename_product do |options| - lane_options = extract_prefixed_options(options, "rename_product") + lane_options = extract_prefixed_options(options, 'rename_product') next if lane_options[:skip] == true product_source = options[:product_source] - assert(message: "Missing required option :product_source") if product_source.to_s.strip.empty? + assert(message: 'Missing required option :product_source') if product_source.to_s.strip.empty? products_root = options[:products_root] - assert(message: "Missing required option :products_root") if products_root.to_s.strip.empty? - product_destination = File.join(products_root, File.basename(product_source)) - assert(message: "Missing required option :product_destination") if product_destination.to_s.strip.empty? + assert(message: 'Missing required option :products_root') if products_root.to_s.strip.empty? + product_destination = File.join(products_root, File.basename(product_source)) + assert(message: 'Missing required option :product_destination') if product_destination.to_s.strip.empty? assert(message: "Product not found at #{product_destination}") unless File.exist?(product_destination) sdk_name = options[:sdk_name] - assert(message: "Missing required option :sdk_name") if sdk_name.to_s.strip.empty? + assert(message: 'Missing required option :sdk_name') if sdk_name.to_s.strip.empty? modified_sdk_name = options[:rename_to_sdk_name] - assert(message: "Missing required option :rename_to_sdk_name") if modified_sdk_name.to_s.strip.empty? - + assert(message: 'Missing required option :rename_to_sdk_name') if modified_sdk_name.to_s.strip.empty? + old_framework_path = product_destination new_framework_path = File.join(products_root, "#{modified_sdk_name}.xcframework") @@ -194,7 +192,9 @@ end # Rename the rpath for all the frameworks and update symlinks if required + # rubocop:disable Metrics/LineLength framework_paths = new_framework_path.include?('.xcframework') ? Dir.glob("#{new_framework_path}/**/*.framework") : [new_framework_path] + # rubocop:enable Metrics/LineLength framework_paths.each do |path| Dir.chdir(path) do if File.symlink?(modified_sdk_name) @@ -212,7 +212,7 @@ end lane :prepare_signing do |options| - lane_options = extract_prefixed_options(options, "prepare_signing") + lane_options = extract_prefixed_options(options, 'prepare_signing') next unless lane_options[:skip] == true custom_match( @@ -223,32 +223,33 @@ end lane :sign_product do |options| - lane_options = extract_prefixed_options(options, "sign_product") + lane_options = extract_prefixed_options(options, 'sign_product') next if lane_options[:skip] == true - + matchfile = options[:match_file] - assert(message: "Missing required option :match_file") if matchfile.to_s.strip.empty? - + assert(message: 'Missing required option :match_file') if matchfile.to_s.strip.empty? + team_id = File.read(matchfile).match(/team_id\("(.*)"\)/)[1] frameworks = Dir.glob("#{options[:product]}/**/*.framework") + signing_identity = "'Apple Distribution: Stream.io Inc (#{team_id})'" frameworks.each do |framework| execute_command( - command: "/usr/bin/codesign --force --timestamp --deep -v --sign 'Apple Distribution: Stream.io Inc (#{team_id})' \"#{framework}\"", + command: "/usr/bin/codesign --force --timestamp --deep -v --sign #{signing_identity} \"#{framework}\"", verbose: options[:verbose] ) end end lane :verify_signatures do |options| - lane_options = extract_prefixed_options(options, "verify_signatures") + lane_options = extract_prefixed_options(options, 'verify_signatures') next if lane_options[:skip] == true product_path = options[:product] - assert(message: "Missing required option :product") if product_path.to_s.strip.empty? + assert(message: 'Missing required option :product') if product_path.to_s.strip.empty? assert(message: "Product not found at #{product_path}") unless File.exist?(product_path) frameworks = Dir.glob("#{product_path}/**/*.framework") - assert(message: "No frameworks found to validate signatures") if frameworks.empty? + assert(message: 'No frameworks found to validate signatures') if frameworks.empty? log_info(message: "Validating code signatures for #{frameworks.count} frameworks") @@ -261,7 +262,7 @@ end lane :zip_product do |options| - lane_options = extract_prefixed_options(options, "zip_product") + lane_options = extract_prefixed_options(options, 'zip_product') next if lane_options[:skip] == true file_path = options[:product] @@ -273,21 +274,24 @@ zip_path end - desc "Compute a checksum for the packaged xcframework zip" + desc 'Compute a checksum for the packaged xcframework zip' lane :compute_zip_checksum do |options| - lane_options = extract_prefixed_options(options, "compute_zip_checksum") + lane_options = extract_prefixed_options(options, 'compute_zip_checksum') next if lane_options[:skip] == true - ensure_required_tool(tool: "swift", verbose: options[:verbose]) + ensure_required_tool(tool: 'swift', verbose: options[:verbose]) zip_path = lane_options[:zip_path] || options[:zip_path] if zip_path.to_s.strip.empty? products_root = options[:products_root] rename_to_sdk_name = options[:rename_to_sdk_name] - zip_path = File.join(products_root, "#{rename_to_sdk_name}.zip") unless products_root.to_s.strip.empty? || rename_to_sdk_name.to_s.strip.empty? + unless products_root.to_s.strip.empty? || rename_to_sdk_name.to_s.strip.empty? + zip_path = File.join(products_root, + "#{rename_to_sdk_name}.zip") + end end - assert(message: "Missing required option :zip_path") if zip_path.to_s.strip.empty? + assert(message: 'Missing required option :zip_path') if zip_path.to_s.strip.empty? assert(message: "Zip file not found at #{zip_path}") unless File.exist?(zip_path) command = "swift package compute-checksum #{Shellwords.escape(zip_path)}" @@ -304,7 +308,7 @@ args = options[:args] || {} provided_args = [] - + arg_options = args.each_with_object({}) do |(key, value), memo| key_str = key.to_s @@ -314,15 +318,15 @@ end arg_options.each do |key, value| - value_str = value.is_a?(TrueClass) || value.is_a?(FalseClass) ? value.to_s : value.to_s + value_str = value.to_s provided_args << "#{key}=#{value_str}" end default_args = { - "is_debug" => "false", - "use_goma" => "false", - "use_rtti" => "false", - "rtc_libvpx_build_vp9" => "true" + 'is_debug' => 'false', + 'use_goma' => 'false', + 'use_rtti' => 'false', + 'rtc_libvpx_build_vp9' => 'true' } args_map = default_args.dup @@ -368,3 +372,4 @@ ) end end +# rubocop:enable Metrics/BlockLength diff --git a/fastlane/lanes/utilities b/fastlane/lanes/utilities deleted file mode 100644 index 3b6992ea5d..0000000000 --- a/fastlane/lanes/utilities +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -private_lane :verify_build_environment do |options| - log_debug( - message: "Verifying build environment...", - verbose: options[:verbose] - ) - - # Check if required tools are available - ensure_required_tool(tool: "gclient", verbose: options[:verbose]) - ensure_required_tool(tool: "python3", verbose: options[:verbose]) - - UI.success("Build environment verified successfully") -end - -private_lane :log_debug do |options| - UI.message(options[:message]) if options[:verbose] -end - -private_lane :log_info do |options| - UI.message(options[:message]) -end - -private_lane :log_success do |options| - UI.success(options[:message]) -end - -private_lane :log_error do |options| - UI.error(options[:message]) -end - -private_lane :assert do |options| - UI.abort_with_message!(options[:message]) -end - -private_lane :ensure_required_tool do |options| - tool = options[:tool] - unless system("which #{tool} > /dev/null 2>&1") - UI.user_error!("Required tool '#{tool}' not found in PATH") - end -end - -private_lane :execute_command do |options| - sh( - options[:command], - print_command: true, - print_command_output: options[:verbose] - ) -end - -def extract_prefixed_options(options, prefix) - return {} if options.nil? - - prefix = prefix.to_s - return {} if prefix.empty? - - prefix = prefix.end_with?('_') ? prefix : "#{prefix}_" - - options.each_with_object({}) do |(key, value), extracted| - next if value.nil? - - key_str = key.to_s - next unless key_str.start_with?(prefix) - - stripped_key = key_str.sub(prefix, '') - extracted[stripped_key.to_sym] = value - end -end - diff --git a/fastlane/lanes/utilities.rb b/fastlane/lanes/utilities.rb new file mode 100644 index 0000000000..89f5756d33 --- /dev/null +++ b/fastlane/lanes/utilities.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +# rubocop:disable Metrics/MethodLength +private_lane :verify_build_environment do |options| + log_debug( + message: 'Verifying build environment...', + verbose: options[:verbose] + ) + + # Check if required tools are available + ensure_required_tool(tool: 'gclient', verbose: options[:verbose]) + ensure_required_tool(tool: 'python3', verbose: options[:verbose]) + + UI.success('Build environment verified successfully') +end + +private_lane :log_debug do |options| + UI.message(options[:message]) if options[:verbose] +end + +private_lane :log_info do |options| + UI.message(options[:message]) +end + +private_lane :log_success do |options| + UI.success(options[:message]) +end + +private_lane :log_error do |options| + UI.error(options[:message]) +end + +private_lane :assert do |options| + UI.abort_with_message!(options[:message]) +end + +private_lane :ensure_required_tool do |options| + tool = options[:tool] + UI.user_error!("Required tool '#{tool}' not found in PATH") unless system("which #{tool} > /dev/null 2>&1") +end + +private_lane :execute_command do |options| + sh( + options[:command], + print_command: true, + print_command_output: options[:verbose] + ) +end + +def extract_prefixed_options(options, prefix) + return {} if options.nil? + + prefix = prefix.to_s + return {} if prefix.empty? + + prefix = prefix.end_with?('_') ? prefix : "#{prefix}_" + + options.each_with_object({}) do |(key, value), extracted| + next if value.nil? + + key_str = key.to_s + next unless key_str.start_with?(prefix) + + stripped_key = key_str.sub(prefix, '') + extracted[stripped_key.to_sym] = value + end +end +# rubocop:enable Metrics/MethodLength diff --git a/fastlane/report.xml b/fastlane/report.xml index 34e6fc0c18..ef5ff1c031 100644 --- a/fastlane/report.xml +++ b/fastlane/report.xml @@ -5,12 +5,12 @@ - + - + @@ -30,107 +30,112 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + +'" time="0.956599"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + From 11b8ec1045dc8471004d9bc2359a99d1f3d14526 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 1 Oct 2025 17:01:03 +0300 Subject: [PATCH 3/5] Address feedback vol.2 --- fastlane/.env | 7 ++ fastlane/.rubocop.yml | 170 ++++++++++++++++++++++++++++++++++ fastlane/Fastfile | 7 ++ fastlane/Gemfile | 7 +- fastlane/Gemfile.lock | 24 +++-- fastlane/Pluginfile | 2 +- fastlane/build_xcframework.sh | 24 ----- fastlane/lanes/gclient.rb | 2 - fastlane/lanes/ios.rb | 7 -- fastlane/lanes/utilities.rb | 2 - 10 files changed, 205 insertions(+), 47 deletions(-) create mode 100644 fastlane/.env create mode 100644 fastlane/.rubocop.yml delete mode 100755 fastlane/build_xcframework.sh diff --git a/fastlane/.env b/fastlane/.env new file mode 100644 index 0000000000..6230f91510 --- /dev/null +++ b/fastlane/.env @@ -0,0 +1,7 @@ + +FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT=180 +FASTLANE_XCODEBUILD_SETTINGS_RETRIES=10 +FASTLANE_SKIP_ACTION_SUMMARY=true +FASTLANE_HIDE_PLUGINS_TABLE=true +FASTLANE_SKIP_UPDATE_CHECK=true +FASTLANE_HIDE_CHANGELOG=true diff --git a/fastlane/.rubocop.yml b/fastlane/.rubocop.yml new file mode 100644 index 0000000000..8336cfa33a --- /dev/null +++ b/fastlane/.rubocop.yml @@ -0,0 +1,170 @@ +--- +require: +- rubocop/require_tools +- rubocop-performance +AllCops: + TargetRubyVersion: 2.4 + NewCops: enable + Include: + - "**/*.rb" + - "**/*file" +Style/MultipleComparison: + Enabled: false +Style/PercentLiteralDelimiters: + Enabled: false +Style/ClassCheck: + EnforcedStyle: kind_of? +Style/FrozenStringLiteralComment: + Enabled: false +Style/SafeNavigation: + Enabled: false +Performance/RegexpMatch: + Enabled: false +Performance/StringReplacement: + Enabled: false +Style/NumericPredicate: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Naming/VariableNumber: + Enabled: false +Style/MissingRespondToMissing: + Enabled: false +Style/MultilineBlockChain: + Enabled: false +Style/NumericLiteralPrefix: + Enabled: false +Style/TernaryParentheses: + Enabled: false +Style/EmptyMethod: + Enabled: false +Lint/UselessAssignment: + Exclude: + - "**/spec/**/*" +Require/MissingRequireStatement: + Enabled: false +Layout/FirstHashElementIndentation: + Enabled: false +Layout/HashAlignment: + Enabled: false +Style/HashLikeCase: + Enabled: false +Layout/DotPosition: + Enabled: false +Style/DoubleNegation: + Enabled: false +Style/SymbolArray: + Enabled: false +Layout/HeredocIndentation: + Enabled: false +Style/MixinGrouping: + Exclude: + - "**/spec/**/*" +Lint/SuppressedException: + Enabled: false +Lint/UnusedBlockArgument: + Enabled: false +Lint/AmbiguousBlockAssociation: + Enabled: false +Style/GlobalVars: + Enabled: false +Style/ClassAndModuleChildren: + Enabled: false +Style/SpecialGlobalVars: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Style/WordArray: + MinSize: 19 +Style/SignalException: + Enabled: false +Style/RedundantReturn: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/AndOr: + Enabled: true + EnforcedStyle: conditionals +Metrics/ClassLength: + Max: 320 +Layout/LineLength: + Max: 370 +Metrics/ParameterLists: + Max: 17 +Metrics/PerceivedComplexity: + Max: 20 +Style/GuardClause: + Enabled: false +Style/StringLiterals: + Enabled: false +Style/ConditionalAssignment: + Enabled: false +Style/RedundantSelf: + Enabled: false +Lint/UnusedMethodArgument: + Enabled: false +Lint/ParenthesesAsGroupedExpression: + Exclude: + - "**/spec/**/*" +Naming/PredicateName: + Enabled: false +Style/PerlBackrefs: + Enabled: false +Naming/FileName: + Exclude: + - "**/Dangerfile" + - "**/Brewfile" + - "**/Gemfile" + - "**/Podfile" + - "**/Rakefile" + - "**/Fastfile" + - "**/Scanfile" + - "**/Matchfile" + - "**/Appfile" + - "**/Allurefile" + - "**/Sonarfile" + - "**/Deliverfile" + - "**/Snapfile" + - "**/Pluginfile" + - "**/*.gemspec" +Style/Documentation: + Enabled: false +Style/MutableConstant: + Enabled: false +Style/ZeroLengthPredicate: + Enabled: false +Style/IfInsideElse: + Enabled: false +Style/CollectionMethods: + Enabled: false +Style/MethodCallWithArgsParentheses: + Enabled: true + IgnoredMethods: + - require + - require_relative + - fastlane_require + - gem + - program + - command + - raise + - attr_accessor + - attr_reader + - desc + - lane + - private_lane + - platform + - to + - not_to + - describe + - it + - be + - context + - before + - after + - and diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 1dd49ed40e..d8a0c9e69e 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,6 +1,7 @@ # frozen_string_literal: true skip_docs +opt_out_usage require 'json' require 'net/http' @@ -9,3 +10,9 @@ require 'fileutils' import './lanes/utilities.rb' import './lanes/gclient.rb' import './lanes/ios.rb' + +before_all do |lane| + setup_ci if is_ci + setup_git_config if is_ci + sh('bundle exec rubocop') if is_ci +end \ No newline at end of file diff --git a/fastlane/Gemfile b/fastlane/Gemfile index 3e35d8127c..84b2e83947 100644 --- a/fastlane/Gemfile +++ b/fastlane/Gemfile @@ -8,7 +8,12 @@ gem 'cocoapods' gem 'fastlane' gem 'json' gem 'plist' -gem 'rubocop' +gem 'rubocop', '1.38', group: :rubocop_dependencies + +group :rubocop_dependencies do + gem 'rubocop-performance' + gem 'rubocop-require_tools' +end plugins_path = File.join(File.dirname(__FILE__), 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock index a870259fac..ca382cea64 100644 --- a/fastlane/Gemfile.lock +++ b/fastlane/Gemfile.lock @@ -228,8 +228,6 @@ GEM json (2.13.0) jwt (2.10.2) base64 - language_server-protocol (3.17.0.5) - lint_roller (1.1.0) logger (1.7.0) mini_magick (4.13.2) mini_mime (1.1.5) @@ -263,20 +261,24 @@ GEM retriable (3.1.2) rexml (3.4.1) rouge (3.28.0) - rubocop (1.81.1) + rubocop (1.38.0) json (~> 2.3) - language_server-protocol (~> 3.17.0.2) - lint_roller (~> 1.1.0) parallel (~> 1.10) - parser (>= 3.3.0.2) + parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.47.1, < 2.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.23.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 4.0) + unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.47.1) parser (>= 3.3.7.2) prism (~> 1.4) + rubocop-performance (1.19.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-require_tools (0.1.2) + rubocop (>= 0.49.1) ruby-macho (2.5.1) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) @@ -329,7 +331,9 @@ DEPENDENCIES fastlane-plugin-stream_actions (= 0.3.90) json plist - rubocop + rubocop (= 1.38) + rubocop-performance + rubocop-require_tools BUNDLED WITH 2.3.3 diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile index 76c87679b1..f545710b61 100644 --- a/fastlane/Pluginfile +++ b/fastlane/Pluginfile @@ -2,4 +2,4 @@ # # Ensure this file is checked in to source control! -gem 'fastlane-plugin-stream_actions', '0.3.90' \ No newline at end of file +gem 'fastlane-plugin-stream_actions', '0.3.90' diff --git a/fastlane/build_xcframework.sh b/fastlane/build_xcframework.sh deleted file mode 100755 index a26887ea72..0000000000 --- a/fastlane/build_xcframework.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -gclient root -gclient config --spec 'solutions = [ -{ - "name": "src", - "url": "git@github.com:GetStream/webrtc.git", - "deps_file": "DEPS", - "managed": False, - "custom_deps": {}, -}, -] -target_os = ["ios", "mac"] -' -gclient sync -j8 -v - -cd src -./tools_webrtc/ios/build_ios_libs.py \ - --deployment-target 13.0 \ - --extra-gn-args \ - is_debug=false \ - use_goma=false \ - use_rtti=false \ - rtc_libvpx_build_vp9=true \ No newline at end of file diff --git a/fastlane/lanes/gclient.rb b/fastlane/lanes/gclient.rb index be51556f2e..29baadaf08 100644 --- a/fastlane/lanes/gclient.rb +++ b/fastlane/lanes/gclient.rb @@ -2,7 +2,6 @@ require 'fileutils' -# rubocop:disable Metrics/BlockLength private_lane :configure_gclient do |options| log_debug( message: 'Configuring gclient...', @@ -51,7 +50,6 @@ ) end end -# rubocop:enable Metrics/BlockLength private_lane :sync_dependencies do |options| jobs = options[:number_of_jobs] || 8 diff --git a/fastlane/lanes/ios.rb b/fastlane/lanes/ios.rb index 03b16f28e5..013a486a3d 100644 --- a/fastlane/lanes/ios.rb +++ b/fastlane/lanes/ios.rb @@ -5,7 +5,6 @@ require 'shellwords' fastlane_require 'fastlane-plugin-stream_actions' -# rubocop:disable Metrics/BlockLength platform :ios do desc 'Sync dependencies and build the WebRTC iOS libraries' @@ -31,9 +30,6 @@ log_info(message: "Product: #{options[:product]}") log_info(message: "Mac Catalyst support: #{options[:maccatalyst_support]}") - setup_ci if is_ci - setup_git_config if is_ci - clean_up_products(options) verify_environment(options) configure_google_client(options) @@ -192,9 +188,7 @@ end # Rename the rpath for all the frameworks and update symlinks if required - # rubocop:disable Metrics/LineLength framework_paths = new_framework_path.include?('.xcframework') ? Dir.glob("#{new_framework_path}/**/*.framework") : [new_framework_path] - # rubocop:enable Metrics/LineLength framework_paths.each do |path| Dir.chdir(path) do if File.symlink?(modified_sdk_name) @@ -372,4 +366,3 @@ ) end end -# rubocop:enable Metrics/BlockLength diff --git a/fastlane/lanes/utilities.rb b/fastlane/lanes/utilities.rb index 89f5756d33..3a13914857 100644 --- a/fastlane/lanes/utilities.rb +++ b/fastlane/lanes/utilities.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -# rubocop:disable Metrics/MethodLength private_lane :verify_build_environment do |options| log_debug( message: 'Verifying build environment...', @@ -65,4 +64,3 @@ def extract_prefixed_options(options, prefix) extracted[stripped_key.to_sym] = value end end -# rubocop:enable Metrics/MethodLength From ddd99f25e654005908d052e5de8f26c33ddfce27 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 1 Oct 2025 17:13:43 +0300 Subject: [PATCH 4/5] Address feedback vol.3 --- fastlane/Fastfile | 14 +- fastlane/Gemfile | 2 - fastlane/Gemfile.lock | 339 --------------------------------- fastlane/lanes/gclient.rb | 2 - fastlane/lanes/ios.rb | 5 +- fastlane/lanes/utilities.rb | 2 - fastlane/report.xml | 363 ------------------------------------ 7 files changed, 8 insertions(+), 719 deletions(-) delete mode 100644 fastlane/Gemfile.lock delete mode 100644 fastlane/report.xml diff --git a/fastlane/Fastfile b/fastlane/Fastfile index d8a0c9e69e..78eda3a824 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,5 +1,3 @@ -# frozen_string_literal: true - skip_docs opt_out_usage @@ -11,8 +9,10 @@ import './lanes/utilities.rb' import './lanes/gclient.rb' import './lanes/ios.rb' -before_all do |lane| - setup_ci if is_ci - setup_git_config if is_ci - sh('bundle exec rubocop') if is_ci -end \ No newline at end of file +before_all do + if is_ci + setup_ci + setup_git_config + end + sh('bundle exec rubocop') +end diff --git a/fastlane/Gemfile b/fastlane/Gemfile index 84b2e83947..5371f20543 100644 --- a/fastlane/Gemfile +++ b/fastlane/Gemfile @@ -1,5 +1,3 @@ -# frozen_string_literal: true - source 'https://rubygems.org' git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock deleted file mode 100644 index ca382cea64..0000000000 --- a/fastlane/Gemfile.lock +++ /dev/null @@ -1,339 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.7) - base64 - nkf - rexml - activesupport (7.2.2.1) - base64 - benchmark (>= 0.3) - bigdecimal - concurrent-ruby (~> 1.0, >= 1.3.1) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - logger (>= 1.4.2) - minitest (>= 5.1) - securerandom (>= 0.3) - tzinfo (~> 2.0, >= 2.0.5) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) - algoliasearch (1.27.5) - httpclient (~> 2.8, >= 2.8.3) - json (>= 1.5.1) - artifactory (3.0.17) - ast (2.4.3) - atomos (0.1.3) - aws-eventstream (1.4.0) - aws-partitions (1.1131.0) - aws-sdk-core (3.226.3) - aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.992.0) - aws-sigv4 (~> 1.9) - base64 - jmespath (~> 1, >= 1.6.1) - logger - aws-sdk-kms (1.106.0) - aws-sdk-core (~> 3, >= 3.225.0) - aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.193.0) - aws-sdk-core (~> 3, >= 3.225.0) - aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.5) - aws-sigv4 (1.12.1) - aws-eventstream (~> 1, >= 1.0.2) - babosa (1.0.4) - base64 (0.3.0) - benchmark (0.4.1) - bigdecimal (3.2.2) - claide (1.1.0) - cocoapods (1.16.2) - addressable (~> 2.8) - claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.16.2) - cocoapods-deintegrate (>= 1.0.3, < 2.0) - cocoapods-downloader (>= 2.1, < 3.0) - cocoapods-plugins (>= 1.0.0, < 2.0) - cocoapods-search (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.6.0, < 2.0) - cocoapods-try (>= 1.1.0, < 2.0) - colored2 (~> 3.1) - escape (~> 0.0.4) - fourflusher (>= 2.3.0, < 3.0) - gh_inspector (~> 1.0) - molinillo (~> 0.8.0) - nap (~> 1.0) - ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.27.0, < 2.0) - cocoapods-core (1.16.2) - activesupport (>= 5.0, < 8) - addressable (~> 2.8) - algoliasearch (~> 1.0) - concurrent-ruby (~> 1.1) - fuzzy_match (~> 2.0.4) - nap (~> 1.0) - netrc (~> 0.11) - public_suffix (~> 4.0) - typhoeus (~> 1.0) - cocoapods-deintegrate (1.0.5) - cocoapods-downloader (2.1) - cocoapods-plugins (1.0.0) - nap - cocoapods-search (1.0.1) - cocoapods-trunk (1.6.0) - nap (>= 0.8, < 2.0) - netrc (~> 0.11) - cocoapods-try (1.2.0) - colored (1.2) - colored2 (3.1.2) - commander (4.6.0) - highline (~> 2.0.0) - concurrent-ruby (1.3.5) - connection_pool (2.5.3) - declarative (0.0.20) - digest-crc (0.7.0) - rake (>= 12.0.0, < 14.0.0) - domain_name (0.6.20240107) - dotenv (2.8.1) - drb (2.2.3) - emoji_regex (3.2.3) - escape (0.0.4) - ethon (0.16.0) - ffi (>= 1.15.0) - excon (0.112.0) - faraday (1.10.4) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0) - faraday-multipart (~> 1.0) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - faraday-retry (~> 1.0) - ruby2_keywords (>= 0.0.4) - faraday-cookie_jar (0.0.7) - faraday (>= 0.8.0) - http-cookie (~> 1.0.0) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.1) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-multipart (1.1.1) - multipart-post (~> 2.0) - faraday-net_http (1.0.2) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - faraday-retry (1.0.3) - faraday_middleware (1.2.1) - faraday (~> 1.0) - fastimage (2.4.0) - fastlane (2.228.0) - CFPropertyList (>= 2.3, < 4.0.0) - addressable (>= 2.8, < 3.0.0) - artifactory (~> 3.0) - aws-sdk-s3 (~> 1.0) - babosa (>= 1.0.3, < 2.0.0) - bundler (>= 1.12.0, < 3.0.0) - colored (~> 1.2) - commander (~> 4.6) - dotenv (>= 2.1.1, < 3.0.0) - emoji_regex (>= 0.1, < 4.0) - excon (>= 0.71.0, < 1.0.0) - faraday (~> 1.0) - faraday-cookie_jar (~> 0.0.6) - faraday_middleware (~> 1.0) - fastimage (>= 2.1.0, < 3.0.0) - fastlane-sirp (>= 1.0.0) - gh_inspector (>= 1.1.2, < 2.0.0) - google-apis-androidpublisher_v3 (~> 0.3) - google-apis-playcustomapp_v1 (~> 0.1) - google-cloud-env (>= 1.6.0, < 2.0.0) - google-cloud-storage (~> 1.31) - highline (~> 2.0) - http-cookie (~> 1.0.5) - json (< 3.0.0) - jwt (>= 2.1.0, < 3) - mini_magick (>= 4.9.4, < 5.0.0) - multipart-post (>= 2.0.0, < 3.0.0) - naturally (~> 2.2) - optparse (>= 0.1.1, < 1.0.0) - plist (>= 3.1.0, < 4.0.0) - rubyzip (>= 2.0.0, < 3.0.0) - security (= 0.1.5) - simctl (~> 1.6.3) - terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (~> 3) - tty-screen (>= 0.6.3, < 1.0.0) - tty-spinner (>= 0.8.0, < 1.0.0) - word_wrap (~> 1.0.0) - xcodeproj (>= 1.13.0, < 2.0.0) - xcpretty (~> 0.4.1) - xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-plugin-stream_actions (0.3.90) - xctest_list (= 1.2.1) - fastlane-sirp (1.0.0) - sysrandom (~> 1.0) - ffi (1.17.2-arm64-darwin) - fourflusher (2.3.1) - fuzzy_match (2.0.4) - gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.54.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.3) - addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) - mini_mime (~> 1.0) - representable (~> 3.0) - retriable (>= 2.0, < 4.a) - rexml - google-apis-iamcredentials_v1 (0.17.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-playcustomapp_v1 (0.13.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.31.0) - google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.8.0) - google-cloud-env (>= 1.0, < 3.a) - google-cloud-errors (~> 1.0) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.5.0) - google-cloud-storage (1.47.0) - addressable (~> 2.8) - digest-crc (~> 0.4) - google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.31.0) - google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) - mini_mime (~> 1.0) - googleauth (1.8.1) - faraday (>= 0.17.3, < 3.a) - jwt (>= 1.4, < 3.0) - multi_json (~> 1.11) - os (>= 0.9, < 2.0) - signet (>= 0.16, < 2.a) - highline (2.0.3) - http-cookie (1.0.8) - domain_name (~> 0.5) - httpclient (2.9.0) - mutex_m - i18n (1.14.7) - concurrent-ruby (~> 1.0) - jmespath (1.6.2) - json (2.13.0) - jwt (2.10.2) - base64 - logger (1.7.0) - mini_magick (4.13.2) - mini_mime (1.1.5) - minitest (5.25.5) - molinillo (0.8.0) - multi_json (1.17.0) - multipart-post (2.4.1) - mutex_m (0.3.0) - nanaimo (0.4.0) - nap (1.1.0) - naturally (2.3.0) - netrc (0.11.0) - nkf (0.2.0) - optparse (0.6.0) - os (1.1.4) - parallel (1.27.0) - parser (3.3.9.0) - ast (~> 2.4.1) - racc - plist (3.7.2) - prism (1.5.1) - public_suffix (4.0.7) - racc (1.8.1) - rainbow (3.1.1) - rake (13.3.0) - regexp_parser (2.11.3) - representable (3.2.0) - declarative (< 0.1.0) - trailblazer-option (>= 0.1.1, < 0.2.0) - uber (< 0.2.0) - retriable (3.1.2) - rexml (3.4.1) - rouge (3.28.0) - rubocop (1.38.0) - json (~> 2.3) - parallel (~> 1.10) - parser (>= 3.1.2.1) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.23.0, < 2.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.47.1) - parser (>= 3.3.7.2) - prism (~> 1.4) - rubocop-performance (1.19.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-require_tools (0.1.2) - rubocop (>= 0.49.1) - ruby-macho (2.5.1) - ruby-progressbar (1.13.0) - ruby2_keywords (0.0.5) - rubyzip (2.4.1) - securerandom (0.4.1) - security (0.1.5) - signet (0.20.0) - addressable (~> 2.8) - faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 3.0) - multi_json (~> 1.10) - simctl (1.6.10) - CFPropertyList - naturally - sysrandom (1.0.5) - terminal-notifier (2.0.0) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) - trailblazer-option (0.1.2) - tty-cursor (0.7.1) - tty-screen (0.8.2) - tty-spinner (0.9.3) - tty-cursor (~> 0.7) - typhoeus (1.4.1) - ethon (>= 0.9.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - uber (0.1.0) - unicode-display_width (2.6.0) - word_wrap (1.0.0) - xcodeproj (1.27.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.4.0) - rexml (>= 3.3.6, < 4.0) - xcpretty (0.4.1) - rouge (~> 3.28.0) - xcpretty-travis-formatter (1.0.1) - xcpretty (~> 0.2, >= 0.0.7) - xctest_list (1.2.1) - -PLATFORMS - arm64-darwin-24 - -DEPENDENCIES - cocoapods - fastlane - fastlane-plugin-stream_actions (= 0.3.90) - json - plist - rubocop (= 1.38) - rubocop-performance - rubocop-require_tools - -BUNDLED WITH - 2.3.3 diff --git a/fastlane/lanes/gclient.rb b/fastlane/lanes/gclient.rb index 29baadaf08..751b621e4b 100644 --- a/fastlane/lanes/gclient.rb +++ b/fastlane/lanes/gclient.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require 'fileutils' private_lane :configure_gclient do |options| diff --git a/fastlane/lanes/ios.rb b/fastlane/lanes/ios.rb index 013a486a3d..3c8d079794 100644 --- a/fastlane/lanes/ios.rb +++ b/fastlane/lanes/ios.rb @@ -1,7 +1,4 @@ -# frozen_string_literal: true - require 'fileutils' -require 'pathname' require 'shellwords' fastlane_require 'fastlane-plugin-stream_actions' @@ -9,7 +6,7 @@ desc 'Sync dependencies and build the WebRTC iOS libraries' lane :build do |options| - options[:root] = Pathname.new(__dir__).join('..', '..', '..').expand_path + options[:root] = File.expand_path('../../..', __dir__) options[:build_root] = File.join(options[:root], '.output') options[:products_root] = File.join(options[:root], '.products') options[:sdk_name] = 'WebRTC' diff --git a/fastlane/lanes/utilities.rb b/fastlane/lanes/utilities.rb index 3a13914857..18654a64b3 100644 --- a/fastlane/lanes/utilities.rb +++ b/fastlane/lanes/utilities.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - private_lane :verify_build_environment do |options| log_debug( message: 'Verifying build environment...', diff --git a/fastlane/report.xml b/fastlane/report.xml deleted file mode 100644 index ef5ff1c031..0000000000 --- a/fastlane/report.xml +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From bb35640bf1c617432154ead342cc9238dbb6d9f9 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 1 Oct 2025 17:22:51 +0300 Subject: [PATCH 5/5] Update Gemfile --- .gitignore | 1 - fastlane/Gemfile.lock | 340 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 fastlane/Gemfile.lock diff --git a/.gitignore b/.gitignore index a0394baba1..238501bf44 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,5 @@ # Stream specifics fastlane/vendor -fastlane/Gemfile.lock fastlane/*.xml out_ios_libs diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock new file mode 100644 index 0000000000..29164fce8e --- /dev/null +++ b/fastlane/Gemfile.lock @@ -0,0 +1,340 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + activesupport (7.2.2.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + artifactory (3.0.17) + ast (2.4.3) + atomos (0.1.3) + aws-eventstream (1.4.0) + aws-partitions (1.1168.0) + aws-sdk-core (3.233.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 + bigdecimal + jmespath (~> 1, >= 1.6.1) + logger + aws-sdk-kms (1.113.0) + aws-sdk-core (~> 3, >= 3.231.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.199.1) + aws-sdk-core (~> 3, >= 3.231.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.12.1) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.3.0) + benchmark (0.4.1) + bigdecimal (3.2.3) + claide (1.1.0) + cocoapods (1.16.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.16.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.27.0, < 2.0) + cocoapods-core (1.16.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + concurrent-ruby (1.3.5) + connection_pool (2.5.4) + declarative (0.0.20) + digest-crc (0.7.0) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.6.20240107) + dotenv (2.8.1) + drb (2.2.3) + emoji_regex (3.2.3) + escape (0.0.4) + ethon (0.15.0) + ffi (>= 1.15.0) + excon (0.112.0) + faraday (1.10.4) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.1) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.1.1) + multipart-post (~> 2.0) + faraday-net_http (1.0.2) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.1) + faraday (~> 1.0) + fastimage (2.4.0) + fastlane (2.228.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored (~> 1.2) + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (>= 0.1.1, < 1.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.5) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.4.1) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-plugin-stream_actions (0.3.90) + xctest_list (= 1.2.1) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) + ffi (1.17.2-arm64-darwin) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.54.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.3) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.31.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.8.0) + google-cloud-env (>= 1.0, < 3.a) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.5.0) + google-cloud-storage (1.47.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.31.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.8) + domain_name (~> 0.5) + httpclient (2.9.0) + mutex_m + i18n (1.14.7) + concurrent-ruby (~> 1.0) + jmespath (1.6.2) + json (2.15.0) + jwt (2.10.2) + base64 + logger (1.7.0) + mini_magick (4.13.2) + mini_mime (1.1.5) + minitest (5.25.5) + molinillo (0.8.0) + multi_json (1.17.0) + multipart-post (2.4.1) + mutex_m (0.3.0) + nanaimo (0.4.0) + nap (1.1.0) + naturally (2.3.0) + netrc (0.11.0) + nkf (0.2.0) + optparse (0.6.0) + os (1.1.4) + parallel (1.27.0) + parser (3.3.9.0) + ast (~> 2.4.1) + racc + plist (3.7.2) + prism (1.5.1) + public_suffix (4.0.7) + racc (1.8.1) + rainbow (3.1.1) + rake (13.3.0) + regexp_parser (2.11.3) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.4.4) + rouge (3.28.0) + rubocop (1.38.0) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.1.2.1) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.23.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.47.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-performance (1.19.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-require_tools (0.1.2) + rubocop (>= 0.49.1) + ruby-macho (2.5.1) + ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) + rubyzip (2.4.1) + securerandom (0.4.1) + security (0.1.5) + signet (0.21.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 4.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + sysrandom (1.0.5) + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.2) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + typhoeus (1.5.0) + ethon (>= 0.9.0, < 0.16.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uber (0.1.0) + unicode-display_width (2.6.0) + word_wrap (1.0.0) + xcodeproj (1.27.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) + xcpretty (0.4.1) + rouge (~> 3.28.0) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + xctest_list (1.2.1) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods + fastlane + fastlane-plugin-stream_actions (= 0.3.90) + json + plist + rubocop (= 1.38) + rubocop-performance + rubocop-require_tools + +BUNDLED WITH + 2.3.3