Skip to content

Instantly share code, notes, and snippets.

@nickludlam
Last active February 21, 2024 16:15
Show Gist options
  • Save nickludlam/8648d8b48cd081cd2f31fb723baf6ecb to your computer and use it in GitHub Desktop.
Save nickludlam/8648d8b48cd081cd2f31fb723baf6ecb to your computer and use it in GitHub Desktop.
This file will adapt the Mammoth git repo to a personal bundle identifier and development team, so it becomes locally buildable
#!/usr/bin/env ruby
# File: personalize_mammoth.rb
# Description: Adapt the Mammoth project to a personal bundle identifier and development team
# and change the entitlements files to match the desired bundle identifier
# When run again, it will revert the changes
# Usage: ruby personalize_mammoth.rb
# Deps: xcodeproj
require 'xcodeproj'
require 'yaml'
PROJECT_PATH = 'Mammoth.xcodeproj'
PERSONALIZE_CONFIG = '.personalize.yml'
# The following files should be personalized by having group.com.theblvd.mammoth.wormhole
# updated with the same change as the bundle identifier - i.e. search/replace
ENTITLEMENTS_FILES = [
'Mammoth/Mammoth.entitlements',
'Mammoth Share Extension/Mammoth Share Extension.entitlements',
'MammothNotificationServiceExtension/MammothNotificationServiceExtension.entitlements'
]
SKIP_TARGETS = ['MammothTests', 'MammothUITests']
##############################################################################
# Example .personalize.yml:
# #Search and replace done to all bundle identifiers
# ORIGINAL_BUNDLE_PREFIX: 'com.theblvd.mammoth'
# PERSONAL_BUNDLE_PREFIX: 'com.yourcompany.mammoth'
#
# #Replacement development team
# ORIGINAL_DEVELOPMENT_TEAM: 'W44P88K5SB' # this is the mammoth team
# PERSONAL_DEVELOPMENT_TEAM: 'ABCD123Z56' # from https://developer.apple.com/help/account/manage-your-team/locate-your-team-id/
##############################################################################
# The config file .personalize.yml should contain the following keys:
EXPECTED_ORIGINAL_KEYS= %w(ORIGINAL_BUNDLE_PREFIX ORIGINAL_DEVELOPMENT_TEAM)
EXPECTED_PERSONALIZED_KEYS= %w(PERSONAL_BUNDLE_PREFIX PERSONAL_DEVELOPMENT_TEAM)
EXPECTED_KEYS = EXPECTED_ORIGINAL_KEYS + EXPECTED_PERSONALIZED_KEYS
CONFIG = {}
# Load and check our config
def load_config()
if !File.exist?(PERSONALIZE_CONFIG)
puts "Error: Please create a .personalize.yml config file. See the source for details"
exit 1
end
YAML.load(File.open(PERSONALIZE_CONFIG)).each do |key, value|
CONFIG[key.to_s] = value
end
# Check that the configuration file has the expected keys
EXPECTED_KEYS.each do |key|
unless CONFIG.key?(key)
puts "Error: The configuration file #{PERSONALIZE_CONFIG} is missing the key #{key}"
exit 1
end
end
end
# Adapt the bundle identifier and team members for the main target
def update_target_config(target, original_bundle_prefix, replacement_bundle_prefix, team_id)
target.build_configurations.each do |config|
product_bundle_identifier = config.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = product_bundle_identifier.sub(original_bundle_prefix, replacement_bundle_prefix)
config.build_settings['DEVELOPMENT_TEAM'] = team_id
end
end
def is_personalized?(bundle_identifier)
bundle_identifier.start_with?(CONFIG['PERSONAL_BUNDLE_PREFIX'])
end
def update_entitlements(entitlements_file, original_bundle_prefix, replacement_bundle_prefix)
text = File.read(entitlements_file)
new_contents = text.gsub(original_bundle_prefix, replacement_bundle_prefix)
File.open(entitlements_file, "w") {|file| file.puts new_contents }
end
# Main
load_config()
project = Xcodeproj::Project.open(PROJECT_PATH)
perform_personalization = true
# Adapt the bundle identifier and team members for the test target
project.targets.each do |target|
if SKIP_TARGETS.include?(target.name)
puts "Skipping target #{target.name}"
next
end
# Get the first target bundle identifier and figure out if it's personalized already
product_bundle_identifier = target.build_configurations.first.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
if is_personalized?(product_bundle_identifier)
puts "Reverting target #{target.name} to original state"
update_target_config(target, CONFIG['PERSONAL_BUNDLE_PREFIX'], CONFIG['ORIGINAL_BUNDLE_PREFIX'], CONFIG['ORIGINAL_DEVELOPMENT_TEAM'])
perform_personalization = false # I know this is eval'd multiple times, but I'm being lazy
else
puts "Personalizing target #{target.name}"
update_target_config(target, CONFIG['ORIGINAL_BUNDLE_PREFIX'], CONFIG['PERSONAL_BUNDLE_PREFIX'], CONFIG['PERSONAL_DEVELOPMENT_TEAM'])
end
end
if perform_personalization
ENTITLEMENTS_FILES.each do |entitlements_file|
puts "Personalising entitlements file #{entitlements_file}"
update_entitlements(entitlements_file, CONFIG['ORIGINAL_BUNDLE_PREFIX'], CONFIG['PERSONAL_BUNDLE_PREFIX'])
end
else
# Do the reverse
ENTITLEMENTS_FILES.each do |entitlements_file|
puts "Reverting entitlements file #{entitlements_file}"
update_entitlements(entitlements_file, CONFIG['PERSONAL_BUNDLE_PREFIX'], CONFIG['ORIGINAL_BUNDLE_PREFIX'])
end
end
project.save
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment