-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Android and iOS app_id/package_name guessers with ability to chec…
…k config files (#10477) * Add Android and iOS app_id/package_name guessers with ability to check config files * Add clarifying comment to argument value accessing code. * Rubocop fixes to improve iteration skipping. * More clarifying comments.
- Loading branch information
Showing
7 changed files
with
305 additions
and
35 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
fastlane_core/lib/fastlane_core/android_package_name_guesser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
module FastlaneCore | ||
class AndroidPackageNameGuesser | ||
class << self | ||
def android_package_name_arg?(gem_name, arg) | ||
return arg == "--package_name" || | ||
arg == "--app_package_name" || | ||
(arg == '-p' && gem_name == 'supply') || | ||
(arg == '-a' && gem_name == 'screengrab') | ||
end | ||
|
||
def guess_package_name_from_args(gem_name, args) | ||
# args example: ["-a", "com.krausefx.app"] | ||
package_name = nil | ||
args.each_with_index do |current, index| | ||
next unless android_package_name_arg?(gem_name, current) | ||
# argument names are followed by argument values in the args array; | ||
# use [index + 1] to find the package name (range check the array | ||
# to avoid array bounds errors) | ||
package_name = args[index + 1] if args.count > index | ||
break | ||
end | ||
package_name | ||
end | ||
|
||
def guess_package_name_from_environment | ||
package_name = nil | ||
package_name ||= ENV["SUPPLY_PACKAGE_NAME"] if FastlaneCore::Env.truthy?("SUPPLY_PACKAGE_NAME") | ||
package_name ||= ENV["SCREENGRAB_APP_PACKAGE_NAME"] if FastlaneCore::Env.truthy?("SCREENGRAB_APP_PACKAGE_NAME") | ||
package_name | ||
end | ||
|
||
def guess_package_name_from_appfile | ||
CredentialsManager::AppfileConfig.try_fetch_value(:package_name) | ||
end | ||
|
||
def fetch_package_name_from_file(file_name, package_name_key) | ||
# we only care about the package name item in the configuration file, so | ||
# build an options array & Configuration with just that one key and it will | ||
# be fetched if it is present in the config file | ||
genericfile_options = [FastlaneCore::ConfigItem.new(key: package_name_key)] | ||
options = FastlaneCore::Configuration.create(genericfile_options, {}) | ||
# pass the empty proc to disable options validation, otherwise this will fail | ||
# when the other (non-package name) keys are encountered in the config file; | ||
# 3rd parameter "true" disables the printout of the contents of the | ||
# configuration file, which is noisy and confusing in this case | ||
options.load_configuration_file(file_name, proc {}, true) | ||
return options[package_name_key] | ||
rescue | ||
# any option/file error here should just be treated as identifier not found | ||
nil | ||
end | ||
|
||
def guess_package_name_from_config_files | ||
package_name = nil | ||
package_name ||= fetch_package_name_from_file("Supplyfile", :package_name) | ||
package_name ||= fetch_package_name_from_file("Screengrabfile", :app_package_name) | ||
package_name | ||
end | ||
|
||
# make a best-guess for the package_name for this project, using most-reliable signals | ||
# first and then using less accurate ones afterwards; because this method only returns | ||
# a GUESS for the package_name, it is only useful for metrics or other places where | ||
# absolute accuracy is not required | ||
def guess_package_name(gem_name, args) | ||
package_name = nil | ||
package_name ||= guess_package_name_from_args(gem_name, args) | ||
package_name ||= guess_package_name_from_environment | ||
package_name ||= guess_package_name_from_appfile | ||
package_name ||= guess_package_name_from_config_files | ||
package_name | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
fastlane_core/lib/fastlane_core/ios_app_identifier_guesser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
module FastlaneCore | ||
class IOSAppIdentifierGuesser | ||
class << self | ||
def guess_app_identifier_from_args(args) | ||
# args example: ["-a", "com.krausefx.app", "--team_id", "5AA97AAHK2"] | ||
args.each_with_index do |current, index| | ||
next unless current == "-a" || current == "--app_identifier" | ||
# argument names are followed by argument values in the args array; | ||
# use [index + 1] to find the package name (range check the array | ||
# to avoid array bounds errors) | ||
return args[index + 1] if args.count > index | ||
end | ||
nil | ||
end | ||
|
||
def guess_app_identifier_from_environment | ||
["FASTLANE", "DELIVER", "PILOT", "PRODUCE", "PEM", "SIGH", "SNAPSHOT", "MATCH"].each do |current| | ||
return ENV["#{current}_APP_IDENTIFIER"] if FastlaneCore::Env.truthy?("#{current}_APP_IDENTIFIER") | ||
end | ||
nil | ||
end | ||
|
||
def guess_app_identifier_from_appfile | ||
CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier) | ||
end | ||
|
||
def fetch_app_identifier_from_file(file_name) | ||
# we only care about the app_identifier item in the configuration file, so | ||
# build an options array & Configuration with just that one key and it will | ||
# be fetched if it is present in the config file | ||
genericfile_options = [FastlaneCore::ConfigItem.new(key: :app_identifier)] | ||
options = FastlaneCore::Configuration.create(genericfile_options, {}) | ||
# pass the empty proc to disable options validation, otherwise this will fail | ||
# when the other (non-app_identifier) keys are encountered in the config file; | ||
# 3rd parameter "true" disables the printout of the contents of the | ||
# configuration file, which is noisy and confusing in this case | ||
options.load_configuration_file(file_name, proc {}, true) | ||
return options[:app_identifier] | ||
rescue | ||
# any option/file error here should just be treated as identifier not found | ||
nil | ||
end | ||
|
||
def guess_app_identifier_from_config_files | ||
["Deliverfile", "Gymfile", "Snapfile", "Matchfile"].each do |current| | ||
app_identifier = self.fetch_app_identifier_from_file(current) | ||
return app_identifier if app_identifier | ||
end | ||
nil | ||
end | ||
|
||
# make a best-guess for the app_identifier for this project, using most-reliable signals | ||
# first and then using less accurate ones afterwards; because this method only returns | ||
# a GUESS for the app_identifier, it is only useful for metrics or other places where | ||
# absolute accuracy is not required | ||
def guess_app_identifier(args) | ||
app_identifier = nil | ||
app_identifier ||= guess_app_identifier_from_args(args) | ||
app_identifier ||= guess_app_identifier_from_environment | ||
app_identifier ||= guess_app_identifier_from_appfile | ||
app_identifier ||= guess_app_identifier_from_config_files | ||
app_identifier | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
require 'spec_helper' | ||
|
||
require 'fastlane_core/android_package_name_guesser' | ||
|
||
describe FastlaneCore::AndroidPackageNameGuesser do | ||
it 'returns nil if no clues' do | ||
# this might also fail if the environment or config files are not clean | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('fastlane', [])).to be_nil | ||
end | ||
|
||
describe 'guessing from command line args' do | ||
it 'returns Android package_name if specified with --package_name' do | ||
args = ["--package_name", "com.krausefx.app"] | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('fastlane', args)).to eq("com.krausefx.app") | ||
end | ||
|
||
it 'returns Android package_name if specified with --app_package_name' do | ||
args = ["--app_package_name", "com.krausefx.app"] | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('fastlane', args)).to eq("com.krausefx.app") | ||
end | ||
|
||
it 'returns Android package_name if specified for supply gem with -p' do | ||
args = ["-p", "com.krausefx.app"] | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('supply', args)).to eq("com.krausefx.app") | ||
end | ||
|
||
it 'returns Android package_name if specified for screengrab gem with -p' do | ||
args = ["-a", "com.krausefx.app"] | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('screengrab', args)).to eq("com.krausefx.app") | ||
end | ||
end | ||
|
||
describe 'guessing from environment' do | ||
it 'returns Android package_name present in environment' do | ||
["SUPPLY", "SCREENGRAB_APP"].each do |current| | ||
env_var_name = "#{current}_PACKAGE_NAME" | ||
package_name = "#{current}.bundle.id" | ||
ENV[env_var_name] = package_name | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('fastlane', [])).to eq(package_name) | ||
ENV.delete(env_var_name) | ||
end | ||
end | ||
end | ||
|
||
describe 'guessing from configuration files' do | ||
def allow_non_target_configuration_file(file_name) | ||
allow_any_instance_of(FastlaneCore::Configuration).to receive(:load_configuration_file).with(file_name, any_args) do |configuration, config_file_name| | ||
nil | ||
end | ||
end | ||
|
||
def allow_target_configuration_file(file_name, package_name_key) | ||
allow_any_instance_of(FastlaneCore::Configuration).to receive(:load_configuration_file).with(file_name, any_args) do |configuration, config_file_name| | ||
configuration[package_name_key] = "#{config_file_name}.bundle.id" | ||
end | ||
end | ||
|
||
it 'returns iOS app_identifier found in Supplyfile' do | ||
allow_target_configuration_file("Supplyfile", :package_name) | ||
allow_non_target_configuration_file("Screengrabfile") | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('supply', [])).to eq("Supplyfile.bundle.id") | ||
end | ||
|
||
it 'returns iOS app_identifier found in Screengrabfile' do | ||
allow_target_configuration_file("Screengrabfile", :app_package_name) | ||
allow_non_target_configuration_file("Supplyfile") | ||
expect(FastlaneCore::AndroidPackageNameGuesser.guess_package_name('screengrab', [])).to eq("Screengrabfile.bundle.id") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
require 'spec_helper' | ||
|
||
require 'fastlane_core/ios_app_identifier_guesser' | ||
|
||
describe FastlaneCore::IOSAppIdentifierGuesser do | ||
it 'returns nil if no clues' do | ||
# this might also fail if the environment or config files are not clean | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to be_nil | ||
end | ||
|
||
describe 'guessing from command line args' do | ||
it 'returns iOS app_identifier if specified with -a' do | ||
args = ["-a", "com.krausefx.app"] | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier(args)).to eq("com.krausefx.app") | ||
end | ||
|
||
it 'returns iOS app_identifier if specified with --app_identifier' do | ||
args = ["--app_identifier", "com.krausefx.app"] | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier(args)).to eq("com.krausefx.app") | ||
end | ||
end | ||
|
||
describe 'guessing from environment' do | ||
it 'returns iOS app_identifier present in environment' do | ||
["FASTLANE", "DELIVER", "PILOT", "PRODUCE", "PEM", "SIGH", "SNAPSHOT", "MATCH"].each do |current| | ||
env_var_name = "#{current}_APP_IDENTIFIER" | ||
app_identifier = "#{current}.bundle.id" | ||
ENV[env_var_name] = app_identifier | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq(app_identifier) | ||
ENV.delete(env_var_name) | ||
end | ||
end | ||
end | ||
|
||
describe 'guessing from Appfile' do | ||
it 'returns iOS app_identifier found in Appfile' do | ||
expect(CredentialsManager::AppfileConfig).to receive(:try_fetch_value).with(:app_identifier).and_return("Appfile.bundle.id") | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq("Appfile.bundle.id") | ||
end | ||
end | ||
|
||
describe 'guessing from configuration files' do | ||
def allow_non_target_configuration_file(file_name) | ||
allow_any_instance_of(FastlaneCore::Configuration).to receive(:load_configuration_file).with(file_name, any_args) do |configuration, config_file_name| | ||
nil | ||
end | ||
end | ||
|
||
def allow_target_configuration_file(file_name) | ||
allow_any_instance_of(FastlaneCore::Configuration).to receive(:load_configuration_file).with(file_name, any_args) do |configuration, config_file_name| | ||
configuration[:app_identifier] = "#{config_file_name}.bundle.id" | ||
end | ||
end | ||
|
||
it 'returns iOS app_identifier found in Deliverfile' do | ||
allow_target_configuration_file("Deliverfile") | ||
allow_non_target_configuration_file("Gymfile") | ||
allow_non_target_configuration_file("Matchfile") | ||
allow_non_target_configuration_file("Snapfile") | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq("Deliverfile.bundle.id") | ||
end | ||
|
||
it 'returns iOS app_identifier found in Gymfile' do | ||
allow_target_configuration_file("Gymfile") | ||
allow_non_target_configuration_file("Deliverfile") | ||
allow_non_target_configuration_file("Matchfile") | ||
allow_non_target_configuration_file("Snapfile") | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq("Gymfile.bundle.id") | ||
end | ||
|
||
it 'returns iOS app_identifier found in Snapfile' do | ||
allow_target_configuration_file("Snapfile") | ||
allow_non_target_configuration_file("Deliverfile") | ||
allow_non_target_configuration_file("Gymfile") | ||
allow_non_target_configuration_file("Matchfile") | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq("Snapfile.bundle.id") | ||
end | ||
|
||
it 'returns iOS app_identifier found in Matchfile' do | ||
allow_target_configuration_file("Matchfile") | ||
allow_non_target_configuration_file("Deliverfile") | ||
allow_non_target_configuration_file("Gymfile") | ||
allow_non_target_configuration_file("Snapfile") | ||
expect(FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier([])).to eq("Matchfile.bundle.id") | ||
end | ||
end | ||
end |