require "fileutils" require "open3" require "shellwords" require "tempfile" default_platform(:ios) BUNDLE_IDENTIFIER = "net.buzzert.QueueCube" DEVELOPMENT_TEAM = "DQQH5H6GBD" PROVISIONING_PROFILE_NAME = "#{BUNDLE_IDENTIFIER} AppStore" APP_ROOT = File.expand_path("..", File.expand_path(__dir__)) IOS_PROJECT_DIR = File.join(APP_ROOT, "ios") XCODE_PROJECT = File.join(IOS_PROJECT_DIR, "QueueCube.xcodeproj") SCHEME = "QueueCube" ARCHIVE_PATH = File.join(IOS_PROJECT_DIR, "build", "#{SCHEME}.xcarchive") EXPORT_PATH = File.join(IOS_PROJECT_DIR, "build", "upload") def shell_command(*parts) parts.flatten.map { |part| part.to_s.shellescape }.join(" ") end def archive_path ARCHIVE_PATH end def export_path EXPORT_PATH end def git_output(*args) stdout, stderr, status = Open3.capture3("git", *args, chdir: APP_ROOT) UI.user_error!("git #{args.join(' ')} failed: #{stderr.strip}") unless status.success? stdout.strip end def app_version tag = git_output("describe", "--tags", "--abbrev=0") version = tag.sub(/\Av/, "") unless version.match?(/\A\d+(?:\.\d+){0,2}\z/) UI.user_error!("Latest git tag #{tag.inspect} is not a valid App Store version. Use a tag like 1.5.2 or v1.5.2.") end version end def build_number git_output("rev-list", "--count", "HEAD") end def upload_export_options <<~PLIST method app-store-connect signingStyle manual teamID #{DEVELOPMENT_TEAM} signingCertificate Apple Distribution provisioningProfiles #{BUNDLE_IDENTIFIER} #{PROVISIONING_PROFILE_NAME} manageAppVersionAndBuildNumber stripSwiftSymbols uploadSymbols PLIST end platform :ios do desc "Build QueueCube for iOS and upload the archive to TestFlight" lane :beta do version = app_version build = build_number UI.message("Using QueueCube version #{version} (build #{build}) from git") FileUtils.rm_rf(archive_path) FileUtils.rm_rf(export_path) Dir.chdir(IOS_PROJECT_DIR) do sh(shell_command( "xcodebuild", "-project", XCODE_PROJECT, "-scheme", SCHEME, "-configuration", "Release", "-destination", "generic/platform=iOS", "-archivePath", archive_path, "-allowProvisioningUpdates", "clean", "archive", "DEVELOPMENT_TEAM=#{DEVELOPMENT_TEAM}", "PRODUCT_BUNDLE_IDENTIFIER=#{BUNDLE_IDENTIFIER}", "MARKETING_VERSION=#{version}", "CURRENT_PROJECT_VERSION=#{build}", "CODE_SIGN_IDENTITY=Apple Distribution" )) end export_options = Tempfile.new(["queuecube-export-options", ".plist"]) export_options.write(upload_export_options) export_options.close FileUtils.rm_rf(export_path) Dir.chdir(IOS_PROJECT_DIR) do sh(shell_command( "xcodebuild", "-exportArchive", "-archivePath", archive_path, "-exportPath", export_path, "-exportOptionsPlist", export_options.path, "-allowProvisioningUpdates" )) end ipa_path = Dir[File.join(export_path, "*.ipa")].first UI.user_error!("No IPA found in #{export_path}") unless ipa_path upload_to_testflight( app_identifier: BUNDLE_IDENTIFIER, ipa: ipa_path, skip_waiting_for_build_processing: true, uses_non_exempt_encryption: false ) ensure export_options&.unlink end end