require 'fastlane/erb_template_helper' require 'ostruct' require 'securerandom' module Fastlane module Actions module SharedValues S3_IPA_OUTPUT_PATH = :S3_IPA_OUTPUT_PATH S3_DSYM_OUTPUT_PATH = :S3_DSYM_OUTPUT_PATH S3_APK_OUTPUT_PATH = :S3_APK_OUTPUT_PATH S3_MAPPING_OUTPUT_PATH = :S3_MAPPING_OUTPUT_PATH end class FotaS3Action < Action def self.run(config) Fastlane::Polidea.session.action_launched("fota_s3", config) platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME].to_sym # Calling fetch on config so that default values will be used params = {} params[:ipa] = config[:ipa] params[:apk] = config[:apk] params[:dsym] = config[:dsym] params[:mapping] = config[:mapping] params[:environment] = config[:environment] params[:api_token] = config[:api_token] params[:app_identifier] = config[:app_identifier] params[:prefix_schema] = config[:prefix_schema] params[:build_number] = config[:build_number] shuttle_client = Shuttle::Client.new(base_url(params[:environment]), params[:api_token]) case platform when :ios upload_ios(params, shuttle_client) when :android upload_android(params, shuttle_client) end Fastlane::Polidea.session.action_completed("fota_s3") return true end def self.upload_ios(params, shuttle_client) # Pulling parameters for other uses ipa_file = params[:ipa] dsym_file = params[:dsym] app_identifier = params[:app_identifier] prefix_schema = params[:prefix_schema] UI.user_error!("No IPA file path given, pass using `ipa: 'ipa path'`") unless ipa_file.to_s.length > 0 upload_urls = shuttle_client.get_upload_urls('ios', app_identifier, prefix_schema) upload_build_url = upload_urls['buildUrl'] self.upload_file(upload_build_url, ipa_file) # Setting action and environment variables Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] = upload_build_url ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] = upload_build_url if dsym_file upload_dsym_url = upload_urls['debugFileUrl'] self.upload_file(upload_url, dsym_file) end UI.success("Successfully uploaded ipa file") if upload_dsym_url Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH] = upload_dsym_url ENV[SharedValues::S3_DSYM_OUTPUT_PATH.to_s] = upload_dsym_url UI.success("Successfully uploaded dsym file") end end def self.upload_android(params, shuttle_client) # Pulling parameters for other uses apk_file = params[:apk] mapping_file = params[:mapping] app_identifier = params[:app_identifier] build_number = params[:build_number] UI.user_error!("No APK file path given, pass using `apk: 'apk path'`") unless apk_file.to_s.length > 0 upload_urls = shuttle_client.get_upload_urls('android', app_identifier, build_number) upload_build_url = upload_urls['buildUrl'] self.upload_file(upload_build_url, apk_file) # Setting action and environment variables Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH] = upload_build_url ENV[SharedValues::S3_APK_OUTPUT_PATH.to_s] = upload_build_url if mapping_file upload_mapping_file_url = upload_urls['debugFileUrl'] self.upload_file(upload_mapping_file_url, mapping_file) # Setting action and environment variables Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] = upload_mapping_file_url ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] = upload_mapping_file_url end UI.success("Successfully uploaded apk file") if upload_mapping_file_url UI.success("Successfully uploaded mapping file") end end def self.upload_file(url, build) client = S3::Client.new client.upload_file(url, build) end def self.base_url(environment) case environment when :production "https://shuttle.polidea.com" when :testing "https://shuttle-testing.polidea.com" end end private_class_method :base_url def self.description "Uploads build to AWS S3" end def self.available_options [ FastlaneCore::ConfigItem.new(key: :ipa, env_name: "", description: ".ipa file for the build", optional: true, default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]), FastlaneCore::ConfigItem.new(key: :dsym, env_name: "", description: "zipped .dsym package for the build", optional: true, default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH]), FastlaneCore::ConfigItem.new(key: :apk, env_name: "", description: ".apk file for the build", optional: true, default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]), FastlaneCore::ConfigItem.new(key: :mapping, env_name: "", description: "The path to the mapping.txt file", optional: true, default_value: Actions.lane_context[SharedValues::GRADLE_MAPPING_TXT_OUTPUT_PATH]), FastlaneCore::ConfigItem.new(key: :treat_bucket_as_domain_name, description: "If it's true, it transforms all urls from https://s3.amazonaws.com/BUCKET_NAME to https://BUCKET_NAME", is_string: false, optional: true, default_value: true), FastlaneCore::ConfigItem.new(key: :environment, description: "Select environment, defaults to :production", type: Symbol, default_value: :production, optional: true), FastlaneCore::ConfigItem.new(key: :api_token, env_name: "SHUTTLE_API_TOKEN", description: "API Token for Shuttle", verify_block: proc do |api_token| UI.user_error!("No API token for Shuttle given, pass using `api_token: 'token'`") unless api_token and !api_token.empty? end), FastlaneCore::ConfigItem.new(key: :app_identifier, description: "App identifier, either bundle id or package name", type: String, default_value: Actions.lane_context[SharedValues::APP_IDENTIFIER]), FastlaneCore::ConfigItem.new(key: :prefix_schema, env_name: "SHUTTLE_PREFIX_SCHEMA", description: "Prefix schema in uploaded app", default_value: Actions.lane_context[SharedValues::PREFIX_SCHEMA], optional: true), FastlaneCore::ConfigItem.new(key: :build_number, description: "Build number, eg. 1337", is_string: false, default_value: Actions.lane_context[SharedValues::BUILD_NUMBER], verify_block: proc do |build_number| UI.user_error!("No value found for 'build_number'") unless build_number and build_number.kind_of? Integer end) ] end def self.output [ ['S3_IPA_OUTPUT_PATH', 'Direct HTTP link to the uploaded ipa file'], ['S3_DSYM_OUTPUT_PATH', 'Direct HTTP link to the uploaded dsym file'], ['S3_APK_OUTPUT_PATH', 'Direct HTTP link to the uploaded apk file'], ['S3_MAPPING_OUTPUT_PATH', 'Direct HTTP link to the uploaded mapping.txt file'] ] end def self.author "joshdholtz" end def self.is_supported?(platform) [:ios, :android].include? platform end end end end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/ClassLength