diff --git a/Gemfile b/Gemfile index 7280bb8..faa75ed 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ gem 'builder' gem 'multi_json' gem 'plist' gem 'rest-client' +gem 'xcpretty' # Documentation gem 'yard' diff --git a/README.md b/README.md index c8189da..bc0095c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,5 @@ # XCoder -## No Longer Maintained - -Unfortuantely, I just don't have the time to maintain Xcoder, and given there are so many other tools that do bits and peices of what xcoder does, it doesnt feel as needed any more. - -Perhaps parts of xcoder (keychain, profile management) could be extracted into stand-along tools - take a more unix-y approach to managing tools. - -If anyone wants to more actively maintain Xcoder, please contact me. - ## Description Taking the pain out of scripting and automating xcode builds. diff --git a/lib/xcode/builder/base_builder.rb b/lib/xcode/builder/base_builder.rb index 4bf75e1..c3912b8 100644 --- a/lib/xcode/builder/base_builder.rb +++ b/lib/xcode/builder/base_builder.rb @@ -26,7 +26,7 @@ def profile= (value) @profile = ProvisioningProfile.new(value) end end - + def cocoapods_installed? system("which pod > /dev/null 2>&1") end @@ -43,7 +43,7 @@ def dependencies if has_dependencies? and cocoapods_installed? print_task :builder, "Fetch depencies", :notice podfile = File.join(File.dirname(@target.project.path), "Podfile") - + print_task :cocoapods, "pod setup", :info with_command('pod setup').execute @@ -57,10 +57,10 @@ def prepare_xcodebuild sdk=@sdk #:yield: Xcode::Shell::Command cmd.log_to_file = true cmd.attach Xcode::Builder::XcodebuildParser.new - + cmd.env["OBJROOT"] = "\"#{objroot}/\"" cmd.env["SYMROOT"] = "\"#{symroot}/\"" - + unless profile.nil? profile.install print_task "builder", "Using profile #{profile.install_path}", :debug @@ -81,8 +81,8 @@ def prepare_xcodebuild sdk=@sdk #:yield: Xcode::Shell::Command yield cmd if block_given? end - end - + end + def with_command command_line cmd = Xcode::Shell::Command.new command_line cmd.output_dir = objroot @@ -124,6 +124,59 @@ def prepare_package_command end end + # Packaging doesn't come with SwiftSupport folder, so we need to copy them over. + def copy_swift_packages + swift_frameworks = Dir["#{app_path}/Frameworks/libswift*"] + + unless swift_frameworks.empty? + Dir.mktmpdir do | tmpdir | + swift_support_path = File.join(tmpdir, "SwiftSupport") + Dir.mkdir(swift_support_path) + + xcode_path = `xcode-select --print-path`.strip + + swift_frameworks.each do | path | + filename = File.basename(path) + toolchain_version = "#{xcode_path}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/#{@sdk}/#{filename}" + + FileUtils.cp(toolchain_version, swift_support_path, :verbose => true) + end + + command = with_command 'zip' do |zip| + zip << "--recurse-paths \"#{ipa_path}\" \"SwiftSupport\"" + end + + #have to change the directory so we can just zip in the SwiftSupport folder + Dir.chdir(tmpdir) do + command.execute + end + end + end + end + + # Credits to https://github.com/drewcrawford/cavejohnson for reverse-engineering the process + def prepare_dsym_itunesconnect + Dir.mktmpdir do | tmpdir | + symbol_path = File.join(tmpdir, "Symbols") + Dir.mkdir(symbol_path) + + xcode_path = `xcode-select --print-path`.strip + + appbinary = File.join(app_path, "#{product_name}") + toolchain_symbol_path = File.join(xcode_path, "/usr/bin/symbols") + + system "#{toolchain_symbol_path} -noTextInSOD -noDaemon -arch all -symbolsPackageDir \"#{symbol_path}\" \"#{appbinary}\"" + + zip_cmd = with_command 'zip' do |zip| + zip << "--recurse-paths \"#{ipa_path}\" \"Symbols\"" + end + + Dir.chdir(tmpdir) do + zip_cmd.execute + end + end + end + def prepare_dsym_command # package dSYM with_command 'zip' do |cmd| @@ -246,6 +299,8 @@ def package options = {}, &block print_task :package, "generating IPA: #{ipa_path}", :info with_keychain do prepare_package_command.execute + copy_swift_packages + prepare_dsym_itunesconnect end print_task :package, "creating dSYM zip: #{dsym_zip_path}", :info @@ -308,7 +363,7 @@ def objroot @objroot ||= build_path end - def symroot + def symroot @symroot ||= File.join(build_path, 'Products') end diff --git a/lib/xcode/configuration.rb b/lib/xcode/configuration.rb index 036256e..3a70dcf 100644 --- a/lib/xcode/configuration.rb +++ b/lib/xcode/configuration.rb @@ -442,6 +442,8 @@ def substitute(value) case match when "$(TARGET_NAME)" @target.name + when "$(SRCROOT)" + else raise "Unknown substitution variable #{match}" end diff --git a/lib/xcode/deploy/hockeyapp.rb b/lib/xcode/deploy/hockeyapp.rb new file mode 100644 index 0000000..5ff95c4 --- /dev/null +++ b/lib/xcode/deploy/hockeyapp.rb @@ -0,0 +1,74 @@ +require 'rest-client' + +module Xcode + module Deploy + class Hockeyapp + attr_accessor :app_id, :hockeyapp_token, :status, :notify, :proxy, :notes, :notes_type, :builder, :tags, :teams, :users + @@defaults = {} + + def self.defaults(defaults={}) + @@defaults = defaults + end + + def initialize(builder, options={}) + @builder = builder + @app_id = options[:app_id]||@@defaults[:app_id] + @hockeyapp_token = options[:hockeyapp_token]||@@defaults[:hockeyapp_token] + @status = options[:status] + @notify = options[:notify] + @notes = options[:notes] + @notes_type = options[:notes_type] + @tags = options[:tags]||[] + @teams = options[:teams]||[] + @users = options[:users]||[] + @proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] + end + + def deploy + puts "Uploading to HockeyApp..." + + # RestClient.proxy = @proxy || ENV['http_proxy'] || ENV['HTTP_PROXY'] + # RestClient.log = '/tmp/restclient.log' + # + # response = RestClient.post('http://testflightapp.com/api/builds.json', + # :file => File.new(builder.ipa_path), + # :dsym => File.new(builder.dsym_zip_path), + # :api_token => @api_token, + # :team_token => @team_token, + # :notes => @notes, + # :notify => @notify ? 'True' : 'False', + # :distribution_lists => @lists.join(',') + # ) + # + # json = JSON.parse(response) + # puts " + Done, got: #{json.inspect}" + # json + + + + cmd = Xcode::Shell::Command.new 'curl' + cmd << "--proxy #{@proxy}" unless @proxy.nil? or @proxy=='' + cmd << "-X POST https://rink.hockeyapp.net/api/2/apps/#{@app_id}/app_versions/upload" + cmd << "-F ipa=@\"#{@builder.ipa_path}\"" + cmd << "-F dsym=@\"#{@builder.dsym_zip_path}\"" unless @builder.dsym_zip_path.nil? + cmd << "-F notes=\"#{@notes}\"" unless @notes.nil? + cmd << "-F notify=\"#{@notify}\"" unless @notify.nil? + cmd << "-F status=\"#{@status}\"" unless @status.nil? + cmd << "-F notes_type=\"#{@notes_type}\"" unless @notes_type.nil? + cmd << "-F tags='#{@tags.join(',')}'" unless @tags.count==0 + cmd << "-F teams='#{@teams.join(',')}'" unless @teams.count==0 + cmd << "-F users='#{@users.join(',')}'" unless @users.count==0 + cmd << "-H \"X-HockeyAppToken: #{@hockeyapp_token}\"" + + response = cmd.execute + + json = MultiJson.load(response.join('')) + puts " + Done, got: #{json.inspect}" + + yield(json) if block_given? + + json + end + end + end +end diff --git a/lib/xcode/version.rb b/lib/xcode/version.rb index f4766ec..fc841e2 100644 --- a/lib/xcode/version.rb +++ b/lib/xcode/version.rb @@ -1,3 +1,3 @@ module Xcode - VERSION = "0.1.19" + VERSION = "0.1.24" end diff --git a/lib/xcoder.rb b/lib/xcoder.rb index 97d90da..c80ad9b 100644 --- a/lib/xcoder.rb +++ b/lib/xcoder.rb @@ -10,6 +10,7 @@ require 'xcode/workspace' require 'xcode/platform' require 'multi_json' +require 'xcpretty' module Xcode diff --git a/xcoder.iml b/xcoder.iml new file mode 100644 index 0000000..6f25e7d --- /dev/null +++ b/xcoder.iml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file