./lib/shenzhen/plugins/itunesconnect.rb in shenzhen-0.8.2 vs ./lib/shenzhen/plugins/itunesconnect.rb in shenzhen-0.9.0
- old
+ new
@@ -1,53 +1,80 @@
require 'security'
+require 'pathname'
+require 'fileutils'
+require 'digest/md5'
module Shenzhen::Plugins
module ITunesConnect
ITUNES_CONNECT_SERVER = 'Xcode:itunesconnect.apple.com'
class Client
attr_reader :ipa, :sdk, :params
- def initialize(ipa, sdk, params = [])
+ def initialize(ipa, apple_id, sdk, account, password, params = [])
@ipa = ipa
+ @apple_id = apple_id
@sdk = sdk
+ @account = account
+ @password = password
@params = params
end
- def ensure_itunesconnect!
- case xcrun(:Validation, [:online])
- when /(error)|(fail)/i
- say_error "An error occurred checking the status of the app in iTunes Connect.\nRun with --verbose for more info." and abort
- when /validation was skipped/i
- say_error "Validation was skipped. Double check your credentials and ensure the app in the 'Waiting for Upload' state." and abort
- end
- end
-
def upload_build!
- case xcrun(:Validation, [:online, :upload])
+ size = File.size(@ipa)
+ checksum = Digest::MD5.file(@ipa)
+
+ FileUtils.mkdir_p("Package.itmsp")
+ FileUtils.copy_entry(@ipa, "Package.itmsp/#{@ipa}")
+
+ File.write("Package.itmsp/metadata.xml", metadata(@apple_id, checksum, size))
+
+ case transport
when /(error)|(fail)/i
say_error "An error occurred when trying to upload the build to iTunesConnect.\nRun with --verbose for more info." and abort
end
+
+ FileUtils.rmdir("Package.itmsp")
end
private
- def xcrun(tool, options = [])
- args = ["xcrun", "-sdk #{sdk}", tool] + (options + @params).collect{|o| "-#{o}"} + [ipa, '2>&1']
- command = args.join(' ')
+ def transport
+ xcode = `xcode-select --print-path`.strip
+ tool = Pathname.new(xcode).parent + "Applications/Application Loader.app/Contents/MacOS/itms/bin/iTMSTransporter"
+ tool = tool.to_s.gsub(/ /, '\ ')
+ args = [tool.to_s, "-m upload", "-f Package.itmsp", "-u #{@account}", "-p #{@password}"]
+ command = args.join(' ').strip
+
say "#{command}" if verbose?
- output = `#{command}`
+ output = `#{command} 2> /dev/null`
say output.chomp if verbose?
- return output
+ output
end
def verbose?
@params.collect(&:to_sym).include?(:verbose)
end
+
+ def metadata(apple_id, checksum, size)
+ %{<?xml version="1.0" encoding="UTF-8"?>
+ <package version="software4.7" xmlns="http://apple.com/itunes/importer">
+ <software_assets apple_id="#{apple_id}">
+ <asset type="bundle">
+ <data_file>
+ <file_name>#{@ipa}</file_name>
+ <checksum type="md5">#{checksum}</checksum>
+ <size>#{size}</size>
+ </data_file>
+ </asset>
+ </software_assets>
+ </package>
+ }
+ end
end
end
end
command :'distribute:itunesconnect' do |c|
@@ -58,10 +85,11 @@
c.option '-a', '--account ACCOUNT', "Apple ID used to log into https://itunesconnect.apple.com"
c.option '-p', '--password PASSWORD', "Password for the account unless already stored in the keychain"
c.option '-u', '--upload', "Actually attempt to upload the build to iTunes Connect"
c.option '-w', '--warnings', "Check for warnings when validating the ipa"
c.option '-e', '--errors', "Check for errors when validating the ipa"
+ c.option '-i', '--apple-id STRING', "Apple ID from iTunes Connect"
c.option '--verbose', "Run commands verbosely"
c.option '--sdk SDK', "SDK to use when validating the ipa. Defaults to 'iphoneos'"
c.option '--save-keychain', "Save the provided account in the keychain for future use"
c.action do |args, options|
@@ -71,10 +99,13 @@
say_error "Missing or unspecified .ipa file" and abort unless @file and File.exist?(@file)
determine_itunes_connect_account! unless @account = options.account || ENV['ITUNES_CONNECT_ACCOUNT']
say_error "Missing iTunes Connect account" and abort unless @account
+ apple_id = options.apple_id
+ say_error "Missing Apple ID" and abort unless apple_id
+
@password = options.password || ENV['ITUNES_CONNECT_PASSWORD']
if @password ||= Security::GenericPassword.find(:s => Shenzhen::Plugins::ITunesConnect::ITUNES_CONNECT_SERVER, :a => @account)
say_ok "Found password in keychain for account: #{@account}" if options.verbose
else
determine_itunes_connect_password! unless @password
@@ -86,13 +117,10 @@
parameters = []
parameters << :verbose if options.verbose
parameters << :warnings if options.warnings
parameters << :errors if options.errors
- client = Shenzhen::Plugins::ITunesConnect::Client.new(@file, options.sdk, parameters)
-
- client.ensure_itunesconnect!
- say_warning "Upload not requested, skipping." and abort unless options.upload
+ client = Shenzhen::Plugins::ITunesConnect::Client.new(@file, apple_id, options.sdk, @account, @password, parameters)
client.upload_build!
say_ok "Upload complete. You may want to double check iTunes Connect to make sure it was received correctly."
end