lib/fastlane/plugin/polidea/actions/fota_s3.rb in fastlane-plugin-polidea-3.0.1 vs lib/fastlane/plugin/polidea/actions/fota_s3.rb in fastlane-plugin-polidea-4.0.0.pre
- old
+ new
@@ -1,22 +1,17 @@
-# rubocop:disable Metrics/AbcSize
-# rubocop:disable Metrics/ClassLength
+
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_PLIST_OUTPUT_PATH = :S3_PLIST_OUTPUT_PATH
S3_APK_OUTPUT_PATH = :S3_APK_OUTPUT_PATH
S3_MAPPING_OUTPUT_PATH = :S3_MAPPING_OUTPUT_PATH
- S3_HTML_OUTPUT_PATH = :S3_HTML_OUTPUT_PATH
- S3_VERSION_OUTPUT_PATH = :S3_VERSION_OUTPUT_PATH
- S3_ICON_OUTPUT_PATH = :S3_ICON_OUTPUT_PATH
end
class FotaS3Action < Action
def self.run(config)
Fastlane::Polidea.session.action_launched("fota_s3", config)
@@ -25,429 +20,113 @@
# Calling fetch on config so that default values will be used
params = {}
params[:ipa] = config[:ipa]
params[:apk] = config[:apk]
- params[:icon] = config[:icon]
params[:dsym] = config[:dsym]
params[:mapping] = config[:mapping]
- params[:access_key] = config[:access_key]
- params[:secret_access_key] = config[:secret_access_key]
- params[:bucket] = config[:bucket]
- params[:region] = config[:region]
- params[:acl] = config[:acl]
- params[:upload_metadata] = config[:upload_metadata]
- params[:plist_template_path] = config[:plist_template_path]
- params[:html_template_path] = config[:html_template_path]
- params[:html_file_name] = config[:html_file_name]
- params[:version_template_path] = config[:version_template_path]
- params[:version_file_name] = config[:version_file_name]
- params[:acl] = config[:acl]
- params[:release_notes] = config[:release_notes]
- params[:treat_bucket_as_domain_name] = config[:treat_bucket_as_domain_name]
+ 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)
+ upload_ios(params, shuttle_client)
when :android
- upload_android(params)
+ upload_android(params, shuttle_client)
end
Fastlane::Polidea.session.action_completed("fota_s3")
return true
end
- def self.upload_ios(params)
+ def self.upload_ios(params, shuttle_client)
# Pulling parameters for other uses
- s3_region = params[:region]
- s3_subdomain = params[:region] ? "s3-#{params[:region]}" : "s3"
- s3_access_key = params[:access_key]
- s3_secret_access_key = params[:secret_access_key]
- s3_bucket = params[:bucket]
ipa_file = params[:ipa]
- icon_file = params[:icon]
dsym_file = params[:dsym]
- acl = params[:acl]
- release_notes = params[:release_notes]
- treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
+ app_identifier = params[:app_identifier]
+ prefix_schema = params[:prefix_schema]
- validate(params)
UI.user_error!("No IPA file path given, pass using `ipa: 'ipa path'`") unless ipa_file.to_s.length > 0
- UI.message("Will transform S3 urls from https://s3.amazonaws.com/#{s3_bucket} to https://#{s3_bucket}") if treat_bucket_as_domain_name
+ 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)
- bucket = get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
-
- # Gets info used for the plist
- info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(ipa_file)
-
- build_number = info['CFBundleVersion']
- bundle_id = info['CFBundleIdentifier']
- bundle_version = info['CFBundleShortVersionString']
- app_name = info['CFBundleDisplayName'] || info['CFBundleName']
- full_version = "#{bundle_version}.#{build_number}"
- url_part = get_url_part(app_name, "ios", bundle_version, build_number)
-
- plist_template_path = params[:plist_template_path]
- html_file_name = params[:html_file_name]
- version_template_path = params[:version_template_path]
- version_file_name = params[:version_file_name]
-
- ipa_file_basename = File.basename(ipa_file)
- ipa_file_name = "#{url_part}#{ipa_file_basename}"
- ipa_file_data = File.open(ipa_file, 'rb')
-
- ipa_url = self.upload_file(bucket, ipa_file_name, ipa_file_data, acl, treat_bucket_as_domain_name)
-
# Setting action and environment variables
- Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] = ipa_url
- ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] = ipa_url
+ 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
- dsym_file_basename = File.basename(dsym_file)
- dsym_file_name = "#{url_part}#{dsym_file_basename}"
- dsym_file_data = File.open(dsym_file, 'rb')
-
- dsym_url = self.upload_file(bucket, dsym_file_name, dsym_file_data, acl, treat_bucket_as_domain_name)
-
- dsym_file_data.close
+ upload_dsym_url = upload_urls['debugFileUrl']
+ self.upload_file(upload_url, dsym_file)
end
- if params[:upload_metadata] == false
- return true
- end
+ UI.success("Successfully uploaded ipa file")
- #####################################
- #
- # html and plist building
- #
- #####################################
-
- # Creating plist and html names
- plist_file_name = "#{url_part}manifest.plist"
- plist_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{plist_file_name}"
-
- html_file_name ||= "#{url_part}index.html"
- html_resources_name = "#{url_part}installation-page"
-
- version_file_name ||= "#{url_part}version.json"
-
- # grabs module
- eth = Fastlane::ErbTemplateHelper
-
- # Creates plist from template
- if plist_template_path && File.exist?(plist_template_path)
- plist_template = eth.load_from_path(plist_template_path)
- else
- plist_template = eth.load("s3_plist_template")
+ 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
- plist_render = eth.render(plist_template, {
- url: ipa_url,
- ipa_url: ipa_url,
- bundle_id: bundle_id,
- build_number: build_number,
- bundle_version: bundle_version,
- title: app_name
- })
-
- # Gets icon from ipa and uploads it
- icon_url = self.upload_icon(icon_file, url_part, bucket, acl, treat_bucket_as_domain_name)
-
- # Creates html from template
- html_render = PageGenerator.installation_page({
- url: "itms-services://?action=download-manifest&url=#{URI.encode_www_form_component(plist_url)}",
- app_version: bundle_version,
- build_number: build_number,
- app_name: app_name,
- app_icon: icon_url,
- platform: "ios",
- release_notes: release_notes
- })
-
- # Creates version from template
- if version_template_path && File.exist?(version_template_path)
- version_template = eth.load_from_path(version_template_path)
- else
- version_template = eth.load("s3_version_template")
- end
- version_render = eth.render(version_template, {
- url: plist_url,
- plist_url: plist_url,
- ipa_url: ipa_url,
- build_number: build_number,
- bundle_version: bundle_version,
- full_version: full_version
- })
-
- #####################################
- #
- # html and plist uploading
- #
- #####################################
-
- plist_url = self.upload_file(bucket, plist_file_name, plist_render, acl, treat_bucket_as_domain_name)
- html_url = self.upload_file(bucket, html_file_name, html_render, acl, treat_bucket_as_domain_name)
- self.upload_directory(bucket, html_resources_name, "#{__dir__}/../templates/installation-page", acl)
- version_url = self.upload_file(bucket, version_file_name, version_render, acl, treat_bucket_as_domain_name)
-
- # Setting action and environment variables
- Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH] = plist_url
- ENV[SharedValues::S3_PLIST_OUTPUT_PATH.to_s] = plist_url
-
- Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH] = html_url
- ENV[SharedValues::S3_HTML_OUTPUT_PATH.to_s] = html_url
-
- Actions.lane_context[SharedValues::S3_VERSION_OUTPUT_PATH] = version_url
- ENV[SharedValues::S3_VERSION_OUTPUT_PATH.to_s] = version_url
-
- UI.success("Successfully uploaded ipa file to '#{Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH]}'")
- UI.success("Successfully uploaded plist file to '#{Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH]}'")
- UI.success("Successfully uploaded html file to '#{Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH]}'")
- UI.success("Successfully uploaded version file to '#{Actions.lane_context[SharedValues::S3_VERSION_OUTPUT_PATH]}'")
-
- if icon_url
- Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH] = icon_url
- ENV[SharedValues::S3_ICON_OUTPUT_PATH.to_s] = icon_url
- UI.success("Successfully uploaded icon file to '#{Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH]}'")
- end
- if dsym_url
- Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH] = dsym_url
- ENV[SharedValues::S3_DSYM_OUTPUT_PATH.to_s] = dsym_url
- UI.success("Successfully uploaded dsym file to '#{Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH]}'")
- end
end
- def self.upload_android(params)
+ def self.upload_android(params, shuttle_client)
# Pulling parameters for other uses
- s3_region = params[:region]
- s3_access_key = params[:access_key]
- s3_secret_access_key = params[:secret_access_key]
- s3_bucket = params[:bucket]
apk_file = params[:apk]
- icon_file = params[:icon]
mapping_file = params[:mapping]
- acl = params[:acl]
- release_notes = params[:release_notes]
- treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
+ app_identifier = params[:app_identifier]
+ build_number = params[:build_number]
- validate(params)
UI.user_error!("No APK file path given, pass using `apk: 'apk path'`") unless apk_file.to_s.length > 0
- UI.message("Will transform S3 urls from https://s3.amazonaws.com/#{s3_bucket} to https://#{s3_bucket}") if treat_bucket_as_domain_name
+ 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)
- bucket = get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
-
- # Gets info used from the apk manifest
- manifest = Android::Apk.new(apk_file).manifest
-
- app_name = manifest.label
- build_number = manifest.version_code
- app_version = manifest.version_name
- url_part = get_url_part(app_name, "android", app_version, build_number)
-
- html_file_name = params[:html_file_name]
-
- apk_file_basename = File.basename(apk_file)
- apk_file_name = "#{url_part}#{apk_file_basename}"
- apk_file_data = File.open(apk_file, 'rb')
-
- apk_url = self.upload_file(bucket, apk_file_name, apk_file_data, acl, treat_bucket_as_domain_name)
-
# Setting action and environment variables
- Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH] = apk_url
- ENV[SharedValues::S3_APK_OUTPUT_PATH.to_s] = apk_url
+ 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
- mapping_file_basename = File.basename(mapping_file)
- mapping_file_name = "#{url_part}#{mapping_file_basename}"
- mapping_file_data = File.open(mapping_file, 'rb')
+ upload_mapping_file_url = upload_urls['debugFileUrl']
+ self.upload_file(upload_mapping_file_url, mapping_file)
- mapping_url = self.upload_file(bucket, mapping_file_name, mapping_file_data, acl, treat_bucket_as_domain_name)
-
# Setting action and environment variables
- Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] = mapping_url
- ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] = mapping_url
+ Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] = upload_mapping_file_url
+ ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] = upload_mapping_file_url
- mapping_file_data.close
end
- #####################################
- #
- # html building
- #
- #####################################
+ UI.success("Successfully uploaded apk file")
- # Creating html names
-
- html_file_name ||= "#{url_part}index.html"
- html_resources_name = "#{url_part}installation-page"
-
- # Gets icon from ipa and uploads it
- icon_url = self.upload_icon(icon_file, url_part, bucket, acl, treat_bucket_as_domain_name)
-
- # Creates html from template
- html_render = PageGenerator.installation_page({
- url: apk_url,
- app_version: app_version,
- build_number: build_number,
- app_name: app_name,
- app_icon: icon_url,
- platform: "android",
- release_notes: release_notes
- })
-
- html_url = self.upload_file(bucket, html_file_name, html_render, acl, treat_bucket_as_domain_name)
- self.upload_directory(bucket, html_resources_name, "#{__dir__}/../templates/installation-page", acl)
-
- Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH] = html_url
- ENV[SharedValues::S3_HTML_OUTPUT_PATH.to_s] = html_url
-
- UI.success("Successfully uploaded apk file to '#{Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH]}'")
- UI.success("Successfully uploaded html file to '#{Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH]}'")
-
- if icon_url
- Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH] = icon_url
- ENV[SharedValues::S3_ICON_OUTPUT_PATH.to_s] = icon_url
- UI.success("Successfully uploaded icon file to '#{Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH]}'")
+ if upload_mapping_file_url
+ UI.success("Successfully uploaded mapping file")
end
- if mapping_url
- UI.success("Successfully uploaded mapping file to '#{Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH]}'")
- end
end
- def self.validate(params)
- s3_access_key = params[:access_key]
- s3_secret_access_key = params[:secret_access_key]
- s3_bucket = params[:bucket]
-
- UI.user_error!("No S3 access key given, pass using `access_key: 'key'`") unless s3_access_key.to_s.length > 0
- UI.user_error!("No S3 secret access key given, pass using `secret_access_key: 'secret key'`") unless s3_secret_access_key.to_s.length > 0
- UI.user_error!("No S3 bucket given, pass using `bucket: 'bucket'`") unless s3_bucket.to_s.length > 0
+ def self.upload_file(url, build)
+ client = S3::Client.new
+ client.upload_file(url, build)
end
- def self.get_url_part(app_name, platform, app_version, build_number)
- random_part = SecureRandom.hex(10)
- "#{app_name}/#{platform}/#{app_version}_#{build_number}/#{random_part}/"
- end
-
- def self.get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
- self.s3_client(s3_access_key, s3_secret_access_key, s3_region).bucket(s3_bucket)
- end
-
- def self.s3_client(s3_access_key, s3_secret_access_key, s3_region)
- Actions.verify_gem!('aws-sdk-s3')
- require 'aws-sdk-s3'
-
- if s3_region
- s3_client = Aws::S3::Resource.new(
- access_key_id: s3_access_key,
- secret_access_key: s3_secret_access_key,
- region: s3_region
- )
- else
- s3_client = Aws::S3::Resource.new(
- access_key_id: s3_access_key,
- secret_access_key: s3_secret_access_key
- )
+ def self.base_url(environment)
+ case environment
+ when :production
+ "https://shuttle.polidea.com"
+ when :testing
+ "https://shuttle-testing.polidea.com"
end
- s3_client
end
+ private_class_method :base_url
- def self.upload_file(bucket, file_name, file_data, acl, treat_bucket_as_domain_name)
- obj = bucket.put_object({
- key: file_name,
- body: file_data,
- acl: acl,
- content_type: Mime.content_type_for_file(file_name)
- })
-
- # When you enable versioning on a S3 bucket,
- # writing to an object will create an object version
- # instead of replacing the existing object.
- # http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/ObjectVersion.html
- if obj.kind_of? Aws::S3::ObjectVersion
- obj = obj.object
- end
-
- if treat_bucket_as_domain_name
- # Return public url
- shorten_url(obj.public_url.to_s)
- else
- obj.public_url.to_s
- end
- end
-
- def self.upload_directory(bucket, directory_name, directory_path, acl)
- files = files_at_path(directory_path)
-
- files.each do |file|
- local_path = directory_path + file
- s3_path = directory_name + file
-
- bucket.put_object({
- key: s3_path,
- body: File.open(local_path),
- acl: acl,
- content_type: Mime.content_type_for_file(local_path)
- })
- end
- end
-
- def self.files_at_path(path)
- files = Dir.glob(path + "/**/*")
- to_remove = []
- files.each do |file|
- if File.directory?(file)
- to_remove.push file
- else
- file.slice! path
- end
- end
- to_remove.each do |file|
- files.delete file
- end
- return files
- end
-
- #
- # NOT a fan of this as this was taken straight from Shenzhen
- # https://github.com/nomad/shenzhen/blob/986792db5d4d16a80c865a2748ee96ba63644821/lib/shenzhen/plugins/s3.rb#L32
- #
- # Need to find a way to not use this copied method
- #
- # AGAIN, I am not happy about this right now.
- # Using this for prototype reasons.
- #
- def self.expand_path_with_substitutions_from_ipa_plist(ipa, path)
- substitutions = path.scan(/\{CFBundle[^}]+\}/)
- return path if substitutions.empty?
- info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(ipa) or return path
-
- substitutions.uniq.each do |substitution|
- key = substitution[1...-1]
- value = info[key]
- path.gsub!(Regexp.new(substitution), value) if value
- end
-
- return path
- end
-
- def self.upload_icon(icon_path, url_part, bucket, acl, treat_bucket_as_domain_name)
- return unless icon_path
- icon_file_basename = File.basename(icon_path)
- icon_file = File.open(icon_path)
- icon_file_name = "#{url_part}#{icon_file_basename}"
- self.upload_file(bucket, icon_file_name, icon_file, acl, treat_bucket_as_domain_name)
- end
-
- def self.shorten_url(url)
- uri = URI.parse(url)
- uri.scheme + ':/' + uri.path
- end
-
def self.description
- "Generates a plist file and uploads all to AWS S3"
+ "Uploads build to AWS S3"
end
def self.available_options
[
FastlaneCore::ConfigItem.new(key: :ipa,
@@ -468,89 +147,50 @@
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: :icon,
- env_name: "",
- description: "app icon file to upload",
- optional: true,
- default_value: Actions.lane_context[SharedValues::ICON_OUTPUT_PATH]),
- FastlaneCore::ConfigItem.new(key: :upload_metadata,
- env_name: "",
- description: "Upload relevant metadata for this build",
- optional: true,
- default_value: true,
- is_string: false),
- FastlaneCore::ConfigItem.new(key: :plist_template_path,
- env_name: "",
- description: "plist template path",
- optional: true),
- FastlaneCore::ConfigItem.new(key: :html_template_path,
- env_name: "",
- description: "html erb template path",
- optional: true),
- FastlaneCore::ConfigItem.new(key: :html_file_name,
- env_name: "",
- description: "uploaded html filename",
- optional: true),
- FastlaneCore::ConfigItem.new(key: :version_template_path,
- env_name: "",
- description: "version erb template path",
- optional: true),
- FastlaneCore::ConfigItem.new(key: :version_file_name,
- env_name: "",
- description: "uploaded version filename",
- optional: true),
- FastlaneCore::ConfigItem.new(key: :access_key,
- env_name: "S3_ACCESS_KEY",
- description: "AWS Access Key ID ",
- optional: true,
- default_value: ENV['AWS_ACCESS_KEY_ID']),
- FastlaneCore::ConfigItem.new(key: :secret_access_key,
- env_name: "S3_SECRET_ACCESS_KEY",
- description: "AWS Secret Access Key ",
- optional: true,
- default_value: ENV['AWS_SECRET_ACCESS_KEY']),
- FastlaneCore::ConfigItem.new(key: :bucket,
- env_name: "S3_BUCKET",
- description: "AWS bucket name",
- optional: true,
- default_value: ENV['AWS_BUCKET_NAME']),
- FastlaneCore::ConfigItem.new(key: :region,
- env_name: "S3_REGION",
- description: "AWS region (for bucket creation) ",
- optional: true,
- default_value: ENV['AWS_REGION']),
- FastlaneCore::ConfigItem.new(key: :acl,
- env_name: "S3_ACL",
- description: "Uploaded object permissions e.g public_read (default), private, public_read_write, authenticated_read ",
- optional: true,
- default_value: "public-read"),
- FastlaneCore::ConfigItem.new(key: :release_notes,
- env_name: "S3_RELEASE_NOTES",
- description: "Release notes",
- type: String,
- optional: true,
- default_value: Actions.lane_context[SharedValues::RELEASE_NOTES]),
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)
+ 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_PLIST_OUTPUT_PATH', 'Direct HTTP link to the uploaded plist 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'],
- ['S3_HTML_OUTPUT_PATH', 'Direct HTTP link to the uploaded HTML file'],
- ['S3_VERSION_OUTPUT_PATH', 'Direct HTTP link to the uploaded Version file'],
- ['S3_ICON_OUTPUT_PATH', 'Direct HTTP link to the uploaded icon file']
+ ['S3_MAPPING_OUTPUT_PATH', 'Direct HTTP link to the uploaded mapping.txt file']
]
end
def self.author
"joshdholtz"