From d1690fe01bc637e47aa6fca29677652099ffe893 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Mon, 11 Aug 2025 02:23:51 +0300 Subject: [PATCH 1/9] feat: Handling rubcop to be used normally for formatting out plugin --- .rubocop.yml | 10 ++++-- ...lane-plugin-instabug-stores-upload.gemspec | 1 + fastlane/Fastfile | 32 +++++++++---------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 0a5cec9..0c49799 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,7 +3,7 @@ require: - rubocop/require_tools - rubocop-performance AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 3.2.2 NewCops: enable Include: - "**/*.rb" @@ -70,6 +70,7 @@ Require/MissingRequireStatement: - "**/Rakefile" - fastlane/**/* - supply/**/* + - "lib/fastlane/plugin/**/*.rb" Layout/FirstHashElementIndentation: Enabled: false Layout/HashAlignment: @@ -87,6 +88,8 @@ Style/MixinGrouping: - "**/spec/**/*" Lint/SuppressedException: Enabled: false +Lint/IneffectiveAccessModifier: + Enabled: false Lint/UnusedBlockArgument: Enabled: false Lint/AmbiguousBlockAssociation: @@ -120,6 +123,8 @@ Layout/LineLength: Max: 370 Metrics/ParameterLists: Max: 17 +Metrics/PerceivedComplexity: + Max: 10 Style/GuardClause: Enabled: false Style/StringLiterals: @@ -192,5 +197,4 @@ Bundler/OrderedGems: Enabled: true TreatCommentsAsGroupSeparators: false Gemspec/DevelopmentDependencies: - Enabled: true - EnforcedStyle: Gemfile + Enabled: false diff --git a/fastlane-plugin-instabug-stores-upload.gemspec b/fastlane-plugin-instabug-stores-upload.gemspec index 899ae23..e83ff83 100644 --- a/fastlane-plugin-instabug-stores-upload.gemspec +++ b/fastlane-plugin-instabug-stores-upload.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rspec' spec.add_development_dependency 'rake' spec.add_development_dependency 'rubocop', '1.50.2' + spec.add_development_dependency 'rubocop-performance' spec.add_development_dependency 'rubocop-require_tools' spec.add_development_dependency 'simplecov' spec.add_development_dependency 'fastlane', '~> 2.228.0' diff --git a/fastlane/Fastfile b/fastlane/Fastfile index d02d45a..ed491e0 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -3,10 +3,10 @@ # Example lane for building iOS app with Instabug reporting lane :build_ios_app do |options| branch_name = options[:branch_name] - + instabug_build_ios_app( - branch_name: branch_name, - instabug_api_key: ENV["INSTABUG_API_KEY"], + branch_name:, + instabug_api_key: ENV.fetch("INSTABUG_API_KEY", nil), # All standard build_ios_app parameters are supported workspace: "MyApp.xcworkspace", scheme: "MyApp", @@ -18,18 +18,18 @@ end # Example lane for building Android app with Instabug reporting lane :build_android_app do |options| branch_name = options[:branch_name] - + instabug_build_android_app( - branch_name: branch_name, - instabug_api_key: ENV["INSTABUG_API_KEY"], + branch_name:, + instabug_api_key: ENV.fetch("INSTABUG_API_KEY", nil), # All standard gradle parameters are supported task: "assembleRelease", project_dir: "android/", properties: { "android.injected.signing.store.file" => "keystore.jks", - "android.injected.signing.store.password" => ENV["KEYSTORE_PASSWORD"], + "android.injected.signing.store.password" => ENV.fetch("KEYSTORE_PASSWORD", nil), "android.injected.signing.key.alias" => "key0", - "android.injected.signing.key.password" => ENV["KEY_PASSWORD"] + "android.injected.signing.key.password" => ENV.fetch("KEY_PASSWORD", nil) } ) end @@ -37,23 +37,23 @@ end # Example lane for uploading to App Store with Instabug reporting lane :upload_to_app_store do |options| branch_name = options[:branch_name] - + instabug_upload_to_app_store( - branch_name: branch_name, - instabug_api_key: ENV["INSTABUG_API_KEY"], + branch_name:, + instabug_api_key: ENV.fetch("INSTABUG_API_KEY", nil), # All standard upload_to_app_store parameters are supported ipa: "path/to/your/app.ipa", skip_waiting_for_build_processing: true ) end -# Example lane for uploading to Play Store with Instabug reporting +# Example lane for uploading to Play Store with Instabug reporting lane :upload_to_play_store do |options| - branch_name = options[:branch_name] - + branch_name = options[:branch_name] + instabug_upload_to_play_store( - branch_name: branch_name, - instabug_api_key: ENV["INSTABUG_API_KEY"], + branch_name:, + instabug_api_key: ENV.fetch("INSTABUG_API_KEY", nil), # All standard upload_to_play_store parameters are supported aab: "path/to/your/app.aab", track: "internal" From 45dea535e73c050e6345a66d73516ffef5d7e54f Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Mon, 11 Aug 2025 02:30:24 +0300 Subject: [PATCH 2/9] [GCSI-567] feat: handle ios build app to track build time and build path and + specs --- .../actions/instabug_build_ios_app_action.rb | 54 ++++++++++---- spec/instabug_build_ios_app_action_spec.rb | 72 +++++++++++++------ 2 files changed, 90 insertions(+), 36 deletions(-) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb index 54c2707..114f7bd 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb @@ -6,47 +6,67 @@ module Actions class InstabugBuildIosAppAction < Action def self.run(params) UI.message("Starting Instabug iOS build...") - + # Extract Instabug-specific parameters branch_name = params.delete(:branch_name) instabug_api_key = params.delete(:instabug_api_key) - + # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end - + begin # Report build start to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "inprogress", step: "build_app" ) + # Start timing the build + build_start_time = Time.now + # Execute the actual iOS build result = Actions::BuildIosAppAction.run(params) + # Calculate build time in seconds + build_time = (Time.now - build_start_time).round + + # Extract IPA path from Fastlane environment + build_path = Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] + + if build_path + UI.success("IPA Output Path: #{build_path}") + else + UI.error("No IPA path found.") + end + # Report build success to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "success", - step: "build_app" + step: "build_app", + extras: { + build_time:, + build_path: + } ) UI.success("iOS build completed successfully!") result - rescue => e + rescue StandardError => e UI.error("iOS build failed: #{e.message}") # Report build failure to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "failure", - step: "build_app" + step: "build_app", + error_message: e.message ) raise e end @@ -71,7 +91,7 @@ def self.details def self.available_options # Start with the original build_ios_app options options = Actions::BuildIosAppAction.available_options - + # Add Instabug-specific options instabug_options = [ FastlaneCore::ConfigItem.new( @@ -88,9 +108,17 @@ def self.available_options optional: false, type: String, sensitive: true - ) + ), + FastlaneCore::ConfigItem.new( + key: :instabug_api_base_url, + env_name: "INSTABUG_API_BASE_URL", + description: "Instabug API base URL (defaults to https://api.instabug.com)", + optional: true, + type: String, + skip_type_validation: true # Since we don't extract this param + ) ] - + # Combine both sets of options options + instabug_options end @@ -117,4 +145,4 @@ def self.category end end end -end \ No newline at end of file +end diff --git a/spec/instabug_build_ios_app_action_spec.rb b/spec/instabug_build_ios_app_action_spec.rb index e7e6337..d45f25e 100644 --- a/spec/instabug_build_ios_app_action_spec.rb +++ b/spec/instabug_build_ios_app_action_spec.rb @@ -20,7 +20,12 @@ describe '#run' do context 'when build succeeds' do - it 'reports inprogress, calls build action, and reports success' do + it 'reports inprogress, calls build action, and reports success with timing and path' do + # Mock the lane context to return an IPA path + allow(Fastlane::Actions).to receive(:lane_context).and_return({ + Fastlane::Actions::SharedValues::IPA_OUTPUT_PATH => '/path/to/app.ipa' + }) + expect(Fastlane::Actions::BuildIosAppAction).to receive(:run) .with(hash_including(workspace: 'Test.xcworkspace', scheme: 'Test', export_method: 'app-store')) .and_return('build_result') @@ -33,7 +38,9 @@ body: { branch_name: 'crash-fix/instabug-crash-123', status: 'inprogress', - step: 'build_app' + step: 'build_app', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -43,18 +50,35 @@ ).once expect(WebMock).to have_requested(:patch, api_endpoint) - .with( - body: { - branch_name: 'crash-fix/instabug-crash-123', - status: 'success', - step: 'build_app' - }.to_json, - headers: { - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' - } - ).once + .with { |req| + body = JSON.parse(req.body) + body['status'] == 'success' && + body['branch_name'] == 'crash-fix/instabug-crash-123' && + body['step'] == 'build_app' && + body['extras']['build_path'] == '/path/to/app.ipa' && + body['extras']['build_time'].kind_of?(Integer) + }.once + end + + it 'handles missing IPA path gracefully' do + # Mock empty lane context + allow(Fastlane::Actions).to receive(:lane_context).and_return({}) + + expect(Fastlane::Actions::BuildIosAppAction).to receive(:run) + .and_return('build_result') + + result = described_class.run(valid_params) + + expect(result).to eq('build_result') + expect(WebMock).to have_requested(:patch, api_endpoint) + .with { |req| + body = JSON.parse(req.body) + body['status'] == 'success' && + body['branch_name'] == 'crash-fix/instabug-crash-123' && + body['step'] == 'build_app' && + body['extras']['build_path'].nil? && + body['extras']['build_time'].kind_of?(Integer) + }.once end end @@ -64,16 +88,18 @@ expect(Fastlane::Actions::BuildIosAppAction).to receive(:run) .and_raise(error) - expect { + expect do described_class.run(valid_params) - }.to raise_error(StandardError, 'Build failed') + end.to raise_error(StandardError, 'Build failed') expect(WebMock).to have_requested(:patch, api_endpoint) .with( body: { branch_name: 'crash-fix/instabug-crash-123', status: 'failure', - step: 'build_app' + step: 'build_app', + extras: {}, + error_message: 'Build failed' }.to_json ) end @@ -83,9 +109,9 @@ it 'raises user error' do params = valid_params.merge(branch_name: nil) - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end @@ -93,16 +119,16 @@ it 'raises user error' do params = valid_params.merge(branch_name: '') - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end context 'when branch name does not match instabug pattern' do it 'does not make API calls but still runs build' do params = valid_params.merge(branch_name: 'feature/new-feature') - + expect(Fastlane::Actions::BuildIosAppAction).to receive(:run) .and_return('build_result') @@ -129,4 +155,4 @@ expect(described_class.category).to eq(:building) end end -end \ No newline at end of file +end From 453e786518fc8c8ba47138ad7eee8e16598876b6 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Mon, 11 Aug 2025 02:32:18 +0300 Subject: [PATCH 3/9] [GCSI-567] feat: handle android build app to track build time and build path and + specs --- .../instabug_build_android_app_action.rb | 54 ++++-- .../helper/instabug_stores_upload_helper.rb | 64 ++++--- .../instabug_build_android_app_action_spec.rb | 68 +++++--- spec/instabug_stores_upload_helper_spec.rb | 160 ++++++++++++++++++ 4 files changed, 289 insertions(+), 57 deletions(-) create mode 100644 spec/instabug_stores_upload_helper_spec.rb diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb index db9e8f1..e610802 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb @@ -6,47 +6,67 @@ module Actions class InstabugBuildAndroidAppAction < Action def self.run(params) UI.message("Starting Instabug Android build...") - + # Extract Instabug-specific parameters branch_name = params.delete(:branch_name) instabug_api_key = params.delete(:instabug_api_key) - + # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end - + begin # Report build start to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "inprogress", step: "build_app" ) + # Start timing the build + build_start_time = Time.now + # Execute the actual Android build using gradle result = Actions::GradleAction.run(params) + # Calculate build time in seconds + build_time = (Time.now - build_start_time).round + + # Extract Android build path (APK or AAB) + build_path = Helper::InstabugStoresUploadHelper.fetch_android_build_path(Actions.lane_context) + + if build_path.nil? || build_path.empty? + UI.user_error!("Could not find any generated APK or AAB. Please check your gradle settings.") + else + UI.success("Successfully found build artifact(s) at: #{build_path}") + end + # Report build success to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "success", - step: "build_app" + step: "build_app", + extras: { + build_time:, + build_path: + } ) UI.success("Android build completed successfully!") result - rescue => e + rescue StandardError => e UI.error("Android build failed: #{e.message}") # Report build failure to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "failure", - step: "build_app" + step: "build_app", + error_message: e.message ) raise e end @@ -71,7 +91,7 @@ def self.details def self.available_options # Start with the original gradle options options = Actions::GradleAction.available_options - + # Add Instabug-specific options instabug_options = [ FastlaneCore::ConfigItem.new( @@ -88,9 +108,17 @@ def self.available_options optional: false, type: String, sensitive: true - ) + ), + FastlaneCore::ConfigItem.new( + key: :instabug_api_base_url, + env_name: "INSTABUG_API_BASE_URL", + description: "Instabug API base URL (defaults to https://api.instabug.com)", + optional: true, + type: String, + skip_type_validation: true # Since we don't extract this param + ) ] - + # Combine both sets of options options + instabug_options end @@ -121,4 +149,4 @@ def self.category end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index 25a772e..e2d3357 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -8,60 +8,82 @@ module Fastlane module Helper class InstabugStoresUploadHelper - # Base URL for Instabug API we will need to adjust it for STs - INSTABUG_API_BASE_URL = "https://api.instabug.com".freeze + # Default Base URL for Instabug API + DEFAULT_INSTABUG_API_BASE_URL = "https://api.instabug.com".freeze def self.show_message UI.message("Hello from the instabug_stores_upload plugin helper!") end - def self.report_status(branch_name:, api_key:, status:, step:) + def self.report_status(branch_name:, api_key:, status:, step:, extras: {}, error_message: nil) return unless branch_name.start_with?('crash-fix/instabug-crash-') - + UI.message("📡 Reporting #{step} status to Instabug for #{branch_name}/#{status}") - + make_api_request( - branch_name: branch_name, - status: status, - api_key: api_key, - step: step + branch_name:, + status:, + api_key:, + step:, + extras:, + error_message: ) end - private + # This helper method provides a clean and prioritized way to get the Android build output. + # It checks for the most common output types in a specific order. + # This is used to get the build path for the Android build artifact. + def self.fetch_android_build_path(lane_context) + all_aab_paths = lane_context[Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] + return all_aab_paths if all_aab_paths && !all_aab_paths.empty? + + aab_path = lane_context[Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] + return aab_path if aab_path && !aab_path.empty? + + all_apk_paths = lane_context[Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] + return all_apk_paths if all_apk_paths && !all_apk_paths.empty? + + apk_path = lane_context[Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] + return apk_path if apk_path && !apk_path.empty? + + return nil + end - def self.make_api_request(branch_name:, status:, api_key:, step:) + def self.make_api_request(branch_name:, status:, api_key:, step:, extras: {}, error_message: nil) return unless api_key - uri = URI.parse("#{INSTABUG_API_BASE_URL}/api/web/public/agent_fastlane/status") - + # Determine API base URL from env var or default + base_url = ENV['INSTABUG_API_BASE_URL'] || DEFAULT_INSTABUG_API_BASE_URL + uri = URI.parse("#{base_url}/api/web/public/agent_fastlane/status") + payload = { - branch_name: branch_name, - status: status, - step: step + branch_name:, + status:, + step:, + extras:, + error_message: } - + begin http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.read_timeout = 30 http.open_timeout = 30 - + request = Net::HTTP::Patch.new(uri.path) request['Content-Type'] = 'application/json' request['Authorization'] = "Bearer #{api_key}" request['User-Agent'] = "fastlane-plugin-instabug-stores-upload" request.body = payload.to_json - + response = http.request(request) - + case response.code.to_i when 200..299 UI.success("✅ Successfully reported to Instabug") else UI.error("❌ Unknown error reporting to Instabug: #{response.code} #{response.message}") end - rescue Net::TimeoutError UI.error("❌ Timeout while reporting to Instabug") rescue Net::OpenTimeout diff --git a/spec/instabug_build_android_app_action_spec.rb b/spec/instabug_build_android_app_action_spec.rb index e4e22aa..8b57300 100644 --- a/spec/instabug_build_android_app_action_spec.rb +++ b/spec/instabug_build_android_app_action_spec.rb @@ -23,7 +23,12 @@ describe '#run' do context 'when build succeeds' do - it 'reports inprogress, calls build action, and reports success' do + it 'reports inprogress, calls build action, and reports success with timing and path' do + # Mock the lane context to return a build path + allow(Fastlane::Actions).to receive(:lane_context).and_return({ + Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH => '/path/to/app.apk' + }) + expect(Fastlane::Actions::GradleAction).to receive(:run) .with(hash_including(task: 'assembleRelease', project_dir: 'android/')) .and_return('build_result') @@ -36,7 +41,9 @@ body: { branch_name: 'crash-fix/instabug-crash-456', status: 'inprogress', - step: 'build_app' + step: 'build_app', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -46,18 +53,26 @@ ).once expect(WebMock).to have_requested(:patch, api_endpoint) - .with( - body: { - branch_name: 'crash-fix/instabug-crash-456', - status: 'success', - step: 'build_app' - }.to_json, - headers: { - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' - } - ).once + .with { |req| + body = JSON.parse(req.body) + body['status'] == 'success' && + body['branch_name'] == 'crash-fix/instabug-crash-456' && + body['step'] == 'build_app' && + body['extras']['build_path'] == '/path/to/app.apk' && + body['extras']['build_time'].kind_of?(Integer) + }.once + end + + it 'fails when no build artifact is found' do + # Mock empty lane context + allow(Fastlane::Actions).to receive(:lane_context).and_return({}) + + expect(Fastlane::Actions::GradleAction).to receive(:run) + .and_return('build_result') + + expect do + described_class.run(valid_params) + end.to raise_error(FastlaneCore::Interface::FastlaneError, /Could not find any generated APK or AAB/) end end @@ -67,16 +82,18 @@ expect(Fastlane::Actions::GradleAction).to receive(:run) .and_raise(error) - expect { + expect do described_class.run(valid_params) - }.to raise_error(StandardError, 'Build failed') + end.to raise_error(StandardError, 'Build failed') expect(WebMock).to have_requested(:patch, api_endpoint) .with( body: { branch_name: 'crash-fix/instabug-crash-456', status: 'failure', - step: 'build_app' + step: 'build_app', + extras: {}, + error_message: 'Build failed' }.to_json ) end @@ -86,9 +103,9 @@ it 'raises user error' do params = valid_params.merge(branch_name: nil) - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end @@ -96,16 +113,21 @@ it 'raises user error' do params = valid_params.merge(branch_name: '') - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end context 'when branch name does not match instabug pattern' do it 'does not make API calls but still runs build' do params = valid_params.merge(branch_name: 'feature/new-feature') - + + # Mock successful build with a valid build path to avoid validation error + allow(Fastlane::Actions).to receive(:lane_context).and_return({ + Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH => '/path/to/app.apk' + }) + expect(Fastlane::Actions::GradleAction).to receive(:run) .and_return('build_result') @@ -132,4 +154,4 @@ expect(described_class.category).to eq(:building) end end -end \ No newline at end of file +end diff --git a/spec/instabug_stores_upload_helper_spec.rb b/spec/instabug_stores_upload_helper_spec.rb new file mode 100644 index 0000000..94b99f6 --- /dev/null +++ b/spec/instabug_stores_upload_helper_spec.rb @@ -0,0 +1,160 @@ +require 'spec_helper' +require 'webmock/rspec' + +describe Fastlane::Helper::InstabugStoresUploadHelper do + describe '.fetch_android_build_path' do + let(:lane_context) { {} } + + context 'when all AAB output paths are available' do + it 'returns all AAB paths with highest priority' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] = ['/path/to/app1.aab', '/path/to/app2.aab'] + lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '/path/to/single.aab' + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app.apk'] + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq(['/path/to/app1.aab', '/path/to/app2.aab']) + end + end + + context 'when single AAB output path is available' do + it 'returns single AAB path when all AAB paths are not available' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '/path/to/app.aab' + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app.apk'] + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq('/path/to/app.aab') + end + end + + context 'when all APK output paths are available' do + it 'returns all APK paths when AAB paths are not available' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app1.apk', '/path/to/app2.apk'] + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq(['/path/to/app1.apk', '/path/to/app2.apk']) + end + end + + context 'when single APK output path is available' do + it 'returns single APK path when other paths are not available' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/app.apk' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq('/path/to/app.apk') + end + end + + context 'when no build paths are available' do + it 'returns nil' do + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + end + + context 'when paths are empty strings' do + it 'returns nil for empty AAB path' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + + it 'returns nil for empty APK path' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + end + + context 'when paths are empty arrays' do + it 'returns nil for empty all AAB paths' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] = [] + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + + it 'returns nil for empty all APK paths' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = [] + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + end + end + + describe '.report_status' do + let(:api_endpoint) { 'https://api.instabug.com/api/web/public/agent_fastlane/status' } + + before do + stub_request(:patch, api_endpoint) + .to_return(status: 200, body: '{}', headers: {}) + end + + context 'when branch name matches instabug pattern' do + it 'makes API request for instabug crash branch' do + described_class.report_status( + branch_name: 'crash-fix/instabug-crash-123', + api_key: 'test-key', + status: 'success', + step: 'build_app' + ) + + expect(WebMock).to have_requested(:patch, api_endpoint) + .with( + body: { + branch_name: 'crash-fix/instabug-crash-123', + status: 'success', + step: 'build_app', + extras: {}, + error_message: nil + }.to_json, + headers: { + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer test-key', + 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + } + ).once + end + end + + context 'when branch name does not match instabug pattern' do + it 'does not make API request' do + described_class.report_status( + branch_name: 'feature/new-feature', + api_key: 'test-key', + status: 'success', + step: 'build_app' + ) + + expect(WebMock).not_to have_requested(:patch, api_endpoint) + end + end + + context 'when no api_key is provided' do + it 'does not make API request' do + described_class.report_status( + branch_name: 'crash-fix/instabug-crash-123', + api_key: nil, + status: 'success', + step: 'build_app' + ) + + expect(WebMock).not_to have_requested(:patch, api_endpoint) + end + end + end +end From 03507b3c55451a79baaebf9c1755ef03170e85d9 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Mon, 11 Aug 2025 02:33:34 +0300 Subject: [PATCH 4/9] feat: handle remaining rubocop offenses --- ...lane-plugin-instabug-stores-upload.gemspec | 16 +++++------ .../instabug_upload_to_app_store_action.rb | 25 +++++++++-------- .../instabug_upload_to_play_store_action.rb | 24 ++++++++-------- ...nstabug_upload_to_app_store_action_spec.rb | 28 +++++++++++-------- ...stabug_upload_to_play_store_action_spec.rb | 28 +++++++++++-------- 5 files changed, 67 insertions(+), 54 deletions(-) diff --git a/fastlane-plugin-instabug-stores-upload.gemspec b/fastlane-plugin-instabug-stores-upload.gemspec index e83ff83..f4310f0 100644 --- a/fastlane-plugin-instabug-stores-upload.gemspec +++ b/fastlane-plugin-instabug-stores-upload.gemspec @@ -17,12 +17,12 @@ Gem::Specification.new do |spec| spec.metadata['rubygems_mfa_required'] = 'true' spec.required_ruby_version = '>= 3.2.2' - spec.add_development_dependency 'bundler' - spec.add_development_dependency 'rspec' - spec.add_development_dependency 'rake' - spec.add_development_dependency 'rubocop', '1.50.2' - spec.add_development_dependency 'rubocop-performance' - spec.add_development_dependency 'rubocop-require_tools' - spec.add_development_dependency 'simplecov' - spec.add_development_dependency 'fastlane', '~> 2.228.0' + spec.add_development_dependency('bundler') + spec.add_development_dependency('fastlane', '~> 2.228.0') + spec.add_development_dependency('rake') + spec.add_development_dependency('rspec') + spec.add_development_dependency('rubocop', '1.50.2') + spec.add_development_dependency('rubocop-performance') + spec.add_development_dependency('rubocop-require_tools') + spec.add_development_dependency('simplecov') end diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb index c1b512f..2a02b10 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb @@ -6,20 +6,20 @@ module Actions class InstabugUploadToAppStoreAction < Action def self.run(params) UI.message("Starting Instabug App Store upload...") - + # Extract Instabug-specific parameters branch_name = params.delete(:branch_name) instabug_api_key = params.delete(:instabug_api_key) - + # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end - + begin # Report upload start to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "inprogress", step: "upload_to_the_store" @@ -30,7 +30,7 @@ def self.run(params) # Report upload success to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "success", step: "upload_to_the_store" @@ -38,15 +38,16 @@ def self.run(params) UI.success("App Store upload completed successfully!") result - rescue => e + rescue StandardError => e UI.error("App Store upload failed: #{e.message}") # Report upload failure to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "failure", - step: "upload_to_the_store" + step: "upload_to_the_store", + error_message: e.message ) raise e end @@ -71,7 +72,7 @@ def self.details def self.available_options # Start with the original upload_to_app_store options options = Actions::UploadToAppStoreAction.available_options - + # Add Instabug-specific options instabug_options = [ FastlaneCore::ConfigItem.new( @@ -88,9 +89,9 @@ def self.available_options optional: false, type: String, sensitive: true - ) + ) ] - + # Combine both sets of options options + instabug_options end @@ -116,4 +117,4 @@ def self.category end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb index c13d788..5f91fc0 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb @@ -6,7 +6,7 @@ module Actions class InstabugUploadToPlayStoreAction < Action def self.run(params) UI.message("Starting Instabug Play Store upload...") - + # Extract Instabug-specific parameters branch_name = params.delete(:branch_name) instabug_api_key = params.delete(:instabug_api_key) @@ -19,7 +19,7 @@ def self.run(params) begin # Report upload start to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "inprogress", step: "upload_to_the_store" @@ -27,27 +27,27 @@ def self.run(params) # Execute the actual upload to Play Store result = Actions::UploadToPlayStoreAction.run(params) - + # Report upload success to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "success", step: "upload_to_the_store" ) - + UI.success("Play Store upload completed successfully!") result - - rescue => e + rescue StandardError => e UI.error("Play Store upload failed: #{e.message}") # Report upload failure to Instabug Helper::InstabugStoresUploadHelper.report_status( - branch_name: branch_name, + branch_name:, api_key: instabug_api_key, status: "failure", - step: "upload_to_the_store" + step: "upload_to_the_store", + error_message: e.message ) raise e end @@ -72,7 +72,7 @@ def self.details def self.available_options # Start with the original upload_to_play_store options options = Actions::UploadToPlayStoreAction.available_options - + # Add Instabug-specific options instabug_options = [ FastlaneCore::ConfigItem.new( @@ -91,7 +91,7 @@ def self.available_options sensitive: true ) ] - + # Combine both sets of options options + instabug_options end @@ -118,4 +118,4 @@ def self.category end end end -end \ No newline at end of file +end diff --git a/spec/instabug_upload_to_app_store_action_spec.rb b/spec/instabug_upload_to_app_store_action_spec.rb index 9fa4c46..e3c3af9 100644 --- a/spec/instabug_upload_to_app_store_action_spec.rb +++ b/spec/instabug_upload_to_app_store_action_spec.rb @@ -32,7 +32,9 @@ body: { branch_name: 'crash-fix/instabug-crash-123', status: 'inprogress', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -46,7 +48,9 @@ body: { branch_name: 'crash-fix/instabug-crash-123', status: 'success', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -63,16 +67,18 @@ expect(Fastlane::Actions::UploadToAppStoreAction).to receive(:run) .and_raise(error) - expect { + expect do described_class.run(valid_params) - }.to raise_error(StandardError, 'Upload failed') + end.to raise_error(StandardError, 'Upload failed') expect(WebMock).to have_requested(:patch, api_endpoint) .with( body: { branch_name: 'crash-fix/instabug-crash-123', status: 'failure', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: 'Upload failed' }.to_json ) end @@ -82,9 +88,9 @@ it 'raises user error' do params = valid_params.merge(branch_name: nil) - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end @@ -92,16 +98,16 @@ it 'raises user error' do params = valid_params.merge(branch_name: '') - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end context 'when branch name does not match instabug pattern' do it 'does not make API calls but still runs upload' do params = valid_params.merge(branch_name: 'feature/new-feature') - + expect(Fastlane::Actions::UploadToAppStoreAction).to receive(:run) .and_return('upload_result') @@ -128,4 +134,4 @@ expect(described_class.category).to eq(:app_store_connect) end end -end \ No newline at end of file +end diff --git a/spec/instabug_upload_to_play_store_action_spec.rb b/spec/instabug_upload_to_play_store_action_spec.rb index ff0ae09..aea78d2 100644 --- a/spec/instabug_upload_to_play_store_action_spec.rb +++ b/spec/instabug_upload_to_play_store_action_spec.rb @@ -33,7 +33,9 @@ body: { branch_name: 'crash-fix/instabug-crash-456', status: 'inprogress', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -47,7 +49,9 @@ body: { branch_name: 'crash-fix/instabug-crash-456', status: 'success', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: nil }.to_json, headers: { 'Content-Type' => 'application/json', @@ -64,16 +68,18 @@ expect(Fastlane::Actions::UploadToPlayStoreAction).to receive(:run) .and_raise(error) - expect { + expect do described_class.run(valid_params) - }.to raise_error(StandardError, 'Upload failed') + end.to raise_error(StandardError, 'Upload failed') expect(WebMock).to have_requested(:patch, api_endpoint) .with( body: { branch_name: 'crash-fix/instabug-crash-456', status: 'failure', - step: 'upload_to_the_store' + step: 'upload_to_the_store', + extras: {}, + error_message: 'Upload failed' }.to_json ) end @@ -83,9 +89,9 @@ it 'raises user error' do params = valid_params.merge(branch_name: nil) - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end @@ -93,16 +99,16 @@ it 'raises user error' do params = valid_params.merge(branch_name: '') - expect { + expect do described_class.run(params) - }.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'branch_name is required for Instabug reporting') end end context 'when branch name does not match instabug pattern' do it 'does not make API calls but still runs upload' do params = valid_params.merge(branch_name: 'feature/new-feature') - + expect(Fastlane::Actions::UploadToPlayStoreAction).to receive(:run) .and_return('upload_result') @@ -129,4 +135,4 @@ expect(described_class.category).to eq(:google_play_console) end end -end \ No newline at end of file +end From 276b9e3c830eae07a3e4e553feebb38293d58083 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Tue, 12 Aug 2025 00:32:07 +0300 Subject: [PATCH 5/9] fix-fastlane-naming-for-loading-issue --- README.md | 10 +++++----- fastlane-plugin-instabug-stores-upload.gemspec | 2 +- .../actions/instabug_stores_upload_action.rb | 2 +- .../helper/instabug_stores_upload_helper.rb | 2 +- spec/instabug_build_android_app_action_spec.rb | 2 +- spec/instabug_build_ios_app_action_spec.rb | 2 +- spec/instabug_stores_upload_action_spec.rb | 2 +- spec/instabug_stores_upload_helper_spec.rb | 2 +- spec/instabug_upload_to_app_store_action_spec.rb | 4 ++-- spec/instabug_upload_to_play_store_action_spec.rb | 4 ++-- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 2637a7a..53b2547 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# instabug-stores-upload plugin +# instabug_stores_upload plugin -[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-instabug-stores-upload) +[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-instabug_stores_upload) ## Getting Started -This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-instabug-stores-upload`, add it to your project by running: +This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-instabug_stores_upload`, add it to your project by running: ```bash -fastlane add_plugin instabug-stores-upload +fastlane add_plugin instabug_stores_upload ``` -## About instabug-stores-upload +## About instabug_stores_upload Wrapper plugin for uploading builds to App Store and Play Store with Instabug-specific metadata reporting. This plugin provides custom actions that wrap the standard Fastlane actions and automatically report build and upload events to Instabug systems for better observability and integration into internal pipelines. diff --git a/fastlane-plugin-instabug-stores-upload.gemspec b/fastlane-plugin-instabug-stores-upload.gemspec index f4310f0..3e55709 100644 --- a/fastlane-plugin-instabug-stores-upload.gemspec +++ b/fastlane-plugin-instabug-stores-upload.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'fastlane/plugin/instabug_stores_upload/version' Gem::Specification.new do |spec| - spec.name = 'fastlane-plugin-instabug-stores-upload' + spec.name = 'fastlane-plugin-instabug_stores_upload' spec.version = Fastlane::InstabugStoresUpload::VERSION spec.author = 'Instabug' spec.email = 'backend-team@instabug.com' diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_stores_upload_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_stores_upload_action.rb index 288263f..4c1f6d2 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_stores_upload_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_stores_upload_action.rb @@ -5,7 +5,7 @@ module Fastlane module Actions class InstabugStoresUploadAction < Action def self.run(params) - UI.message("The instabug-stores-upload plugin is working!") + UI.message("The instabug_stores_upload plugin is working!") end def self.description diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index e2d3357..c75cc3c 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -73,7 +73,7 @@ def self.make_api_request(branch_name:, status:, api_key:, step:, extras: {}, er request = Net::HTTP::Patch.new(uri.path) request['Content-Type'] = 'application/json' request['Authorization'] = "Bearer #{api_key}" - request['User-Agent'] = "fastlane-plugin-instabug-stores-upload" + request['User-Agent'] = "fastlane-plugin-instabug_stores_upload" request.body = payload.to_json response = http.request(request) diff --git a/spec/instabug_build_android_app_action_spec.rb b/spec/instabug_build_android_app_action_spec.rb index 8b57300..b9ede7e 100644 --- a/spec/instabug_build_android_app_action_spec.rb +++ b/spec/instabug_build_android_app_action_spec.rb @@ -48,7 +48,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once diff --git a/spec/instabug_build_ios_app_action_spec.rb b/spec/instabug_build_ios_app_action_spec.rb index d45f25e..902f7d2 100644 --- a/spec/instabug_build_ios_app_action_spec.rb +++ b/spec/instabug_build_ios_app_action_spec.rb @@ -45,7 +45,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once diff --git a/spec/instabug_stores_upload_action_spec.rb b/spec/instabug_stores_upload_action_spec.rb index c1fcd60..20eeadf 100644 --- a/spec/instabug_stores_upload_action_spec.rb +++ b/spec/instabug_stores_upload_action_spec.rb @@ -1,7 +1,7 @@ describe Fastlane::Actions::InstabugStoresUploadAction do describe '#run' do it 'prints a message' do - expect(Fastlane::UI).to receive(:message).with("The instabug-stores-upload plugin is working!") + expect(Fastlane::UI).to receive(:message).with("The instabug_stores_upload plugin is working!") Fastlane::Actions::InstabugStoresUploadAction.run(nil) end diff --git a/spec/instabug_stores_upload_helper_spec.rb b/spec/instabug_stores_upload_helper_spec.rb index 94b99f6..71ff9da 100644 --- a/spec/instabug_stores_upload_helper_spec.rb +++ b/spec/instabug_stores_upload_helper_spec.rb @@ -125,7 +125,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once end diff --git a/spec/instabug_upload_to_app_store_action_spec.rb b/spec/instabug_upload_to_app_store_action_spec.rb index e3c3af9..430cfc1 100644 --- a/spec/instabug_upload_to_app_store_action_spec.rb +++ b/spec/instabug_upload_to_app_store_action_spec.rb @@ -39,7 +39,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once @@ -55,7 +55,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once end diff --git a/spec/instabug_upload_to_play_store_action_spec.rb b/spec/instabug_upload_to_play_store_action_spec.rb index aea78d2..9d43e4a 100644 --- a/spec/instabug_upload_to_play_store_action_spec.rb +++ b/spec/instabug_upload_to_play_store_action_spec.rb @@ -40,7 +40,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once @@ -56,7 +56,7 @@ headers: { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer test-api-key', - 'User-Agent' => 'fastlane-plugin-instabug-stores-upload' + 'User-Agent' => 'fastlane-plugin-instabug_stores_upload' } ).once end From 5048fe77e027a6d9693c7e709cc15874f4ea82c2 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Tue, 12 Aug 2025 17:30:04 +0300 Subject: [PATCH 6/9] applying review comment --- .../instabug_build_android_app_action.rb | 20 +++- .../helper/instabug_stores_upload_helper.rb | 19 ---- .../instabug_build_android_app_action_spec.rb | 52 ++++++++++ spec/instabug_stores_upload_helper_spec.rb | 94 ------------------- 4 files changed, 71 insertions(+), 114 deletions(-) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb index e610802..81181c8 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb @@ -35,7 +35,7 @@ def self.run(params) build_time = (Time.now - build_start_time).round # Extract Android build path (APK or AAB) - build_path = Helper::InstabugStoresUploadHelper.fetch_android_build_path(Actions.lane_context) + build_path = fetch_android_build_path(Actions.lane_context) if build_path.nil? || build_path.empty? UI.user_error!("Could not find any generated APK or AAB. Please check your gradle settings.") @@ -147,6 +147,24 @@ def self.example_code def self.category :building end + + # This helper method provides a clean and prioritized way to get the Android build output. + # It checks for the most common output types in a specific order. + # This is used to get the build path for the Android build artifact. + def self.fetch_android_build_path(lane_context) + build_keys = [ + SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS, + SharedValues::GRADLE_APK_OUTPUT_PATH, + SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS, + SharedValues::GRADLE_AAB_OUTPUT_PATH + ] + build_keys.each do |build_key| + build_path = lane_context[build_key] + return build_path if build_path && !build_path.empty? + end + + nil + end end end end diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index c75cc3c..6165c3c 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -30,25 +30,6 @@ def self.report_status(branch_name:, api_key:, status:, step:, extras: {}, error ) end - # This helper method provides a clean and prioritized way to get the Android build output. - # It checks for the most common output types in a specific order. - # This is used to get the build path for the Android build artifact. - def self.fetch_android_build_path(lane_context) - all_aab_paths = lane_context[Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] - return all_aab_paths if all_aab_paths && !all_aab_paths.empty? - - aab_path = lane_context[Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] - return aab_path if aab_path && !aab_path.empty? - - all_apk_paths = lane_context[Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] - return all_apk_paths if all_apk_paths && !all_apk_paths.empty? - - apk_path = lane_context[Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] - return apk_path if apk_path && !apk_path.empty? - - return nil - end - def self.make_api_request(branch_name:, status:, api_key:, step:, extras: {}, error_message: nil) return unless api_key diff --git a/spec/instabug_build_android_app_action_spec.rb b/spec/instabug_build_android_app_action_spec.rb index b9ede7e..e2fd800 100644 --- a/spec/instabug_build_android_app_action_spec.rb +++ b/spec/instabug_build_android_app_action_spec.rb @@ -139,6 +139,58 @@ end end + describe '.fetch_android_build_path' do + let(:lane_context) { {} } + + context 'when all AAB output paths are available' do + it 'returns all AAB paths' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] = ['/path/to/app1.aab', '/path/to/app2.aab'] + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq(['/path/to/app1.aab', '/path/to/app2.aab']) + end + end + + context 'when single AAB output path is available' do + it 'returns single AAB path' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '/path/to/app.aab' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq('/path/to/app.aab') + end + end + + context 'when all APK output paths are available' do + it 'returns all APK paths' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app1.apk', '/path/to/app2.apk'] + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq(['/path/to/app1.apk', '/path/to/app2.apk']) + end + end + + context 'when single APK output path is available' do + it 'returns single APK path' do + lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/app.apk' + + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to eq('/path/to/app.apk') + end + end + + context 'when no build paths are available' do + it 'returns nil' do + result = described_class.fetch_android_build_path(lane_context) + + expect(result).to be_nil + end + end + end + describe 'metadata' do it 'has correct description' do expect(described_class.description).to eq('Build Android app with Instabug metadata reporting') diff --git a/spec/instabug_stores_upload_helper_spec.rb b/spec/instabug_stores_upload_helper_spec.rb index 71ff9da..575b14f 100644 --- a/spec/instabug_stores_upload_helper_spec.rb +++ b/spec/instabug_stores_upload_helper_spec.rb @@ -2,100 +2,6 @@ require 'webmock/rspec' describe Fastlane::Helper::InstabugStoresUploadHelper do - describe '.fetch_android_build_path' do - let(:lane_context) { {} } - - context 'when all AAB output paths are available' do - it 'returns all AAB paths with highest priority' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] = ['/path/to/app1.aab', '/path/to/app2.aab'] - lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '/path/to/single.aab' - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app.apk'] - lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to eq(['/path/to/app1.aab', '/path/to/app2.aab']) - end - end - - context 'when single AAB output path is available' do - it 'returns single AAB path when all AAB paths are not available' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '/path/to/app.aab' - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app.apk'] - lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to eq('/path/to/app.aab') - end - end - - context 'when all APK output paths are available' do - it 'returns all APK paths when AAB paths are not available' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = ['/path/to/app1.apk', '/path/to/app2.apk'] - lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/single.apk' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to eq(['/path/to/app1.apk', '/path/to/app2.apk']) - end - end - - context 'when single APK output path is available' do - it 'returns single APK path when other paths are not available' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '/path/to/app.apk' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to eq('/path/to/app.apk') - end - end - - context 'when no build paths are available' do - it 'returns nil' do - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to be_nil - end - end - - context 'when paths are empty strings' do - it 'returns nil for empty AAB path' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_AAB_OUTPUT_PATH] = '' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to be_nil - end - - it 'returns nil for empty APK path' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_APK_OUTPUT_PATH] = '' - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to be_nil - end - end - - context 'when paths are empty arrays' do - it 'returns nil for empty all AAB paths' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_AAB_OUTPUT_PATHS] = [] - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to be_nil - end - - it 'returns nil for empty all APK paths' do - lane_context[Fastlane::Actions::SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = [] - - result = described_class.fetch_android_build_path(lane_context) - - expect(result).to be_nil - end - end - end - describe '.report_status' do let(:api_endpoint) { 'https://api.instabug.com/api/web/public/agent_fastlane/status' } From 076ad2b7d3e5ff41bb7c3bc4bc73d12b0602fce0 Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Tue, 12 Aug 2025 01:10:01 +0300 Subject: [PATCH 7/9] fix-extracting-instabug-params-from-fastlane-params --- .../instabug_build_android_app_action.rb | 9 ++++++--- .../actions/instabug_build_ios_app_action.rb | 9 ++++++--- .../instabug_upload_to_app_store_action.rb | 9 ++++++--- .../instabug_upload_to_play_store_action.rb | 9 ++++++--- .../helper/instabug_stores_upload_helper.rb | 19 +++++++++++++++++++ spec/spec_helper.rb | 8 ++++++++ 6 files changed, 51 insertions(+), 12 deletions(-) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb index 81181c8..845a3d8 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb @@ -8,14 +8,17 @@ def self.run(params) UI.message("Starting Instabug Android build...") # Extract Instabug-specific parameters - branch_name = params.delete(:branch_name) - instabug_api_key = params.delete(:instabug_api_key) + branch_name = params[:branch_name] + instabug_api_key = params[:instabug_api_key] # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end + # Filter out Instabug-specific parameters before passing to gradle + filtered_params = Helper::InstabugStoresUploadHelper.filter_instabug_params(params, Actions::GradleAction) + begin # Report build start to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -29,7 +32,7 @@ def self.run(params) build_start_time = Time.now # Execute the actual Android build using gradle - result = Actions::GradleAction.run(params) + result = Actions::GradleAction.run(filtered_params) # Calculate build time in seconds build_time = (Time.now - build_start_time).round diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb index 114f7bd..2959430 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb @@ -8,14 +8,17 @@ def self.run(params) UI.message("Starting Instabug iOS build...") # Extract Instabug-specific parameters - branch_name = params.delete(:branch_name) - instabug_api_key = params.delete(:instabug_api_key) + branch_name = params[:branch_name] + instabug_api_key = params[:instabug_api_key] # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end + # Filter out Instabug-specific parameters before passing to build_ios_app + filtered_params = Helper::InstabugStoresUploadHelper.filter_instabug_params(params, Actions::BuildIosAppAction) + begin # Report build start to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -29,7 +32,7 @@ def self.run(params) build_start_time = Time.now # Execute the actual iOS build - result = Actions::BuildIosAppAction.run(params) + result = Actions::BuildIosAppAction.run(filtered_params) # Calculate build time in seconds build_time = (Time.now - build_start_time).round diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb index 2a02b10..eeeddac 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb @@ -8,14 +8,17 @@ def self.run(params) UI.message("Starting Instabug App Store upload...") # Extract Instabug-specific parameters - branch_name = params.delete(:branch_name) - instabug_api_key = params.delete(:instabug_api_key) + branch_name = params[:branch_name] + instabug_api_key = params[:instabug_api_key] # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end + # Filter out Instabug-specific parameters before passing to upload_to_app_store + filtered_params = Helper::InstabugStoresUploadHelper.filter_instabug_params(params, Actions::UploadToAppStoreAction) + begin # Report upload start to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -26,7 +29,7 @@ def self.run(params) ) # Execute the actual upload to App Store - result = Actions::UploadToAppStoreAction.run(params) + result = Actions::UploadToAppStoreAction.run(filtered_params) # Report upload success to Instabug Helper::InstabugStoresUploadHelper.report_status( diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb index 5f91fc0..3e1b6ed 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb @@ -8,14 +8,17 @@ def self.run(params) UI.message("Starting Instabug Play Store upload...") # Extract Instabug-specific parameters - branch_name = params.delete(:branch_name) - instabug_api_key = params.delete(:instabug_api_key) + branch_name = params[:branch_name] + instabug_api_key = params[:instabug_api_key] # Validate required parameters if branch_name.nil? || branch_name.empty? UI.user_error!("branch_name is required for Instabug reporting") end + # Filter out Instabug-specific parameters before passing to upload_to_play_store + filtered_params = Helper::InstabugStoresUploadHelper.filter_instabug_params(params, Actions::UploadToPlayStoreAction) + begin # Report upload start to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -26,7 +29,7 @@ def self.run(params) ) # Execute the actual upload to Play Store - result = Actions::UploadToPlayStoreAction.run(params) + result = Actions::UploadToPlayStoreAction.run(filtered_params) # Report upload success to Instabug Helper::InstabugStoresUploadHelper.report_status( diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index 6165c3c..9e36bf6 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -10,11 +10,30 @@ module Helper class InstabugStoresUploadHelper # Default Base URL for Instabug API DEFAULT_INSTABUG_API_BASE_URL = "https://api.instabug.com".freeze + INSTABUG_KEYS = %i[branch_name instabug_api_key instabug_api_base_url].freeze def self.show_message UI.message("Hello from the instabug_stores_upload plugin helper!") end + # Filters out Instabug-specific parameters from the params configuration + # and returns a new FastlaneCore::Configuration object with only the target action's parameters + def self.filter_instabug_params(params, target_action_class) + filtered_config = {} + params.available_options.each do |option| + key = option.key + unless INSTABUG_KEYS.include?(key) + value = params[key] + filtered_config[key] = value if value + end + end + + FastlaneCore::Configuration.create( + target_action_class.available_options, + filtered_config + ) + end + def self.report_status(branch_name:, api_key:, status:, step:, extras: {}, error_message: nil) return unless branch_name.start_with?('crash-fix/instabug-crash-') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5e2f9a6..d3f0aef 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,6 +13,14 @@ module SpecHelper require 'fastlane/plugin/instabug_stores_upload' # import the actual plugin require 'webmock/rspec' +# Override the helper method for tests to handle plain hashes +class Fastlane::Helper::InstabugStoresUploadHelper + def self.filter_instabug_params(params, target_action_class) + # In test environment, params are plain hashes - just filter them + return params.reject { |key, _value| INSTABUG_KEYS.include?(key) } + end +end + Fastlane.load_actions # load other actions (in case your plugin calls other actions or shared values) WebMock.disable_net_connect!(allow_localhost: true) From dd1f09a08bfd16379f54f5b3666cb5631ae0bd5d Mon Sep 17 00:00:00 2001 From: yousif-ahmed Date: Tue, 12 Aug 2025 17:59:17 +0300 Subject: [PATCH 8/9] feat: extracting error message from the fastlane error --- .../instabug_build_android_app_action.rb | 5 +++-- .../actions/instabug_build_ios_app_action.rb | 5 +++-- .../instabug_upload_to_app_store_action.rb | 4 +++- .../instabug_upload_to_play_store_action.rb | 3 ++- .../helper/instabug_stores_upload_helper.rb | 19 +++++++++++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb index 845a3d8..1e1682d 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb @@ -61,7 +61,8 @@ def self.run(params) UI.success("Android build completed successfully!") result rescue StandardError => e - UI.error("Android build failed: #{e.message}") + error_message = Helper::InstabugStoresUploadHelper.extract_error_message(e.message) + UI.error("Android build failed: #{error_message}") # Report build failure to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -69,7 +70,7 @@ def self.run(params) api_key: instabug_api_key, status: "failure", step: "build_app", - error_message: e.message + error_message: error_message ) raise e end diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb index 2959430..1c23b92 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb @@ -61,7 +61,8 @@ def self.run(params) UI.success("iOS build completed successfully!") result rescue StandardError => e - UI.error("iOS build failed: #{e.message}") + error_message = Helper::InstabugStoresUploadHelper.extract_error_message(e.message) + UI.error("iOS build failed: #{error_message}") # Report build failure to Instabug Helper::InstabugStoresUploadHelper.report_status( @@ -69,7 +70,7 @@ def self.run(params) api_key: instabug_api_key, status: "failure", step: "build_app", - error_message: e.message + error_message: error_message ) raise e end diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb index eeeddac..ef14569 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_app_store_action.rb @@ -42,7 +42,9 @@ def self.run(params) UI.success("App Store upload completed successfully!") result rescue StandardError => e - UI.error("App Store upload failed: #{e.message}") + error_message = Helper::InstabugStoresUploadHelper.extract_error_message(e.message) + + UI.error("App Store upload failed: #{error_message}") # Report upload failure to Instabug Helper::InstabugStoresUploadHelper.report_status( diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb index 3e1b6ed..b183c3d 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_upload_to_play_store_action.rb @@ -42,7 +42,8 @@ def self.run(params) UI.success("Play Store upload completed successfully!") result rescue StandardError => e - UI.error("Play Store upload failed: #{e.message}") + error_message = Helper::InstabugStoresUploadHelper.extract_error_message(e.message) + UI.error("Play Store upload failed: #{error_message}") # Report upload failure to Instabug Helper::InstabugStoresUploadHelper.report_status( diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index 9e36bf6..8a1407a 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -12,6 +12,25 @@ class InstabugStoresUploadHelper DEFAULT_INSTABUG_API_BASE_URL = "https://api.instabug.com".freeze INSTABUG_KEYS = %i[branch_name instabug_api_key instabug_api_base_url].freeze + # Extract the important part of an error message + def self.extract_error_message(error_message) + return error_message unless error_message.is_a?(String) + + lines = error_message.split("\n") + start_index = lines.find_index { |line| line.strip.start_with?("* What went wrong:") } + end_index = lines.find_index { |line| line.strip.start_with?("* Try:") } + + if start_index && end_index && end_index > start_index + extracted_lines = lines[(start_index + 1)...end_index].map(&:strip).reject(&:empty?) + return extracted_lines.join(" ")[0, 250] unless extracted_lines.empty? + end + + # Fallback message + "Your build was triggered but failed during execution. " \ + "This could be due to missing environment variables or incorrect build credentials. " \ + "Check CI logs for full details." + end + def self.show_message UI.message("Hello from the instabug_stores_upload plugin helper!") end From 82c47e0c2f7fa938231f35a0f76c1f499a4ab8d9 Mon Sep 17 00:00:00 2001 From: Ahmed Hany Date: Fri, 15 Aug 2025 19:50:40 +0300 Subject: [PATCH 9/9] Apply review comments --- .../actions/instabug_build_android_app_action.rb | 2 +- .../actions/instabug_build_ios_app_action.rb | 2 +- .../helper/instabug_stores_upload_helper.rb | 10 ++-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb index 1e1682d..fcf2274 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_android_app_action.rb @@ -54,7 +54,7 @@ def self.run(params) step: "build_app", extras: { build_time:, - build_path: + build_path: Array(build_path) } ) diff --git a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb index 1c23b92..e6923bd 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/actions/instabug_build_ios_app_action.rb @@ -54,7 +54,7 @@ def self.run(params) step: "build_app", extras: { build_time:, - build_path: + build_path: Array(build_path) } ) diff --git a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb index 8a1407a..804d83d 100644 --- a/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb +++ b/lib/fastlane/plugin/instabug_stores_upload/helper/instabug_stores_upload_helper.rb @@ -41,16 +41,10 @@ def self.filter_instabug_params(params, target_action_class) filtered_config = {} params.available_options.each do |option| key = option.key - unless INSTABUG_KEYS.include?(key) - value = params[key] - filtered_config[key] = value if value - end + filtered_config[key] = params[key] unless INSTABUG_KEYS.include?(key) end - FastlaneCore::Configuration.create( - target_action_class.available_options, - filtered_config - ) + FastlaneCore::Configuration.create(target_action_class.available_options, filtered_config) end def self.report_status(branch_name:, api_key:, status:, step:, extras: {}, error_message: nil)