Created
May 31, 2026 10:55
-
-
Save amirrajan/96552ee3fd5b46ce9aff889f091bf36b to your computer and use it in GitHub Desktop.
DragonRuby Game Toolkit - iOS Wizard
This file contains hidden or 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
| # coding: utf-8 | |
| # Copyright 2019 DragonRuby LLC | |
| # MIT License | |
| # ios_wizard.rb has been released under MIT (*only this file*). | |
| # Contributors outside of DragonRuby who also hold Copyright: Michał Dudziński | |
| class IOSWizard < Wizard | |
| def help | |
| puts <<~S | |
| * INFO: Help for #{self.class.name} | |
| Here are the available options for this wizard (these options can be invoked through the DragonRuby Console): | |
| ** Device | |
| *** Deploy app to device connected via USB: | |
| #+begin_src | |
| $wizards.ios.start env: :dev | |
| #+end_src | |
| *** Deploy app to device connected via USB with remote hotload: | |
| #+begin_src | |
| $wizards.ios.start env: :hotload | |
| #+end_src | |
| *** Do not uninstall game before deploy the new version | |
| Supported in both ~:dev~ and ~:hotload~ | |
| #+begin_src | |
| $wizards.ios.start env: :dev, uninstall: false | |
| #+end_src | |
| ** Simulator | |
| *** Deploy app to simulator | |
| The default simulator is iPhone 13 Pro Max and will be automatically installed if it doesn't exist. | |
| #+begin_src | |
| $wizards.ios.start env: :sim | |
| #+end_src | |
| *** Deploy app to simulator and specify a device (partial device name allowed): | |
| #+begin_src | |
| $wizards.ios.start env: :sim, sim_name: "iPad Pro" | |
| #+end_src | |
| *** Reset simulators | |
| Delete all content from simulators and reset them | |
| #+begin_src | |
| $wizards.ios.reset_simulators | |
| #+end_src | |
| ** Distribution | |
| *** Package app for production release: | |
| #+begin_src | |
| $wizards.ios.start env: :prod | |
| #+end_src | |
| S | |
| end | |
| def initialize | |
| @doctor_executed_at = 0 | |
| end | |
| def root_dir | |
| $gtk.get_base_dir | |
| end | |
| def prerequisite_steps | |
| [ | |
| :check_for_xcode, | |
| :check_for_brew, | |
| :check_for_certs, | |
| ] | |
| end | |
| def app_metadata_retrieval_steps | |
| [ | |
| :determine_team_identifier, | |
| :determine_app_name, | |
| :determine_app_id, | |
| ] | |
| end | |
| def steps_dev_build | |
| [ | |
| *prerequisite_steps, | |
| :check_for_device, | |
| :check_for_dev_profile, | |
| :determine_app_version, | |
| *app_metadata_retrieval_steps, | |
| :determine_devcert, | |
| :clear_tmp_directory, | |
| :stage_ios_app, | |
| :development_write_info_plist, | |
| :write_entitlements_plist, | |
| :compile_icons, | |
| :clear_payload_directory, | |
| :create_dev_payload_directory, | |
| :create_payload, | |
| :code_sign_binary, | |
| :create_ipa, | |
| :deploy_to_device | |
| ] | |
| end | |
| def steps_test_build | |
| [ | |
| *prerequisite_steps, | |
| :check_for_device, | |
| :check_for_dev_profile, | |
| :determine_app_version, | |
| *app_metadata_retrieval_steps, | |
| :determine_devcert, | |
| :clear_tmp_directory, | |
| :stage_ios_app, | |
| :development_write_info_plist, | |
| :write_entitlements_plist, | |
| :compile_icons, | |
| :clear_payload_directory, | |
| :create_test_payload_directory, | |
| :create_payload, | |
| :code_sign_binary, | |
| :create_ipa, | |
| :deploy_to_device | |
| ] | |
| end | |
| def steps_sim_build | |
| [ | |
| *prerequisite_steps, | |
| :install_simulator_if_needed, | |
| :determine_app_version, | |
| *app_metadata_retrieval_steps, | |
| :determine_devcert, | |
| :clear_tmp_directory, | |
| :stage_sim_app, | |
| :development_write_info_plist, | |
| :write_entitlements_plist, | |
| :compile_icons, | |
| :clear_payload_directory, | |
| :create_sim_payload_directory, | |
| :create_payload, | |
| :code_sign_binary, | |
| :create_ipa, | |
| :deploy_to_sim | |
| ] | |
| end | |
| def steps_prod_build | |
| [ | |
| *prerequisite_steps, | |
| :check_for_distribution_profile, | |
| :determine_app_version, | |
| *app_metadata_retrieval_steps, | |
| :determine_prodcert, | |
| :clear_tmp_directory, | |
| :stage_ios_app, | |
| :production_write_info_plist, | |
| :write_entitlements_plist, | |
| :compile_icons, | |
| :clear_payload_directory, | |
| :create_prod_payload_directory, | |
| :create_payload, | |
| :code_sign_binary, | |
| :create_ipa, | |
| :print_publish_help | |
| ] | |
| end | |
| def get_reserved_sprite png | |
| sprite_path = ".dragonruby/sprites/wizards/ios/#{png}" | |
| if !$gtk.ivar :rcb_release_mode | |
| sprite_path = "deploy_template/#{sprite_path}" | |
| $gtk.reset_sprite sprite_path | |
| end | |
| if !$gtk.read_file sprite_path | |
| log_error "png #{png} not found." | |
| end | |
| sprite_path | |
| end | |
| def production_build? | |
| @build_type == :prod | |
| end | |
| def dev_build? | |
| @build_type == :dev || hotload_build? || @build_type == :test | |
| end | |
| def sim_build? | |
| @build_type == :sim | |
| end | |
| def hotload_build? | |
| @build_type == :hotload || sim_build? | |
| end | |
| def start opts = nil | |
| @opts = opts || {} | |
| if !(@opts.is_a? Hash) || !([:dev, :prod, :hotload, :sim, :test].include?(@opts[:env])) | |
| process_wizard_exception WizardException.new( | |
| "* $wizards.ios.start needs to be provided an ~env:~ option.", | |
| "** To deploy your app to an iOS device connected to your computer:\n $wizards.ios.start env: :dev", | |
| "** To deploy your app with hotloading to an iOS device connected to your computer:\n $wizards.ios.start env: :hotload", | |
| "** To deploy your app to the iOS Simulator:\n $wizards.ios.start env: :sim", | |
| "** To deploy your app for sale on the AppStore:\n $wizards.ios.start env: :prod", | |
| "** For more help type:\n $wizards.ios.help", | |
| ) | |
| end | |
| @should_uninstall = @opts[:uninstall] | |
| @build_type = @opts[:env] | |
| @certificate_name = nil | |
| @app_version = opts[:version] | |
| @app_version = "1.0" if @opts[:env] == :dev && !@app_version | |
| init_wizard_status | |
| $console.set_command_silent "Starting iOS Wizard with #{@opts}, please wait..." | |
| GTK.on_tick_count Kernel.tick_count + 30 do | |
| execute_steps get_steps_to_execute | |
| $console.set_command_silent "" | |
| end | |
| nil | |
| end | |
| def always_fail | |
| return false if $gtk.ivar :rcb_release_mode | |
| return true | |
| end | |
| def check_for_xcode | |
| result = sh "xcrun simctl list devices" | |
| simctl_missing = result.include? "unable to find utility" | |
| if !cli_app_exist?(xcodebuild_cli_app) || simctl_missing | |
| raise WizardException.new( | |
| "* You need Xcode to use $wizards.ios.start.", | |
| { w: 75, h: 75, path: get_reserved_sprite("xcode.png") }, | |
| "** 1. Go to http://developer.apple.com and register.", | |
| "** 2. Download Xcode 11.3+ from http://developer.apple.com/downloads.", | |
| " NOTE: DO NOT install Xcode from the App Store. Use the link above.", | |
| { w: 700, h: 359, path: get_reserved_sprite("xcode-downloads.png") }, | |
| "** 3. After installing. Open up Xcode to accept the EULA." | |
| ) | |
| end | |
| :success | |
| end | |
| def check_for_brew | |
| if !cli_app_exist?('brew') | |
| raise WizardException.new( | |
| "* You need to install Brew.", | |
| { w: 700, h: 388, path: get_reserved_sprite("brew.png") }, | |
| "** 1. Go to http://brew.sh.", | |
| "** 2. Copy the command that starts with `/bin/bash -c` on the site.", | |
| "** 3. Open Terminal and run the command you copied from the website.", | |
| { w: 700, h: 99, path: get_reserved_sprite("terminal.png") }, | |
| ) | |
| end | |
| :success | |
| end | |
| def init_wizard_status | |
| @wizard_status = {} | |
| get_steps_to_execute.each do |m| | |
| @wizard_status[m] = { result: :not_started } | |
| end | |
| previous_step = nil | |
| next_step = nil | |
| get_steps_to_execute.each_cons(2) do |current_step, next_step| | |
| @wizard_status[current_step][:next_step] = next_step | |
| end | |
| get_steps_to_execute.reverse.each_cons(2) do |current_step, previous_step| | |
| @wizard_status[current_step][:previous_step] = previous_step | |
| end | |
| end | |
| def restart | |
| init_wizard_status | |
| start | |
| end | |
| def reset | |
| init_wizard_status | |
| end | |
| def check_for_distribution_profile | |
| @provisioning_profile_path = "profiles/distribution.mobileprovision" | |
| if !($gtk.read_file @provisioning_profile_path) | |
| $gtk.system "mkdir -p #{root_dir}/profiles" | |
| $gtk.system "open #{root_dir}/profiles" | |
| $gtk.system "echo Download the mobile provisioning profile and place it here with the name distribution.mobileprovision > #{root_dir}/profiles/README.txt" | |
| raise WizardException.new( | |
| "* I didn't find a mobile provision.", | |
| "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".", | |
| "** 2. Add an App Identifier.", | |
| "** 3. Select the App IDs option from the list.", | |
| { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") }, | |
| "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.", | |
| { w: 365, h: 69, path: get_reserved_sprite("device-link.png") }, | |
| "** 5. Create a Profile. Associate your certs, id, and device.", | |
| { w: 300, h: 122, path: get_reserved_sprite("profiles.png") }, | |
| "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.", | |
| { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") }, | |
| ) | |
| end | |
| :success | |
| end | |
| def check_for_dev_profile | |
| @provisioning_profile_path = "profiles/development.mobileprovision" | |
| if !($gtk.read_file @provisioning_profile_path) | |
| $gtk.system "mkdir -p #{root_dir}/profiles" | |
| $gtk.system "open #{root_dir}/profiles" | |
| $gtk.system "echo Download the mobile provisioning profile and place it here with the name development.mobileprovision > #{root_dir}/profiles/README.txt" | |
| raise WizardException.new( | |
| "* I didn't find a mobile provision.", | |
| "** 1. Go to http://developer.apple.com and click \"Certificates, IDs & Profiles\".", | |
| "** 2. Add an App Identifier.", | |
| "** 3. Select the App IDs option from the list.", | |
| { w: 700, h: 75, path: get_reserved_sprite("identifiers.png") }, | |
| "** 4. Add your Device next. You can use idevice_id -l to get the UUID of your device.", | |
| { w: 365, h: 69, path: get_reserved_sprite("device-link.png") }, | |
| "** 5. Create a Profile. Associate your certs, id, and device.", | |
| { w: 300, h: 122, path: get_reserved_sprite("profiles.png") }, | |
| "** 6. Download the mobile provision and save it to 'profiles/development.mobileprovision'.", | |
| { w: 200, h: 124, path: get_reserved_sprite("profiles-folder.png") }, | |
| "* NOTE: If you don't want to create a mobile provision right now, you can deploy to the simulator without one. Run the following command:", | |
| <<~S | |
| #+begin_src ruby | |
| # run this in the console to deploy to the simulator (no provisioning profile needed) | |
| $wizards.ios.start env: :sim | |
| #+end_src | |
| S | |
| ) | |
| end | |
| :success | |
| end | |
| def provisioning_profile_path environment | |
| return File.expand_path("profiles/distribution.mobileprovision") if environment == :prod | |
| return File.expand_path("profiles/development.mobileprovision") | |
| end | |
| def ios_metadata_template | |
| <<-S | |
| # ios_metadata.txt is used by the Pro version of DragonRuby Game Toolkit to create iOS apps. | |
| # Information about the Pro version can be found at: http://dragonruby.org/toolkit/game#purchase | |
| # teamid needs to be set to your assigned Team Id which can be found at https://developer.apple.com/account/#/membership/ | |
| teamid= | |
| # appid needs to be set to your application identifier which can be found at https://developer.apple.com/account/resources/identifiers/list | |
| appid= | |
| # appname is the name you want to show up underneath the app icon on the device. Keep it under 10 characters. | |
| appname= | |
| # devcert is the certificate to use for development/deploying to your local device. This is the NAME of the certificate as it's displayed in Keychain Access. | |
| devcert= | |
| # prodcert is the certificate to use for distribution to the app store. This is the NAME of the certificate as it's displayed in Keychain Access. | |
| prodcert= | |
| S | |
| end | |
| def ios_metadata | |
| contents = $gtk.read_file 'metadata/ios_metadata.txt' | |
| if !contents | |
| $gtk.write_file 'metadata/ios_metadata.txt', ios_metadata_template | |
| contents = $gtk.read_file 'metadata/ios_metadata.txt' | |
| end | |
| kvps = contents.each_line | |
| .reject { |l| l.strip.length == 0 || (l.strip.start_with? "#") } | |
| .map do |l| | |
| key, value = l.split("=") | |
| [key.strip.to_sym, value.strip] | |
| end.flatten | |
| Hash[*kvps] | |
| end | |
| def game_metadata | |
| contents = $gtk.read_file 'metadata/game_metadata.txt' | |
| kvps = contents.each_line | |
| .reject { |l| l.strip.length == 0 || (l.strip.start_with? "#") } | |
| .map do |l| | |
| key, value = l.split("=") | |
| [key.strip.to_sym, value.strip] | |
| end.flatten | |
| Hash[*kvps] | |
| end | |
| def raise_ios_metadata_required | |
| raise WizardException.new( | |
| "* mygame/metadata/ios_metadata.txt needs to be filled out.", | |
| "You need to update metadata/ios_metadata.txt with a valid teamid, appname, appid, devcert, and prodcert.", | |
| "Instructions for where the values should come from are within metadata/ios_metadata.txt." | |
| ) | |
| end | |
| def determine_team_identifier | |
| @team_id = (ios_metadata.teamid || "").strip | |
| if @build_type == :sim && @team_id.length == 0 | |
| log_warn <<-S | |
| * WARNING: =mygame/metadata/ios_metadata.txt= does not specify =teamid= | |
| Since this is a simulator build, the default =teamid= of =UNKNOWN= will be used. | |
| S | |
| @team_id = "UNKNOWN" | |
| elsif @team_id.length == 0 | |
| raise_ios_metadata_required if @team_id.strip.length == 0 | |
| end | |
| log_info "Team Identifer is: #{@team_id}" | |
| :success | |
| end | |
| def determine_app_name | |
| @app_name = (ios_metadata.appname || "").strip | |
| if @build_type == :sim && @app_name.length == 0 | |
| log_warn <<-S | |
| * WARNING: =mygame/metadata/ios_metadata.txt= does not specify =appname= | |
| Since this is a simulator build, the default =appname= of =Game= will be used. | |
| S | |
| @app_name = "Game" | |
| elsif @app_name.length == 0 | |
| raise_ios_metadata_required if @app_name.length == 0 | |
| end | |
| log_info "App name is: #{@app_name}." | |
| :success | |
| end | |
| def provisioning_profile_xml environment | |
| xml = $gtk.read_file (provisioning_profile_path environment) | |
| scrubbed = xml.each_line.map do |l| | |
| if l.strip.start_with? "<" | |
| if l.start_with? '</plist>' | |
| '</plist>' | |
| elsif l.include? "Apple Inc." | |
| nil | |
| elsif l.include? '<data>' | |
| nil | |
| else | |
| l | |
| end | |
| else | |
| nil | |
| end | |
| end.reject { |l| !l }.join | |
| $gtk.parse_xml scrubbed | |
| end | |
| def determine_app_id | |
| @app_id = (ios_metadata.appid || "").strip | |
| if @build_type == :sim && @app_id.length == 0 | |
| log_warn <<-S | |
| * WARNING: =mygame/metadata/ios_metadata.txt= does not specify =appid= | |
| Since this is a simulator build, the default =appid= of =com.unknown.game= will be used. | |
| S | |
| @app_id = "com.unknown.game" | |
| elsif @app_id.length == 0 | |
| raise_ios_metadata_required if @app_id.strip.length == 0 | |
| end | |
| log_info "App Identifier is set to: #{@app_id}" | |
| :success | |
| end | |
| def determine_devcert | |
| @certificate_name = (ios_metadata.devcert || "").strip | |
| if @build_type == :sim && @certificate_name.length == 0 | |
| log_warn <<-S | |
| * WARNING: =mygame/metadata/ios_metadata.txt= does not specify =devcert= | |
| Since this is a simulator build, the default =devcert= of =Unknown= will be used. | |
| S | |
| @certificate_name = "Unknown" | |
| elsif @certificate_name.length == 0 | |
| raise_ios_metadata_required | |
| end | |
| log_info "Dev Certificate is set to: #{@certificate_name}" | |
| :success | |
| end | |
| def determine_prodcert | |
| @certificate_name = ios_metadata.prodcert | |
| raise_ios_metadata_required if @certificate_name.strip.length == 0 | |
| log_info "Production (Distribution) Certificate is set to: #{@certificate_name}" | |
| :success | |
| end | |
| def set_app_name name | |
| @app_name = name | |
| start | |
| end | |
| def set_dev_profile path | |
| if !$gtk.read_file path | |
| log_error "I couldn't find a development profile at #{path}." | |
| ask_for_dev_profile | |
| else | |
| @provisioning_profile_path = path | |
| start | |
| end | |
| end | |
| def clear_tmp_directory | |
| sh "rm -rf #{tmp_directory}" | |
| :success | |
| end | |
| def set_app_id id | |
| log_info = "App Id set to: #{id}" | |
| @app_id = id | |
| start | |
| end | |
| def check_for_device | |
| log_info "Looking for device." | |
| if !cli_app_exist?(idevice_id_path) | |
| raise WizardException.new( | |
| "* It doesn't look like you have the libimobiledevice iOS protocol library installed.", | |
| "** 1. Open Terminal.", | |
| { w: 700, h: 99, path: get_reserved_sprite("terminal.png") }, | |
| "** 2. Run: `brew install libimobiledevice`.", | |
| { w: 500, h: 93, path: get_reserved_sprite("brew-install-libimobiledevice.png") }, | |
| ) | |
| end | |
| if !cli_app_exist?(ideviceinstaller_cli_app) | |
| raise WizardException.new( | |
| "* It doesn't look like you have the libimobiledevice iOS protocol library installed.", | |
| "** 1. Open Terminal.", | |
| { w: 700, h: 99, path: get_reserved_sprite("terminal.png") }, | |
| "** 2. Run: `brew install ideviceinstaller`.", | |
| { w: 500, h: 91, path: get_reserved_sprite("brew-install-ideviceinstaller.png") }, | |
| ) | |
| end | |
| if connected_devices.length == 0 | |
| raise WizardException.new("* I couldn't find any connected devices. Connect your iOS device to your Mac and try again.") | |
| end | |
| @device_id = connected_devices.first | |
| log_info "I will be using device with UUID #{@device_id}" | |
| :success | |
| end | |
| def check_for_certs | |
| log_info "Attempting to find certificates on your computer." | |
| if production_build? | |
| @certificate_name = ios_metadata[:prodcert] | |
| elsif dev_build? | |
| @certificate_name = ios_metadata[:devcert] | |
| else | |
| raise "I don't know how to ~check_for_certs~ for a build_type/env of #{@build_type}." | |
| end | |
| log_info "I will be using certificate: '#{@certificate_name}'." | |
| :success | |
| end | |
| def codesign_allocate_path | |
| "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate" | |
| end | |
| def codesign_path | |
| "/usr/bin/codesign" | |
| end | |
| def idevice_id_path | |
| "idevice_id" | |
| end | |
| def ideviceinstaller_cli_app | |
| "ideviceinstaller" | |
| end | |
| def security_cli_app | |
| "/usr/bin/security" | |
| end | |
| def xcodebuild_cli_app | |
| "xcodebuild" | |
| end | |
| def connected_devices | |
| sh("idevice_id -l").strip.each_line.map do |l| | |
| l.strip | |
| end.reject { |l| l.length == 0 } | |
| end | |
| def cli_app_exist? app | |
| `which #{app}`.strip.length != 0 | |
| end | |
| def write_entitlements_plist | |
| if production_build? | |
| entitlement_plist_string = <<-XML | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>application-identifier</key> | |
| <string>:app_id</string> | |
| <key>beta-reports-active</key> | |
| <true/> | |
| </dict> | |
| </plist> | |
| XML | |
| else | |
| entitlement_plist_string = <<-XML | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>application-identifier</key> | |
| <string>:app_id</string> | |
| <key>get-task-allow</key> | |
| <true/> | |
| </dict> | |
| </plist> | |
| XML | |
| end | |
| log_info "Creating Entitlements.plist" | |
| $gtk.write_file_root "tmp/ios/Entitlements.plist", entitlement_plist_string.gsub(":app_id", "#{@team_id}.#{@app_id}").strip | |
| $gtk.write_file_root "tmp/ios/Entitlements.txt", entitlement_plist_string.gsub(":app_id", "#{@team_id}.#{@app_id}").strip | |
| sh "/usr/bin/plutil -convert binary1 \"#{tmp_directory}/Entitlements.plist\"" | |
| sh "/usr/bin/plutil -convert xml1 \"#{tmp_directory}/Entitlements.plist\"" | |
| @entitlement_plist_written = true | |
| :success | |
| end | |
| def code_sign_binary | |
| log_info "Signing app with #{@certificate_name}." | |
| sh "xattr -cr \"#{tmp_directory}/ipa_root/Payload/#{@app_name}.app\"" | |
| sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/ipa_root/Payload/#{@app_name}.app\"" | |
| sh "xattr -cr \"#{tmp_directory}/ipa_root/Payload/#{@app_name}.app/#{@app_name}\"" | |
| sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/ipa_root/Payload/#{@app_name}.app/#{@app_name}\"" | |
| @code_sign_completed = true | |
| :success | |
| end | |
| def __get_plist_orientation_values_xml__ | |
| values_xml = __get_plist_orientation_values__.map do |v| | |
| <<-S.rstrip | |
| <string>#{v}</string> | |
| S | |
| end.join "\n" | |
| array_xml = <<-S.rstrip | |
| <array> | |
| #{values_xml} | |
| </array> | |
| S | |
| array_xml | |
| end | |
| def __get_plist_orientation_values__ | |
| orientation_string_landscape_left = "UIInterfaceOrientationLandscapeLeft" | |
| orientation_string_landscape_right = "UIInterfaceOrientationLandscapeRight" | |
| orientation_string_portrait = "UIInterfaceOrientationPortrait" | |
| # check ios orientation override and return plist values accordingly | |
| ios_orientation = Cvars["game_metadata.orientation_ios"].value | |
| ios_orientation = Cvars["game_metadata.orientation"].value if ios_orientation.length == 0 | |
| if ios_orientation == "portrait,landscape" | |
| [orientation_string_portrait, orientation_string_landscape_right, orientation_string_landscape_left] | |
| elsif ios_orientation == "landscape,portrait" | |
| [orientation_string_landscape_right, orientation_string_landscape_left, orientation_string_portrait] | |
| elsif ios_orientation == "portrait" | |
| [orientation_string_portrait] | |
| elsif ios_orientation == "landscape" | |
| [orientation_string_landscape_right, orientation_string_landscape_left] | |
| end | |
| end | |
| def development_write_info_plist | |
| log_info "Adding Info.plist." | |
| info_plist_string = <<-XML | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>LSSupportsGameMode</key> | |
| <true/> | |
| <key>BuildMachineOSBuild</key> | |
| <string>20D91</string> | |
| <key>CFBundleDevelopmentRegion</key> | |
| <string>en</string> | |
| <key>CFBundleDisplayName</key> | |
| <string>:app_name</string> | |
| <key>CFBundleExecutable</key> | |
| <string>:app_name</string> | |
| <key>NSAppTransportSecurity</key> | |
| <dict> | |
| <key>NSAllowsArbitraryLoads</key> | |
| <true/> | |
| </dict> <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| </array> | |
| <key>CFBundleIcons</key> | |
| <dict> | |
| <key>CFBundlePrimaryIcon</key> | |
| <dict> | |
| <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| </array> | |
| <key>CFBundleIconName</key> | |
| <string>AppIcon</string> | |
| </dict> | |
| </dict> | |
| <key>CFBundleIcons~ipad</key> | |
| <dict> | |
| <key>CFBundlePrimaryIcon</key> | |
| <dict> | |
| <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| <string>AppIcon76x76</string> | |
| <string>AppIcon83.5x83.5</string> | |
| </array> | |
| <key>CFBundleIconName</key> | |
| <string>AppIcon</string> | |
| </dict> | |
| </dict> | |
| <key>CFBundleIdentifier</key> | |
| <string>:app_id</string> | |
| <key>CFBundleInfoDictionaryVersion</key> | |
| <string>:app_version</string> | |
| <key>CFBundleName</key> | |
| <string>:app_name</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>:app_version</string> | |
| <key>CFBundleSignature</key> | |
| <string>????</string> | |
| <key>CFBundleSupportedPlatforms</key> | |
| <array> | |
| <string>iPhoneOS</string> | |
| </array> | |
| <key>CFBundleVersion</key> | |
| <string>:app_version</string> | |
| <key>DTCompiler</key> | |
| <string>com.apple.compilers.llvm.clang.1_0</string> | |
| <key>DTPlatformBuild</key> | |
| <string>18D46</string> | |
| <key>DTPlatformName</key> | |
| <string>iphoneos</string> | |
| <key>DTPlatformVersion</key> | |
| <string>11.0</string> | |
| <key>DTSDKBuild</key> | |
| <string>18D46</string> | |
| <key>DTSDKName</key> | |
| <string>iphoneos14.4</string> | |
| <key>DTXcode</key> | |
| <string>0124</string> | |
| <key>DTXcodeBuild</key> | |
| <string>12D4e</string> | |
| <key>MinimumOSVersion</key> | |
| <string>11.0</string> | |
| <key>UIAppFonts</key> | |
| <array/> | |
| <key>UIBackgroundModes</key> | |
| <array/> | |
| <key>UIDeviceFamily</key> | |
| <array> | |
| <integer>1</integer> | |
| <integer>2</integer> | |
| </array> | |
| <key>UILaunchStoryboardName</key> | |
| <string>SimpleSplash</string> | |
| <key>UIRequiredDeviceCapabilities</key> | |
| <array> | |
| <string>arm64</string> | |
| </array> | |
| <key>UIRequiresFullScreen</key> | |
| <true/> | |
| <key>UIStatusBarStyle</key> | |
| <string>UIStatusBarStyleDefault</string> | |
| <key>UISupportedInterfaceOrientations</key> | |
| #{__get_plist_orientation_values_xml__} | |
| <key>CFBundleURLTypes</key> | |
| <array> | |
| <dict> | |
| <key>CFBundleURLName</key> | |
| <string>:app_id</string> | |
| <key>CFBundleURLSchemes</key> | |
| <array> | |
| <string>:app_id</string> | |
| </array> | |
| </dict> | |
| </array> | |
| </dict> | |
| </plist> | |
| XML | |
| # <string>UIInterfaceOrientationPortrait</string> | |
| # <string>UIInterfaceOrientationLandscapeRight</string> | |
| info_plist_string.gsub!(":app_name", @app_name) | |
| info_plist_string.gsub!(":app_id", @app_id) | |
| info_plist_string.gsub!(":app_version", @app_version) | |
| $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.strip | |
| $gtk.write_file_root "tmp/ios/Info.txt", info_plist_string.strip | |
| @info_plist_written = true | |
| :success | |
| end | |
| def production_write_info_plist | |
| log_info "Adding Info.plist." | |
| info_plist_string = <<-XML | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>LSSupportsGameMode</key> | |
| <true/> | |
| <key>BuildMachineOSBuild</key> | |
| <string>20D91</string> | |
| <key>CFBundleDevelopmentRegion</key> | |
| <string>en</string> | |
| <key>CFBundleDisplayName</key> | |
| <string>:app_name</string> | |
| <key>CFBundleExecutable</key> | |
| <string>:app_name</string> | |
| <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| </array> | |
| <key>CFBundleIcons</key> | |
| <dict> | |
| <key>CFBundlePrimaryIcon</key> | |
| <dict> | |
| <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| </array> | |
| <key>CFBundleIconName</key> | |
| <string>AppIcon</string> | |
| </dict> | |
| </dict> | |
| <key>CFBundleIcons~ipad</key> | |
| <dict> | |
| <key>CFBundlePrimaryIcon</key> | |
| <dict> | |
| <key>CFBundleIconFiles</key> | |
| <array> | |
| <string>AppIcon60x60</string> | |
| <string>AppIcon76x76</string> | |
| <string>AppIcon83.5x83.5</string> | |
| </array> | |
| <key>CFBundleIconName</key> | |
| <string>AppIcon</string> | |
| </dict> | |
| </dict> | |
| <key>CFBundleIdentifier</key> | |
| <string>:app_id</string> | |
| <key>CFBundleInfoDictionaryVersion</key> | |
| <string>:app_version</string> | |
| <key>CFBundleName</key> | |
| <string>:app_name</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>:app_version</string> | |
| <key>CFBundleSignature</key> | |
| <string>????</string> | |
| <key>CFBundleSupportedPlatforms</key> | |
| <array> | |
| <string>iPhoneOS</string> | |
| </array> | |
| <key>CFBundleVersion</key> | |
| <string>:app_version</string> | |
| <key>DTCompiler</key> | |
| <string>com.apple.compilers.llvm.clang.1_0</string> | |
| <key>DTPlatformBuild</key> | |
| <string>18D46</string> | |
| <key>DTPlatformName</key> | |
| <string>iphoneos</string> | |
| <key>DTPlatformVersion</key> | |
| <string>14.4</string> | |
| <key>DTSDKBuild</key> | |
| <string>18D46</string> | |
| <key>DTSDKName</key> | |
| <string>iphoneos14.4</string> | |
| <key>DTXcode</key> | |
| <string>0124</string> | |
| <key>DTXcodeBuild</key> | |
| <string>12D4e</string> | |
| <key>MinimumOSVersion</key> | |
| <string>11.0</string> | |
| <key>UIAppFonts</key> | |
| <array/> | |
| <key>UIBackgroundModes</key> | |
| <array/> | |
| <key>UIDeviceFamily</key> | |
| <array> | |
| <integer>1</integer> | |
| <integer>2</integer> | |
| </array> | |
| <key>UILaunchStoryboardName</key> | |
| <string>SimpleSplash</string> | |
| <key>UIRequiredDeviceCapabilities</key> | |
| <array> | |
| <string>arm64</string> | |
| </array> | |
| <key>UIRequiresFullScreen</key> | |
| <true/> | |
| <key>UIStatusBarStyle</key> | |
| <string>UIStatusBarStyleDefault</string> | |
| <key>UISupportedInterfaceOrientations</key> | |
| #{__get_plist_orientation_values_xml__} | |
| <key>CFBundleURLTypes</key> | |
| <array> | |
| <dict> | |
| <key>CFBundleURLName</key> | |
| <string>:app_id</string> | |
| <key>CFBundleURLSchemes</key> | |
| <array> | |
| <string>:app_id</string> | |
| </array> | |
| </dict> | |
| </array> | |
| </dict> | |
| </plist> | |
| XML | |
| # <string>UIInterfaceOrientationPortrait</string> | |
| # <string>UIInterfaceOrientationLandscapeRight</string> | |
| info_plist_string.gsub!(":app_name", @app_name) | |
| info_plist_string.gsub!(":app_id", @app_id) | |
| info_plist_string.gsub!(":app_version", @app_version) | |
| $gtk.write_file_root "tmp/ios/#{@app_name}.app/Info.plist", info_plist_string.strip | |
| $gtk.write_file_root "tmp/ios/Info.txt", info_plist_string.strip | |
| @info_plist_written = true | |
| :success | |
| end | |
| def tmp_directory | |
| "#{root_dir}/tmp/ios" | |
| end | |
| def app_path | |
| "#{tmp_directory}/#{@app_name}.app" | |
| end | |
| def game_dir | |
| GTK.get_game_dir | |
| end | |
| def embed_mobileprovision | |
| sh %Q[cp #{@provisioning_profile_path} "#{app_path}/embedded.mobileprovision"] | |
| sh %Q[/usr/bin/plutil -convert binary1 "#{app_path}/Info.plist"] | |
| :success | |
| end | |
| def clear_payload_directory | |
| sh %Q[rm -f "#{@app_name}".ipa] | |
| sh %Q[rm -rf "#{app_path}/app"] | |
| sh %Q[rm -rf "#{app_path}/sounds"] | |
| sh %Q[rm -rf "#{app_path}/sprites"] | |
| sh %Q[rm -rf "#{app_path}/data"] | |
| sh %Q[rm -rf "#{app_path}/fonts"] | |
| sh %Q[rm -rf "#{app_path}/metadata"] | |
| :success | |
| end | |
| def ignored_directories | |
| Cvars["game_metadata.ignore_directories"].value | |
| .split(",") | |
| .reject { |d| d.strip.length == 0 } | |
| end | |
| def root_folder_directories | |
| directories = $gtk.list_files "" | |
| directories.reject { |d| ignored_directories.include? d } | |
| end | |
| def stage_ios_app | |
| log_info "Staging." | |
| sh "mkdir -p #{tmp_directory}" | |
| sh "cp -R #{root_dir}/dragonruby-ios.app/ \"#{tmp_directory}/#{@app_name}.app/\"" | |
| sh "mv \"#{tmp_directory}/#{@app_name}.app/Runtime\" \"#{tmp_directory}/#{@app_name}.app/#{@app_name}\"" | |
| exclude_string = ignored_directories.map do |d| | |
| %Q[--exclude="#{d}"] | |
| end.join(" ") | |
| sh %Q[rsync -a #{exclude_string} "#{game_dir}/." "#{app_path}/"] | |
| :success | |
| end | |
| def stage_sim_app | |
| log_info "Staging." | |
| sh "codesign --remove-signature #{root_dir}/dragonruby-ios-simulator.app/Runtime" | |
| sh "mkdir -p #{tmp_directory}" | |
| sh "cp -R #{root_dir}/dragonruby-ios-simulator.app/ \"#{tmp_directory}/#{@app_name}.app/\"" | |
| sh "mv \"#{tmp_directory}/#{@app_name}.app/Runtime\" \"#{tmp_directory}/#{@app_name}.app/#{@app_name}\"" | |
| exclude_string = ignored_directories.map do |d| | |
| %Q[--exclude="#{d}"] | |
| end.join(" ") | |
| sh %Q[rsync -a #{exclude_string} "#{game_dir}/." "#{app_path}/"] | |
| :success | |
| end | |
| def create_payload | |
| sh %Q[mkdir -p #{tmp_directory}/ipa_root/Payload] | |
| sh %Q[cp -r "#{app_path}" "#{tmp_directory}/ipa_root/Payload"] | |
| sh %Q[chmod -R 755 "#{tmp_directory}/ipa_root/Payload"] | |
| :success | |
| end | |
| def write_server_ip_address | |
| if sim_build? | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| sh %Q[echo localhost] | |
| sh %Q[echo localhost > "#{app_path}/metadata/dragonruby_remote_hotload"] | |
| else | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| sh %Q[echo #{$gtk.ffi_misc.get_local_ip_address.strip}] | |
| sh %Q[echo #{$gtk.ffi_misc.get_local_ip_address.strip} > "#{app_path}/metadata/dragonruby_remote_hotload"] | |
| end | |
| :success | |
| end | |
| def create_dev_payload_directory | |
| embed_mobileprovision | |
| clear_payload_directory | |
| stage_ios_app | |
| # write dev machine's ip address for hotloading | |
| write_server_ip_address if hotload_build? | |
| # production build marker | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| :success | |
| end | |
| def create_test_payload_directory | |
| embed_mobileprovision | |
| clear_payload_directory | |
| stage_ios_app | |
| # write dev machine's ip address for hotloading | |
| write_server_ip_address if hotload_build? | |
| # production build marker | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| sh %Q[touch "#{app_path}/metadata/dragonruby_production_build"] | |
| :success | |
| end | |
| def create_prod_payload_directory | |
| # production builds does not hotload ip address | |
| sh %Q[rm -f "#{game_dir}/app/server_ip_address.txt"] | |
| embed_mobileprovision | |
| stage_ios_app | |
| # production build marker | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| sh %Q[touch "#{app_path}/metadata/dragonruby_production_build"] | |
| :success | |
| end | |
| def create_sim_payload_directory | |
| clear_payload_directory | |
| stage_sim_app | |
| write_server_ip_address | |
| # production build marker | |
| sh %Q[mkdir -p "#{app_path}/metadata/"] | |
| :success | |
| end | |
| def create_ipa | |
| do_zip | |
| sh "cp \"#{tmp_directory}/ipa_root/archive.zip\" \"#{tmp_directory}/#{@app_name}.ipa\"" | |
| :success | |
| end | |
| def do_zip | |
| $gtk.write_file_root "tmp/ios/do_zip.sh", <<-SCRIPT | |
| pushd #{tmp_directory}/ipa_root/ | |
| zip -q -r archive.zip Payload | |
| popd | |
| SCRIPT | |
| :success | |
| sh "sh #{tmp_directory}/do_zip.sh" | |
| end | |
| def sh cmd | |
| log_info cmd.strip | |
| result = IO.popen("#{cmd} 2>&1") do |io| | |
| io.read.strip | |
| end | |
| if result.length > 0 | |
| __puts__ result | |
| log_info result | |
| end | |
| if $? != 0 | |
| raise WizardException.new("* ERROR - sh invocation returned a non-zero exit code.", | |
| cmd, | |
| result, | |
| *caller) | |
| end | |
| result | |
| end | |
| def deploy_to_device | |
| version = `ideviceinstaller --version`.strip.split(" ").last | |
| if version.start_with?("1.1") | |
| sh "ideviceinstaller --uninstall #{@app_id}" if @should_uninstall | |
| sh "ideviceinstaller -i \"#{tmp_directory}/#{@app_name}.ipa\"" | |
| else | |
| sh "ideviceinstaller uninstall #{@app_id}" if @should_uninstall | |
| sh "ideviceinstaller install \"#{tmp_directory}/#{@app_name}.ipa\"" | |
| end | |
| log_info "Check your device!!" | |
| :success | |
| end | |
| def simctl_list_devices | |
| output = sh "xcrun simctl list devices" | |
| # get only installed devices | |
| output = output.split("-- Unavailable").first | |
| devices = {} | |
| current_version_number_string = nil | |
| output.each_line do |l| | |
| if l.start_with? "-- iOS" | |
| current_version_number_string = l.strip.gsub("-- iOS ", "").gsub(" --", "") | |
| else | |
| tokens = l.gsub("(Booted)", "") | |
| .gsub("(Shutdown)", "") | |
| .strip.split(" (") | |
| device_name = tokens.first.strip | |
| device_id = tokens.last.gsub(")", "").strip | |
| device_name_2 = if tokens.length <= 2 | |
| "" | |
| else | |
| tokens[1].gsub(")", "").strip | |
| end | |
| if !device_id.include? "Devices" | |
| devices[device_id] = { | |
| name: device_name, | |
| name_2: device_name_2, | |
| version_string: current_version_number_string, | |
| version_number: current_version_number_string.split(".").map(&:to_i), | |
| id: device_id | |
| } | |
| end | |
| end | |
| end | |
| devices | |
| end | |
| def install_simulator_if_needed | |
| results = sh "xcrun simctl list devices" | |
| results = results.split("== Devices ==").last | |
| iphone_13_pro_max_line = results.split("\n").find { |line| line.include? "iPhone 13 Pro Max" } | |
| if iphone_13_pro_max_line && iphone_13_pro_max_line.include?("unavailable") | |
| iphone_13_pro_max_line = nil | |
| end | |
| if !iphone_13_pro_max_line | |
| puts "* INFO: Installing iPhone 13 Pro Max simulator..." | |
| install_command = "xcrun simctl create \"iPhone 13 Pro Max\" com.apple.CoreSimulator.SimDeviceType.iPhone-13-Pro-Max" | |
| results = sh install_command | |
| if results.include? "Could not find an" | |
| raise WizardException.new( | |
| "* ERROR: Unable to install simulator a default simulator.", | |
| "** Please run the following command in your terminal:", | |
| "", | |
| " xcodebuild -downloadPlatform iOS", | |
| "" | |
| ) | |
| end | |
| end | |
| :success | |
| end | |
| def simctl_list_devices_max_version | |
| devices = simctl_list_devices | |
| max_version_number = devices.map { |k, v| v.version_number }.max | |
| max_version_number_string = max_version_number.join(".") | |
| devices.reject! { |k, v| v.version_string != max_version_number_string } | |
| devices | |
| end | |
| def simctl_iphone_device_id_max_version | |
| devices = simctl_list_devices_max_version | |
| k, v = devices.find { |k, v| v.name.include?("iPhone") && !v.name.include?("SE") } | |
| k | |
| end | |
| def simctl_iphone_device_id_by_name | |
| devices = simctl_list_devices | |
| k, v = devices.find { |k, v| v.name.downcase.include?(@opts[:sim_name].downcase) } | |
| k | |
| end | |
| def deploy_to_sim | |
| device_id = nil | |
| if @opts[:sim_name] | |
| device_id = simctl_iphone_device_id_by_name | |
| if !device_id | |
| $console.set_command "$wizards.ios.start env: :#{@opts[:env]}, sim_name: \"#{@opts[:sim_name]}\"" | |
| raise WizardException.new( | |
| "* Unable to find simulator named '#{@opts[:sim_name]}'.", | |
| "** The name must (at least partially) match the name of an existing simulator.", | |
| "** Open your iOS simulator and check File > Open Simulator to see the options." | |
| ) | |
| end | |
| else | |
| device_id = simctl_iphone_device_id_max_version | |
| end | |
| sh "xcrun simctl list devices | grep -q \"#{device_id}.*Booted\" || xcrun simctl boot #{device_id}" | |
| sh "open -a Simulator" | |
| sh "xcrun simctl uninstall #{device_id} #{@app_id}" | |
| sh "xcrun simctl install #{device_id} \"#{tmp_directory}/#{@app_name}.app\"" | |
| sh "xcrun simctl launch #{device_id} #{@app_id}" | |
| puts "Check your simulator!!\nYou can use cmd+left/right arrow to rotate the device." | |
| :success | |
| end | |
| def print_publish_help | |
| has_transporter = (sh "ls /Applications/Transporter.app").include? "Contents" | |
| if !has_transporter | |
| $gtk.openurl "https://apps.apple.com/us/app/transporter/id1450874784?mt=12" | |
| $console.set_command "$wizards.ios.start env: :#{@opts[:env]}, version: \"#{@opts[:version]}\"" | |
| raise WizardException.new( | |
| "* To upload your app, Download Transporter from the App Store https://apps.apple.com/us/app/transporter/id1450874784?mt=12." | |
| ) | |
| else | |
| sh "mkdir ./tmp/ios/intermediary_artifacts" | |
| sh "mv \"#{tmp_directory}/#{@app_name}.app\" #{tmp_directory}/intermediary_artifacts/" | |
| sh "mv \"#{tmp_directory}/do_zip.sh\" #{tmp_directory}/intermediary_artifacts" | |
| sh "mv \"#{tmp_directory}/Entitlements.plist\" #{tmp_directory}/intermediary_artifacts" | |
| sh "mv \"#{tmp_directory}/ipa_root\" #{tmp_directory}/intermediary_artifacts/" | |
| sh "open /Applications/Transporter.app" | |
| sh "open \"#{tmp_directory}\"" | |
| end | |
| :success | |
| end | |
| def compile_icons | |
| cmd = <<-S | |
| "/Applications/Xcode.app/Contents/Developer/usr/bin/actool" --output-format human-readable-text \\ | |
| --notices --warnings --platform iphoneos \\ | |
| --minimum-deployment-target 10.3 \\ | |
| --target-device iphone \\ | |
| --target-device ipad --app-icon 'AppIcon' \\ | |
| --output-partial-info-plist '#{app_path}/AssetCatalog-Info.plist' \\ | |
| --compress-pngs --compile "#{app_path}" \\ | |
| "#{app_path}/Assets.xcassets" | |
| S | |
| sh cmd | |
| :success | |
| end | |
| def stage_native_libs | |
| sh "cp -r \"#{game_dir}/native/\" \"#{app_path}/native/\"" | |
| sh "CODESIGN_ALLOCATE=\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\" /usr/bin/codesign -f -s \"#{@certificate_name}\" --entitlements #{tmp_directory}/Entitlements.plist \"#{tmp_directory}/#{@app_name}.app/native/ios-device/ext.dylib\"" | |
| end | |
| def set_version version | |
| @app_version = version | |
| start env: @opts[:env], version: version | |
| end | |
| def app_name | |
| @app_name | |
| end | |
| def app_version | |
| log_info "Attempting to retrieve App Version from metadata/ios_metadata.txt." | |
| ios_version_number = (ios_metadata.version || "").strip | |
| if ios_version_number.length == 0 | |
| log_info "Not found. Attempting to retrieve App Version from metadata/game_metadata.txt." | |
| ios_version_number = (game_metadata.version || "").strip | |
| end | |
| ios_version_number | |
| end | |
| def determine_app_version | |
| @app_version = app_version | |
| return :success if @app_version | |
| end | |
| def certificate_name | |
| @certificate_name | |
| end | |
| def display_name | |
| "iOS Wizard" | |
| end | |
| def reset_simulators | |
| sh "killall \"Simulator\" 2> /dev/null" | |
| sh "xcrun simctl delete unavailable" | |
| sh "xcrun simctl shutdown all" | |
| sh "xcrun simctl erase all" | |
| end | |
| def get_steps_to_execute | |
| if @build_type == :sim | |
| steps_sim_build | |
| elsif @build_type == :dev || @build_type == :hotload | |
| steps_dev_build | |
| elsif @build_type == :test | |
| steps_test_build | |
| elsif @build_type == :prod | |
| steps_prod_build | |
| else | |
| [] | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment