Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command to configure project for order files #7

Merged
merged 6 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions emerge_cli.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'open3', '~> 0.2.1'
spec.add_dependency 'tty-prompt', '~> 0.23.1'
spec.add_dependency 'tty-table', '~> 0.12.0'
spec.add_dependency 'xcodeproj', '~> 1.27.0'

spec.add_development_dependency 'minitest', '~> 5.25.1'
spec.add_development_dependency 'minitest-reporters', '~> 1.7.1'
Expand Down
100 changes: 100 additions & 0 deletions lib/commands/config/orderfiles/orderfiles_ios.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require 'xcodeproj'

module EmergeCLI
module Commands
module Config
class OrderFilesIOS < EmergeCLI::Commands::GlobalOptions
desc 'Configure order files for iOS'

# Optional options
option :only_enable_linkmaps, type: :boolean, required: false, desc: 'Only enable linkmaps'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option is a bit confusing, not sure what it's doing.

Copy link
Collaborator

@trevor-e trevor-e Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see below it's related to the download script, maybe that could instead be skip_download_script?

option :project_path, type: :string, required: false,
desc: 'Path to the xcode project (will use first found if not provided)'

# Constants
LINK_MAPS_CONFIG = 'LD_GENERATE_MAP_FILE'.freeze
LINK_MAPS_PATH = 'LD_MAP_FILE_PATH'.freeze
PATH_TO_LINKMAP = '$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt'.freeze
ORDER_FILE = 'ORDER_FILE'.freeze
ORDER_FILE_PATH = '$(PROJECT_DIR)/orderfiles/orderfile.txt'.freeze

def initialize; end

def call(**options)
@options = options
before(options)

if @options[:project_path]
project = Xcodeproj::Project.open(@options[:project_path])
else
project = Xcodeproj::Project.open(Dir.glob('*.xcodeproj').first)
Logger.warn 'No project path provided, using first found xcodeproj in current directory'
end

enable_linkmaps(project)

add_order_files_download_script(project) unless @options[:only_enable_linkmaps]

project.save
end

private

def enable_linkmaps(project)
Logger.info 'Enabling Linkmaps'
project.targets.each do |target|
# Only do it for app targets
next unless target.product_type == 'com.apple.product-type.application'

Logger.info " Target: #{target.name}"
target.build_configurations.each do |config|
config.build_settings[LINK_MAPS_CONFIG] = 'YES'
config.build_settings[LINK_MAPS_PATH] = PATH_TO_LINKMAP
end
end
end

def add_order_files_download_script(project)
Logger.info 'Adding order files download script'
project.targets.each do |target|
# Only do it for app targets
next unless target.product_type == 'com.apple.product-type.application'

Logger.info " Target: #{target.name}"

# Create the script phase if it doesn't exist
phase = target.shell_script_build_phases.find { |item| item.name == 'Download Order Files' }
if phase.nil?
Logger.info " Creating script 'Download Order Files'"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would prefix with our name, e.g. EmergeTools Download Order Files

phase = target.new_shell_script_build_phase('Download Order Files')
phase.shell_script = "\
if [ \"$CONFIGURATION\" != \"Release\" ]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using a heredoc avoid all the escaping, or is that necessary for the script itself?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never tried heredoc, time to test it

echo \"Skipping script for non-Release build\"
exit 0
fi

if curl --fail \"https://order-files-prod.emergetools.com/$PRODUCT_BUNDLE_IDENTIFIER/$MARKETING_VERSION\" \\
-H \"X-API-Token: $EMERGE_API_TOKEN\" -o ORDER_FILE.gz ; then
mkdir -p \"$PROJECT_DIR/orderfiles\"
gunzip -c ORDER_FILE.gz > $PROJECT_DIR/orderfiles/orderfile.txt
else
echo \"cURL request failed. Creating an empty file.\"
mkdir -p \"$PROJECT_DIR/orderfiles\"
touch \"$PROJECT_DIR/orderfiles/orderfile.txt\"
fi;"
phase.output_paths = ['$(PROJECT_DIR)/orderfiles/orderfile.txt']
else
Logger.info " 'Download Order Files' already exists"
end
# Make sure it is the first build phase
target.build_phases.move(phase, 0)

target.build_configurations.each do |config|
config.build_settings[ORDER_FILE] = ORDER_FILE_PATH
end
end
end
end
end
end
end
2 changes: 2 additions & 0 deletions lib/emerge_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require_relative './commands/upload/snapshots/client_libraries/default'
require_relative './commands/integrate/fastlane'
require_relative './commands/config/snapshots/snapshots_ios'
require_relative './commands/config/orderfiles/orderfiles_ios'

require_relative './utils/git_info_provider'
require_relative './utils/git_result'
Expand All @@ -30,6 +31,7 @@ module EmergeCLI

register 'configure' do |prefix|
prefix.register 'snapshots-ios', Commands::Config::SnapshotsIOS, aliases: ['c']
prefix.register 'order-files-ios', Commands::Config::OrderFilesIOS, aliases: ['o']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'm thinking maybe we want to avoid aliases for the subcommands and instead have one for configure? Also the c above for 'snapshots-ios' is probably a mistake.

end
end

Expand Down
65 changes: 65 additions & 0 deletions test/commands/config/orderfiles/orderfiles_ios_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'test_helper'

module EmergeCLI
module Commands
module Config
class OrderFilesIOSTest < Minitest::Test
LINK_MAPS_CONFIG = 'LD_GENERATE_MAP_FILE'.freeze
LINK_MAPS_PATH = 'LD_MAP_FILE_PATH'.freeze
PATH_TO_LINKMAP = '$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt'.freeze
ORDER_FILE = 'ORDER_FILE'.freeze
ORDER_FILE_PATH = '$(PROJECT_DIR)/orderfiles/orderfile.txt'.freeze

def setup
@command = EmergeCLI::Commands::Config::OrderFilesIOS.new

FileUtils.mkdir_p('tmp/test_orderfiles')
FileUtils.cp_r('test/test_files/ExampleApp.xcodeproj', 'tmp/test_orderfiles/ExampleApp.xcodeproj')
end

def teardown
FileUtils.rm_rf('tmp/test_orderfiles')
end

def test_linkmaps_are_enabled_and_orderfiles_are_downloaded
options = {
project_path: 'tmp/test_orderfiles/ExampleApp.xcodeproj'
}

@command.call(**options)

project = Xcodeproj::Project.open('tmp/test_orderfiles/ExampleApp.xcodeproj')

project.targets[0].build_configurations.each do |config|
assert_equal PATH_TO_LINKMAP, config.build_settings[LINK_MAPS_PATH]
assert_equal 'YES', config.build_settings[LINK_MAPS_CONFIG]
assert_equal ORDER_FILE_PATH, config.build_settings[ORDER_FILE]
end

phase = project.targets[0].shell_script_build_phases.find { |item| item.name == 'Download Order Files' }
assert_equal ORDER_FILE_PATH, phase.output_paths[0]
end

def test_linkmaps_are_enabled_only
options = {
project_path: 'tmp/test_orderfiles/ExampleApp.xcodeproj',
only_enable_linkmaps: true
}

@command.call(**options)

project = Xcodeproj::Project.open('tmp/test_orderfiles/ExampleApp.xcodeproj')

project.targets[0].build_configurations.each do |config|
assert_equal PATH_TO_LINKMAP, config.build_settings[LINK_MAPS_PATH]
assert_equal 'YES', config.build_settings[LINK_MAPS_CONFIG]
refute_equal ORDER_FILE_PATH, config.build_settings[ORDER_FILE]
end

phase = project.targets[0].shell_script_build_phases.find { |item| item.name == 'Download Order Files' }
assert_nil phase
end
end
end
end
end
Loading