From cbda166c3a621aed3763d857534f6d0bfbb57276 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 00:46:23 +0900 Subject: [PATCH 01/45] ios build --- deploygate.gemspec | 3 ++ lib/deploygate.rb | 5 ++++ lib/deploygate/build/ios.rb | 31 +++++++++++++++++++++ lib/deploygate/commands/deploy.rb | 9 +++++- lib/deploygate/commands/deploy/build.rb | 37 +++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 lib/deploygate/build/ios.rb create mode 100644 lib/deploygate/commands/deploy/build.rb diff --git a/deploygate.gemspec b/deploygate.gemspec index 3ee3f6f..669f6dd 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -29,6 +29,9 @@ POST_INSTALL_MESSAGE spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' + # ios build + spec.add_dependency 'gym', '~> 1.0.0' + spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "rspec", "~> 3.3.0" diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 21107b9..88b4548 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -5,6 +5,9 @@ require "rbconfig" require "color_echo" +# ios build +require "gym" + module DeployGate end @@ -16,9 +19,11 @@ module DeployGate require "deploygate/commands/logout" require "deploygate/commands/deploy" require "deploygate/commands/deploy/push" +require "deploygate/commands/deploy/build" require "deploygate/config" require "deploygate/session" require "deploygate/deploy" +require "deploygate/build/ios" require "deploygate/message/error" require "deploygate/message/success" require "deploygate/version" diff --git a/lib/deploygate/build/ios.rb b/lib/deploygate/build/ios.rb new file mode 100644 index 0000000..b15c4b7 --- /dev/null +++ b/lib/deploygate/build/ios.rb @@ -0,0 +1,31 @@ +module DeployGate + module Build + class Ios + AD_HOC = 'ad-hoc' + ENTERPRISE = 'enterprise' + WORK_DIR_EXTNAMES = ['.xcworkspace', '.xcodeproj'] + + class NotWorkDirExistError < StandardError + end + + attr_reader :work_path + + def initialize(work_path) + @work_path = work_path + raise NotWorkDirExistError, 'Not work dir exist' unless File.exist?(@work_path) + end + + def build(export_method = AD_HOC) + values = { + :export_method => export_method, + :workspace => @work_path + } + v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) + absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) + absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip") # TODO: upload to deploygate + + absolute_ipa_path + end + end + end +end diff --git a/lib/deploygate/commands/deploy.rb b/lib/deploygate/commands/deploy.rb index 84f0f61..875a5ac 100644 --- a/lib/deploygate/commands/deploy.rb +++ b/lib/deploygate/commands/deploy.rb @@ -7,7 +7,14 @@ class << self # @param [Commander::Command::Options] options def run(args, options) # push or build(android/ios) - Push.upload(args, options) + + work_file_path = args.first + if File.directory?(work_file_path) + Build.run(args, options) + else + # file upload + Push.upload(args, options) + end end end end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb new file mode 100644 index 0000000..41e6e20 --- /dev/null +++ b/lib/deploygate/commands/deploy/build.rb @@ -0,0 +1,37 @@ +module DeployGate + module Commands + module Deploy + class Build + class << self + def run(args, options) + # android/ios build + if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.include?(File.extname(args.first)) + ios(args, options) + end + end + + def ios(args, options) + ios = DeployGate::Build::Ios.new(args.first) + + puts 'Select Export method:' + puts '1. ad-hoc' + puts '2. Enterprise' + print '? ' + input = STDIN.gets.chop + + method = nil + case input + when '1' + method = DeployGate::Build::Ios::AD_HOC + when '2' + method = DeployGate::Build::Ios::ENTERPRISE + end + + ipa_path = ios.build(method) + Push.upload([ipa_path], options) + end + end + end + end + end +end From 88948764aa1db1c3d0ac0c73b3e0d81c8c7e3682 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 01:11:07 +0900 Subject: [PATCH 02/45] find work dir --- deploygate.gemspec | 1 + lib/deploygate.rb | 1 + lib/deploygate/build/ios.rb | 1 + lib/deploygate/commands/deploy.rb | 1 + lib/deploygate/commands/deploy/build.rb | 17 ++++++++++++++++- 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/deploygate.gemspec b/deploygate.gemspec index 669f6dd..6dcb9db 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -28,6 +28,7 @@ POST_INSTALL_MESSAGE spec.add_dependency 'httpclient', '~> 2.2.5' spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' + spec.add_dependency 'file-find', '~> 0.3.8' # ios build spec.add_dependency 'gym', '~> 1.0.0' diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 88b4548..c873e22 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -4,6 +4,7 @@ require "io/console" require "rbconfig" require "color_echo" +require "file/find" # ios build require "gym" diff --git a/lib/deploygate/build/ios.rb b/lib/deploygate/build/ios.rb index b15c4b7..34e6d22 100644 --- a/lib/deploygate/build/ios.rb +++ b/lib/deploygate/build/ios.rb @@ -4,6 +4,7 @@ class Ios AD_HOC = 'ad-hoc' ENTERPRISE = 'enterprise' WORK_DIR_EXTNAMES = ['.xcworkspace', '.xcodeproj'] + EX_WORK_NAMES = ['Pods.xcodeproj', 'project.xcworkspace'] class NotWorkDirExistError < StandardError end diff --git a/lib/deploygate/commands/deploy.rb b/lib/deploygate/commands/deploy.rb index 875a5ac..e8878c0 100644 --- a/lib/deploygate/commands/deploy.rb +++ b/lib/deploygate/commands/deploy.rb @@ -7,6 +7,7 @@ class << self # @param [Commander::Command::Options] options def run(args, options) # push or build(android/ios) + args.push(Dir.pwd) if args.empty? work_file_path = args.first if File.directory?(work_file_path) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 41e6e20..99481f7 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -5,8 +5,23 @@ class Build class << self def run(args, options) # android/ios build - if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.include?(File.extname(args.first)) + work_dir = args.first + + if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.include?(File.extname(work_dir)) ios(args, options) + else + projects = [] + DeployGate::Build::Ios::WORK_DIR_EXTNAMES.each do |pattern| + rule = File::Find.new(:pattern => "*#{pattern}", :path => [work_dir]) + rule.find {|f| projects.push(f) unless DeployGate::Build::Ios::EX_WORK_NAMES.include?(File.basename(f))} + end + return if projects.empty? + + select_project = projects.first + projects.each do |project| + select_project = project if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.first == File.extname(project) + end + ios([select_project], options) end end From a5f3510fc6e7bbd39d377b7f6c3d3d6ff220af1d Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 13:54:44 +0900 Subject: [PATCH 03/45] add build --- lib/deploygate.rb | 1 + lib/deploygate/build.rb | 14 ++++++++++++++ lib/deploygate/build/ios.rb | 23 +++++++++++++++++++++++ lib/deploygate/commands/deploy/build.rb | 23 +++++++++-------------- 4 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 lib/deploygate/build.rb diff --git a/lib/deploygate.rb b/lib/deploygate.rb index c873e22..ae0caca 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -24,6 +24,7 @@ module DeployGate require "deploygate/config" require "deploygate/session" require "deploygate/deploy" +require "deploygate/build" require "deploygate/build/ios" require "deploygate/message/error" require "deploygate/message/success" diff --git a/lib/deploygate/build.rb b/lib/deploygate/build.rb new file mode 100644 index 0000000..cd0086a --- /dev/null +++ b/lib/deploygate/build.rb @@ -0,0 +1,14 @@ +module DeployGate + class Build + class << self + def ios?(path) + workspaces = DeployGate::Build::Ios.find_workspaces(path) + DeployGate::Build::Ios.workspace?(path) || !workspaces.empty? + end + + def android?(path) + false # TODO: support android build + end + end + end +end diff --git a/lib/deploygate/build/ios.rb b/lib/deploygate/build/ios.rb index 34e6d22..dd84c1f 100644 --- a/lib/deploygate/build/ios.rb +++ b/lib/deploygate/build/ios.rb @@ -27,6 +27,29 @@ def build(export_method = AD_HOC) absolute_ipa_path end + + def self.workspace?(path) + WORK_DIR_EXTNAMES.include?(File.basename(path)) + end + + def self.find_workspaces(path) + projects = [] + WORK_DIR_EXTNAMES.each do |pattern| + rule = File::Find.new(:pattern => "*#{pattern}", :path => [path]) + rule.find {|f| projects.push(f) unless EX_WORK_NAMES.include?(File.basename(f))} + end + + projects + end + + def self.select_workspace(workspaces) + select = workspaces.empty? ? nil : workspaces.first + workspaces.each do |workspace| + select = workspace if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.first == File.extname(workspace) + end + + select + end end end end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 99481f7..cbbd632 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -7,21 +7,16 @@ def run(args, options) # android/ios build work_dir = args.first - if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.include?(File.extname(work_dir)) - ios(args, options) - else - projects = [] - DeployGate::Build::Ios::WORK_DIR_EXTNAMES.each do |pattern| - rule = File::Find.new(:pattern => "*#{pattern}", :path => [work_dir]) - rule.find {|f| projects.push(f) unless DeployGate::Build::Ios::EX_WORK_NAMES.include?(File.basename(f))} + if DeployGate::Build.ios?(work_dir) + if DeployGate::Build::Ios.workspace?(work_dir) + ios(args, options) + else + workspaces = DeployGate::Build::Ios.find_workspaces(work_dir) + workspace = DeployGate::Build::Ios.select_workspace(workspaces) + ios([workspace], options) end - return if projects.empty? - - select_project = projects.first - projects.each do |project| - select_project = project if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.first == File.extname(project) - end - ios([select_project], options) + elsif DeployGate::Build.android?(work_dir) + # TODO: support android build end end From cde7ece42b09bb16aff5dfc79583549d557976ff Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 13:58:21 +0900 Subject: [PATCH 04/45] add YARD comment --- lib/deploygate/build.rb | 5 +++++ lib/deploygate/build/ios.rb | 10 ++++++++++ lib/deploygate/commands/deploy/build.rb | 7 +++++++ 3 files changed, 22 insertions(+) diff --git a/lib/deploygate/build.rb b/lib/deploygate/build.rb index cd0086a..faa5f58 100644 --- a/lib/deploygate/build.rb +++ b/lib/deploygate/build.rb @@ -1,11 +1,16 @@ module DeployGate class Build class << self + + # @param [String] path + # @return [Boolean] def ios?(path) workspaces = DeployGate::Build::Ios.find_workspaces(path) DeployGate::Build::Ios.workspace?(path) || !workspaces.empty? end + # @param [String] path + # @return [Boolean] def android?(path) false # TODO: support android build end diff --git a/lib/deploygate/build/ios.rb b/lib/deploygate/build/ios.rb index dd84c1f..ad78cf2 100644 --- a/lib/deploygate/build/ios.rb +++ b/lib/deploygate/build/ios.rb @@ -11,11 +11,15 @@ class NotWorkDirExistError < StandardError attr_reader :work_path + # @param [String] work_path + # @return [DeployGate::Build::Ios] def initialize(work_path) @work_path = work_path raise NotWorkDirExistError, 'Not work dir exist' unless File.exist?(@work_path) end + # @param [String] export_method + # @return [String] def build(export_method = AD_HOC) values = { :export_method => export_method, @@ -28,10 +32,14 @@ def build(export_method = AD_HOC) absolute_ipa_path end + # @param [String] path + # @return [Boolean] def self.workspace?(path) WORK_DIR_EXTNAMES.include?(File.basename(path)) end + # @param [String] path + # @return [Array] def self.find_workspaces(path) projects = [] WORK_DIR_EXTNAMES.each do |pattern| @@ -42,6 +50,8 @@ def self.find_workspaces(path) projects end + # @param [Array] workspaces + # @return [String] def self.select_workspace(workspaces) select = workspaces.empty? ? nil : workspaces.first workspaces.each do |workspace| diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index cbbd632..462c602 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -3,6 +3,10 @@ module Commands module Deploy class Build class << self + + # @param [Array] args + # @param [Hash] options + # @return [void] def run(args, options) # android/ios build work_dir = args.first @@ -20,6 +24,9 @@ def run(args, options) end end + # @param [Array] args + # @param [Hash] options + # @return [void] def ios(args, options) ios = DeployGate::Build::Ios.new(args.first) From 3fa43b89e878acada91a123575e7c55b04e12861 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 14:04:58 +0900 Subject: [PATCH 05/45] s/build/builds/ --- lib/deploygate.rb | 2 +- lib/deploygate/{build => builds}/ios.rb | 4 ++-- lib/deploygate/commands/deploy/build.rb | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) rename lib/deploygate/{build => builds}/ios.rb (97%) diff --git a/lib/deploygate.rb b/lib/deploygate.rb index ae0caca..99f42f6 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -25,7 +25,7 @@ module DeployGate require "deploygate/session" require "deploygate/deploy" require "deploygate/build" -require "deploygate/build/ios" +require "deploygate/builds/ios" require "deploygate/message/error" require "deploygate/message/success" require "deploygate/version" diff --git a/lib/deploygate/build/ios.rb b/lib/deploygate/builds/ios.rb similarity index 97% rename from lib/deploygate/build/ios.rb rename to lib/deploygate/builds/ios.rb index ad78cf2..9b5ec77 100644 --- a/lib/deploygate/build/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -1,5 +1,5 @@ module DeployGate - module Build + module Builds class Ios AD_HOC = 'ad-hoc' ENTERPRISE = 'enterprise' @@ -12,7 +12,7 @@ class NotWorkDirExistError < StandardError attr_reader :work_path # @param [String] work_path - # @return [DeployGate::Build::Ios] + # @return [DeployGate::Builds::Ios] def initialize(work_path) @work_path = work_path raise NotWorkDirExistError, 'Not work dir exist' unless File.exist?(@work_path) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 462c602..f2d0e96 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -12,11 +12,11 @@ def run(args, options) work_dir = args.first if DeployGate::Build.ios?(work_dir) - if DeployGate::Build::Ios.workspace?(work_dir) + if DeployGate::Builds::Ios.workspace?(work_dir) ios(args, options) else - workspaces = DeployGate::Build::Ios.find_workspaces(work_dir) - workspace = DeployGate::Build::Ios.select_workspace(workspaces) + workspaces = DeployGate::Builds::Ios.find_workspaces(work_dir) + workspace = DeployGate::Builds::Ios.select_workspace(workspaces) ios([workspace], options) end elsif DeployGate::Build.android?(work_dir) @@ -28,7 +28,7 @@ def run(args, options) # @param [Hash] options # @return [void] def ios(args, options) - ios = DeployGate::Build::Ios.new(args.first) + ios = DeployGate::Builds::Ios.new(args.first) puts 'Select Export method:' puts '1. ad-hoc' @@ -39,9 +39,9 @@ def ios(args, options) method = nil case input when '1' - method = DeployGate::Build::Ios::AD_HOC + method = DeployGate::Builds::Ios::AD_HOC when '2' - method = DeployGate::Build::Ios::ENTERPRISE + method = DeployGate::Builds::Ios::ENTERPRISE end ipa_path = ios.build(method) From 80ed53fc43a18adad0f51fe077317620aa16eae4 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 14:11:15 +0900 Subject: [PATCH 06/45] add DeployGate::Build spec --- lib/deploygate/build.rb | 4 ++-- spec/deploygate/build_spec.rb | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 spec/deploygate/build_spec.rb diff --git a/lib/deploygate/build.rb b/lib/deploygate/build.rb index faa5f58..d8dff6c 100644 --- a/lib/deploygate/build.rb +++ b/lib/deploygate/build.rb @@ -5,8 +5,8 @@ class << self # @param [String] path # @return [Boolean] def ios?(path) - workspaces = DeployGate::Build::Ios.find_workspaces(path) - DeployGate::Build::Ios.workspace?(path) || !workspaces.empty? + workspaces = DeployGate::Builds::Ios.find_workspaces(path) + DeployGate::Builds::Ios.workspace?(path) || !workspaces.empty? end # @param [String] path diff --git a/spec/deploygate/build_spec.rb b/spec/deploygate/build_spec.rb new file mode 100644 index 0000000..8af802c --- /dev/null +++ b/spec/deploygate/build_spec.rb @@ -0,0 +1,34 @@ +describe DeployGate::Build do + describe "#ios?" do + it "when select workspace" do + allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return([]) + allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(true) + + result = DeployGate::Build.ios?('path') + expect(result).to be_truthy + end + + it "when workspaces" do + allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return(['path']) + allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false) + + result = DeployGate::Build.ios?('path') + expect(result).to be_truthy + end + + it "not ios" do + allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return([]) + allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false) + + result = DeployGate::Build.ios?('path') + expect(result).to be_falsey + end + end + + describe "#android?" do + it "android not support" do + result = DeployGate::Build.android?('path') + expect(result).to be_falsey + end + end +end From 3f63321e7582ff6dddff3b0d20c1924c22b5f95a Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 14:41:35 +0900 Subject: [PATCH 07/45] add DeployGate::Builds::Ios spec --- lib/deploygate/builds/ios.rb | 7 ++- spec/deploygate/builds/ios_spec.rb | 69 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 spec/deploygate/builds/ios_spec.rb diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 9b5ec77..4e43caa 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -3,11 +3,14 @@ module Builds class Ios AD_HOC = 'ad-hoc' ENTERPRISE = 'enterprise' + SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE] WORK_DIR_EXTNAMES = ['.xcworkspace', '.xcodeproj'] EX_WORK_NAMES = ['Pods.xcodeproj', 'project.xcworkspace'] class NotWorkDirExistError < StandardError end + class NotSupportExportMethodError < StandardError + end attr_reader :work_path @@ -21,6 +24,8 @@ def initialize(work_path) # @param [String] export_method # @return [String] def build(export_method = AD_HOC) + raise NotSupportExportMethodError, 'Not support export' unless SUPPORT_EXPORT_METHOD.include?(export_method) + values = { :export_method => export_method, :workspace => @work_path @@ -55,7 +60,7 @@ def self.find_workspaces(path) def self.select_workspace(workspaces) select = workspaces.empty? ? nil : workspaces.first workspaces.each do |workspace| - select = workspace if DeployGate::Build::Ios::WORK_DIR_EXTNAMES.first == File.extname(workspace) + select = workspace if DeployGate::Builds::Ios::WORK_DIR_EXTNAMES.first == File.extname(workspace) end select diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb new file mode 100644 index 0000000..9bce4a1 --- /dev/null +++ b/spec/deploygate/builds/ios_spec.rb @@ -0,0 +1,69 @@ +describe DeployGate::Builds::Ios do + describe "#initialize" do + it "raise not work dir" do + allow(File).to receive(:exist?).and_return(false) + + expect { + DeployGate::Builds::Ios.new('path') + }.to raise_error DeployGate::Builds::Ios::NotWorkDirExistError + end + end + + describe "#build" do + it "should call Gym Manager" do + call_gym_manager = false + allow(FastlaneCore::Configuration).to receive(:create) {} + allow_any_instance_of(Gym::Manager).to receive(:work) { call_gym_manager = true } + allow(File).to receive(:exist?).and_return(true) + allow(File).to receive(:expand_path).and_return('path') + + DeployGate::Builds::Ios.new('path').build + expect(call_gym_manager).to be_truthy + end + + it "raise not support export" do + allow(FastlaneCore::Configuration).to receive(:create) {} + allow_any_instance_of(Gym::Manager).to receive(:work) {} + allow(File).to receive(:exist?).and_return(true) + allow(File).to receive(:expand_path).and_return('path') + + expect { + DeployGate::Builds::Ios.new('path').build('not support export method') + }.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError + end + end + + describe "#workspace?" do + it "pod workspace" do + allow(File).to receive(:basename).and_return('.xcworkspace') + + result = DeployGate::Builds::Ios.workspace?('path') + expect(result).to be_truthy + end + + it "default workspace" do + allow(File).to receive(:basename).and_return('.xcodeproj') + + result = DeployGate::Builds::Ios.workspace?('path') + expect(result).to be_truthy + end + end + + describe "#find_workspaces" do + # TODO: add test + end + + describe "#select_workspace" do + it "should select pods workspace" do + select_workspace = 'test.xcworkspace' + workspeces = ['test.xcodeproj', select_workspace] + expect(DeployGate::Builds::Ios.select_workspace(workspeces)).to eq select_workspace + end + + it "default project" do + select_workspace = 'test.xcodeproj' + workspeces = [select_workspace] + expect(DeployGate::Builds::Ios.select_workspace(workspeces)).to eq select_workspace + end + end +end From d2df0e2318d37c6cc4dac117ba0b33d2b67d2150 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 14:47:05 +0900 Subject: [PATCH 08/45] deploy command must login --- lib/deploygate/commands/deploy.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/deploygate/commands/deploy.rb b/lib/deploygate/commands/deploy.rb index e8878c0..ba2f798 100644 --- a/lib/deploygate/commands/deploy.rb +++ b/lib/deploygate/commands/deploy.rb @@ -6,6 +6,8 @@ class << self # @param [Array] args # @param [Commander::Command::Options] options def run(args, options) + Init.login unless DeployGate::Session.new.login? + # push or build(android/ios) args.push(Dir.pwd) if args.empty? From 577064f4d99f3ba8dd5b9a4e5378115f7fcc9d80 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 16:50:51 +0900 Subject: [PATCH 09/45] bug fix --- lib/deploygate/builds/ios.rb | 2 +- spec/deploygate/builds/ios_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 4e43caa..bc6cd60 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -40,7 +40,7 @@ def build(export_method = AD_HOC) # @param [String] path # @return [Boolean] def self.workspace?(path) - WORK_DIR_EXTNAMES.include?(File.basename(path)) + WORK_DIR_EXTNAMES.include?(File.extname(path)) end # @param [String] path diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb index 9bce4a1..8553a6f 100644 --- a/spec/deploygate/builds/ios_spec.rb +++ b/spec/deploygate/builds/ios_spec.rb @@ -35,14 +35,14 @@ describe "#workspace?" do it "pod workspace" do - allow(File).to receive(:basename).and_return('.xcworkspace') + allow(File).to receive(:extname).and_return('.xcworkspace') result = DeployGate::Builds::Ios.workspace?('path') expect(result).to be_truthy end it "default workspace" do - allow(File).to receive(:basename).and_return('.xcodeproj') + allow(File).to receive(:extname).and_return('.xcodeproj') result = DeployGate::Builds::Ios.workspace?('path') expect(result).to be_truthy From 3de3b908afda98098709c3c1746f70a35f7bd5e2 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 18:05:45 +0900 Subject: [PATCH 10/45] not select scheme --- lib/deploygate/build.rb | 2 +- lib/deploygate/builds/ios.rb | 79 ++++++++++++++++------- lib/deploygate/commands/deploy/build.rb | 18 ++---- spec/deploygate/builds/ios_spec.rb | 83 +++++++++++++++++++------ 4 files changed, 127 insertions(+), 55 deletions(-) diff --git a/lib/deploygate/build.rb b/lib/deploygate/build.rb index d8dff6c..c28ad3f 100644 --- a/lib/deploygate/build.rb +++ b/lib/deploygate/build.rb @@ -6,7 +6,7 @@ class << self # @return [Boolean] def ios?(path) workspaces = DeployGate::Builds::Ios.find_workspaces(path) - DeployGate::Builds::Ios.workspace?(path) || !workspaces.empty? + DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || !workspaces.empty? end # @param [String] path diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index bc6cd60..923fa9f 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -4,31 +4,29 @@ class Ios AD_HOC = 'ad-hoc' ENTERPRISE = 'enterprise' SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE] - WORK_DIR_EXTNAMES = ['.xcworkspace', '.xcodeproj'] - EX_WORK_NAMES = ['Pods.xcodeproj', 'project.xcworkspace'] + BASE_WORK_DIR_NAME = 'project.xcworkspace' + WORK_DIR_EXTNAME = '.xcworkspace' + PROJECT_DIR_EXTNAME = '.xcodeproj' - class NotWorkDirExistError < StandardError - end class NotSupportExportMethodError < StandardError end - attr_reader :work_path - - # @param [String] work_path - # @return [DeployGate::Builds::Ios] - def initialize(work_path) - @work_path = work_path - raise NotWorkDirExistError, 'Not work dir exist' unless File.exist?(@work_path) - end - + # @param [Array] workspaces # @param [String] export_method # @return [String] - def build(export_method = AD_HOC) + def build(workspaces, export_method = AD_HOC) raise NotSupportExportMethodError, 'Not support export' unless SUPPORT_EXPORT_METHOD.include?(export_method) + scheme_workspace = Ios.scheme_workspace(workspaces) + build_workspace = Ios.build_workspace(workspaces) + config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => scheme_workspace}) + project = FastlaneCore::Project.new(config) + schemes = project.schemes + values = { :export_method => export_method, - :workspace => @work_path + :workspace => build_workspace, + :scheme => schemes.count == 1 ? schemes.first : nil } v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) @@ -40,27 +38,62 @@ def build(export_method = AD_HOC) # @param [String] path # @return [Boolean] def self.workspace?(path) - WORK_DIR_EXTNAMES.include?(File.extname(path)) + WORK_DIR_EXTNAME == File.extname(path) + end + + # @param [String] path + # @return [Boolean] + def self.project?(path) + PROJECT_DIR_EXTNAME == File.extname(path) end # @param [String] path # @return [Array] def self.find_workspaces(path) projects = [] - WORK_DIR_EXTNAMES.each do |pattern| - rule = File::Find.new(:pattern => "*#{pattern}", :path => [path]) - rule.find {|f| projects.push(f) unless EX_WORK_NAMES.include?(File.basename(f))} - end + rule = File::Find.new(:pattern => "*#{WORK_DIR_EXTNAME}", :path => [path]) + rule.find {|f| projects.push(f)} projects end + # @param [String] path + # @return [String] + def self.project_root_path(path) + result = path + if workspace?(path) || project?(path) + result = project_root_path(File.dirname(path)) + end + result + end + # @param [Array] workspaces # @return [String] - def self.select_workspace(workspaces) - select = workspaces.empty? ? nil : workspaces.first + def self.scheme_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil + workspaces.each do |workspace| + if BASE_WORK_DIR_NAME == File.basename(workspace) + select = workspace + end + end + + select + end + + # @param [Array] workspaces + # @return [String] + def self.build_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil workspaces.each do |workspace| - select = workspace if DeployGate::Builds::Ios::WORK_DIR_EXTNAMES.first == File.extname(workspace) + if BASE_WORK_DIR_NAME != File.basename(workspace) + select = workspace + end end select diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index f2d0e96..fad0678 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -12,24 +12,18 @@ def run(args, options) work_dir = args.first if DeployGate::Build.ios?(work_dir) - if DeployGate::Builds::Ios.workspace?(work_dir) - ios(args, options) - else - workspaces = DeployGate::Builds::Ios.find_workspaces(work_dir) - workspace = DeployGate::Builds::Ios.select_workspace(workspaces) - ios([workspace], options) - end + root_path = DeployGate::Builds::Ios.project_root_path(work_dir) + workspaces = DeployGate::Builds::Ios.find_workspaces(root_path) + ios(workspaces, options) elsif DeployGate::Build.android?(work_dir) # TODO: support android build end end - # @param [Array] args + # @param [Array] workspaces # @param [Hash] options # @return [void] - def ios(args, options) - ios = DeployGate::Builds::Ios.new(args.first) - + def ios(workspaces, options) puts 'Select Export method:' puts '1. ad-hoc' puts '2. Enterprise' @@ -44,7 +38,7 @@ def ios(args, options) method = DeployGate::Builds::Ios::ENTERPRISE end - ipa_path = ios.build(method) + ipa_path = DeployGate::Builds::Ios.new.build(workspaces, method) Push.upload([ipa_path], options) end end diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb index 8553a6f..9ba3e4c 100644 --- a/spec/deploygate/builds/ios_spec.rb +++ b/spec/deploygate/builds/ios_spec.rb @@ -1,11 +1,9 @@ describe DeployGate::Builds::Ios do - describe "#initialize" do - it "raise not work dir" do - allow(File).to receive(:exist?).and_return(false) - - expect { - DeployGate::Builds::Ios.new('path') - }.to raise_error DeployGate::Builds::Ios::NotWorkDirExistError + before do + class ProjectMock + def schemes + [] + end end end @@ -16,8 +14,9 @@ allow_any_instance_of(Gym::Manager).to receive(:work) { call_gym_manager = true } allow(File).to receive(:exist?).and_return(true) allow(File).to receive(:expand_path).and_return('path') + allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) - DeployGate::Builds::Ios.new('path').build + DeployGate::Builds::Ios.new.build([]) expect(call_gym_manager).to be_truthy end @@ -26,9 +25,10 @@ allow_any_instance_of(Gym::Manager).to receive(:work) {} allow(File).to receive(:exist?).and_return(true) allow(File).to receive(:expand_path).and_return('path') + allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) expect { - DeployGate::Builds::Ios.new('path').build('not support export method') + DeployGate::Builds::Ios.new.build([], 'not support export method') }.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError end end @@ -41,10 +41,26 @@ expect(result).to be_truthy end - it "default workspace" do + it "xcode project" do allow(File).to receive(:extname).and_return('.xcodeproj') result = DeployGate::Builds::Ios.workspace?('path') + expect(result).to be_falsey + end + end + + describe "#project?" do + it "pod workspace" do + allow(File).to receive(:extname).and_return('.xcworkspace') + + result = DeployGate::Builds::Ios.project?('path') + expect(result).to be_falsey + end + + it "xcode project" do + allow(File).to receive(:extname).and_return('.xcodeproj') + + result = DeployGate::Builds::Ios.project?('path') expect(result).to be_truthy end end @@ -53,17 +69,46 @@ # TODO: add test end - describe "#select_workspace" do - it "should select pods workspace" do - select_workspace = 'test.xcworkspace' - workspeces = ['test.xcodeproj', select_workspace] - expect(DeployGate::Builds::Ios.select_workspace(workspeces)).to eq select_workspace + describe "#project_root_path" do + let(:root_path) {'test'} + it "when test/test.xcodeproj/project.xcworkspace" do + expect(DeployGate::Builds::Ios.project_root_path('test/test.xcodeproj/project.xcworkspace')).to eq root_path + end + + it "when test/test.xcodeproj" do + expect(DeployGate::Builds::Ios.project_root_path('test/test.xcodeproj')).to eq root_path + end + + it "when test/test.xcworkspace" do + expect(DeployGate::Builds::Ios.project_root_path('test/test.xcworkspace')).to eq root_path + end + + it "when test/" do + expect(DeployGate::Builds::Ios.project_root_path('test/')).to eq root_path + '/' + end + end + + describe "#scheme_workspace" do + it "should select project.xcworkspace" do + workspaces = ['project.xcworkspace', 'test.xcworkspace'] + expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first + end + + it "single workspace" do + workspaces = ['test.xcworkspace'] + expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first + end + end + + describe "#build_workspace" do + it "not select project.xcworkspace" do + workspaces = ['project.xcworkspace', 'test.xcworkspace'] + expect(DeployGate::Builds::Ios.build_workspace(workspaces)).to eq workspaces.last end - it "default project" do - select_workspace = 'test.xcodeproj' - workspeces = [select_workspace] - expect(DeployGate::Builds::Ios.select_workspace(workspeces)).to eq select_workspace + it "single workspace" do + workspaces = ['project.xcworkspace'] + expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first end end end From c7043d8f235862e58c613aaff3de0ab445533673 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 21 Oct 2015 18:15:32 +0900 Subject: [PATCH 11/45] call process block test delete --- spec/deploygate/api/v1/push_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/deploygate/api/v1/push_spec.rb b/spec/deploygate/api/v1/push_spec.rb index 8dbb49e..34e2389 100644 --- a/spec/deploygate/api/v1/push_spec.rb +++ b/spec/deploygate/api/v1/push_spec.rb @@ -21,7 +21,7 @@ to_return(:body => response.to_json) call_process_block = false - results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message) {call_process_block = true} + results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message) expect(results).to eq ({ :error => response[:error], :message => response[:because], @@ -31,7 +31,6 @@ :revision => response[:results][:revision], :web_url => DeployGate::API::V1::Base::BASE_URL + response[:results][:path] }) - expect(call_process_block).to be_truthy end it "failed" do From d49c4992da0dede1c7cc6186a9be9b9013f522f2 Mon Sep 17 00:00:00 2001 From: henteko Date: Thu, 22 Oct 2015 12:08:14 +0900 Subject: [PATCH 12/45] add Ios::Export class --- lib/deploygate.rb | 1 + lib/deploygate/builds/ios.rb | 153 ++++++++++++------------ lib/deploygate/builds/ios/export.rb | 17 +++ lib/deploygate/commands/deploy/build.rb | 17 +-- spec/deploygate/builds/ios_spec.rb | 4 +- 5 files changed, 98 insertions(+), 94 deletions(-) create mode 100644 lib/deploygate/builds/ios/export.rb diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 99f42f6..16bd7a4 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -26,6 +26,7 @@ module DeployGate require "deploygate/deploy" require "deploygate/build" require "deploygate/builds/ios" +require "deploygate/builds/ios/export" require "deploygate/message/error" require "deploygate/message/success" require "deploygate/version" diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 923fa9f..05fc2bd 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -1,9 +1,6 @@ module DeployGate module Builds - class Ios - AD_HOC = 'ad-hoc' - ENTERPRISE = 'enterprise' - SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE] + module Ios BASE_WORK_DIR_NAME = 'project.xcworkspace' WORK_DIR_EXTNAME = '.xcworkspace' PROJECT_DIR_EXTNAME = '.xcodeproj' @@ -11,92 +8,94 @@ class Ios class NotSupportExportMethodError < StandardError end - # @param [Array] workspaces - # @param [String] export_method - # @return [String] - def build(workspaces, export_method = AD_HOC) - raise NotSupportExportMethodError, 'Not support export' unless SUPPORT_EXPORT_METHOD.include?(export_method) - - scheme_workspace = Ios.scheme_workspace(workspaces) - build_workspace = Ios.build_workspace(workspaces) - config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => scheme_workspace}) - project = FastlaneCore::Project.new(config) - schemes = project.schemes - - values = { - :export_method => export_method, - :workspace => build_workspace, - :scheme => schemes.count == 1 ? schemes.first : nil - } - v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) - absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) - absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip") # TODO: upload to deploygate - - absolute_ipa_path - end - - # @param [String] path - # @return [Boolean] - def self.workspace?(path) - WORK_DIR_EXTNAME == File.extname(path) - end + class << self + # @param [Array] workspaces + # @param [String] export_method + # @return [String] + def build(workspaces, export_method = Export::AD_HOC) + raise NotSupportExportMethodError, 'Not support export' unless Export::SUPPORT_EXPORT_METHOD.include?(export_method) + + scheme_workspace = scheme_workspace(workspaces) + build_workspace = build_workspace(workspaces) + config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => scheme_workspace}) + project = FastlaneCore::Project.new(config) + schemes = project.schemes + + values = { + :export_method => export_method, + :workspace => build_workspace, + :scheme => schemes.count == 1 ? schemes.first : nil + } + v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) + absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) + absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip") # TODO: upload to deploygate + + absolute_ipa_path + end - # @param [String] path - # @return [Boolean] - def self.project?(path) - PROJECT_DIR_EXTNAME == File.extname(path) - end + # @param [String] path + # @return [Boolean] + def workspace?(path) + WORK_DIR_EXTNAME == File.extname(path) + end - # @param [String] path - # @return [Array] - def self.find_workspaces(path) - projects = [] - rule = File::Find.new(:pattern => "*#{WORK_DIR_EXTNAME}", :path => [path]) - rule.find {|f| projects.push(f)} + # @param [String] path + # @return [Boolean] + def project?(path) + PROJECT_DIR_EXTNAME == File.extname(path) + end - projects - end + # @param [String] path + # @return [Array] + def find_workspaces(path) + projects = [] + rule = File::Find.new(:pattern => "*#{WORK_DIR_EXTNAME}", :path => [path]) + rule.find {|f| projects.push(f)} - # @param [String] path - # @return [String] - def self.project_root_path(path) - result = path - if workspace?(path) || project?(path) - result = project_root_path(File.dirname(path)) + projects end - result - end - - # @param [Array] workspaces - # @return [String] - def self.scheme_workspace(workspaces) - return nil if workspaces.empty? - return workspaces.first if workspaces.count == 1 - select = nil - workspaces.each do |workspace| - if BASE_WORK_DIR_NAME == File.basename(workspace) - select = workspace + # @param [String] path + # @return [String] + def project_root_path(path) + result = path + if workspace?(path) || project?(path) + result = project_root_path(File.dirname(path)) end + result end - select - end + # @param [Array] workspaces + # @return [String] + def scheme_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil + workspaces.each do |workspace| + if BASE_WORK_DIR_NAME == File.basename(workspace) + select = workspace + end + end - # @param [Array] workspaces - # @return [String] - def self.build_workspace(workspaces) - return nil if workspaces.empty? - return workspaces.first if workspaces.count == 1 + select + end - select = nil - workspaces.each do |workspace| - if BASE_WORK_DIR_NAME != File.basename(workspace) - select = workspace + # @param [Array] workspaces + # @return [String] + def build_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil + workspaces.each do |workspace| + if BASE_WORK_DIR_NAME != File.basename(workspace) + select = workspace + end end - end - select + select + end end end end diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb new file mode 100644 index 0000000..58ec281 --- /dev/null +++ b/lib/deploygate/builds/ios/export.rb @@ -0,0 +1,17 @@ +module DeployGate + module Builds + module Ios + class Export + AD_HOC = 'ad-hoc' + ENTERPRISE = 'enterprise' + SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE] + + class << self + def method + AD_HOC + end + end + end + end + end +end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index fad0678..eb7d949 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -24,21 +24,8 @@ def run(args, options) # @param [Hash] options # @return [void] def ios(workspaces, options) - puts 'Select Export method:' - puts '1. ad-hoc' - puts '2. Enterprise' - print '? ' - input = STDIN.gets.chop - - method = nil - case input - when '1' - method = DeployGate::Builds::Ios::AD_HOC - when '2' - method = DeployGate::Builds::Ios::ENTERPRISE - end - - ipa_path = DeployGate::Builds::Ios.new.build(workspaces, method) + method = DeployGate::Builds::Ios::Export.method + ipa_path = DeployGate::Builds::Ios.build(workspaces, method) Push.upload([ipa_path], options) end end diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb index 9ba3e4c..cbb75ec 100644 --- a/spec/deploygate/builds/ios_spec.rb +++ b/spec/deploygate/builds/ios_spec.rb @@ -16,7 +16,7 @@ def schemes allow(File).to receive(:expand_path).and_return('path') allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) - DeployGate::Builds::Ios.new.build([]) + DeployGate::Builds::Ios.build([]) expect(call_gym_manager).to be_truthy end @@ -28,7 +28,7 @@ def schemes allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) expect { - DeployGate::Builds::Ios.new.build([], 'not support export method') + DeployGate::Builds::Ios.build([], 'not support export method') }.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError end end From 49fbb49b252c3428c70a0f1178eec3b29f852bff Mon Sep 17 00:00:00 2001 From: henteko Date: Thu, 22 Oct 2015 12:40:52 +0900 Subject: [PATCH 13/45] fix Export.method --- deploygate.gemspec | 1 + lib/deploygate.rb | 2 + lib/deploygate/builds/ios/export.rb | 47 ++++++++++++++++++++++- spec/deploygate/builds/ios/export_spec.rb | 15 ++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 spec/deploygate/builds/ios/export_spec.rb diff --git a/deploygate.gemspec b/deploygate.gemspec index 6dcb9db..f84221b 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -29,6 +29,7 @@ POST_INSTALL_MESSAGE spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' spec.add_dependency 'file-find', '~> 0.3.8' + spec.add_dependency 'plist', '~> 3.1.0' # ios build spec.add_dependency 'gym', '~> 1.0.0' diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 16bd7a4..a26d8a5 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -5,6 +5,8 @@ require "rbconfig" require "color_echo" require "file/find" +require "openssl" +require "plist" # ios build require "gym" diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 58ec281..c9e2f84 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -5,10 +5,55 @@ class Export AD_HOC = 'ad-hoc' ENTERPRISE = 'enterprise' SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE] + PROFILE_EXTNAME = '.mobileprovision' class << self def method - AD_HOC + result = AD_HOC + profiles.each do |profile_path| + result = ENTERPRISE if inhouse?(profile_path) + end + + result + end + + # @param [String] profile_path + # @return [Boolean] + def adhoc?(profile_path) + plist = analyze_profile(profile_path) + plist['ProvisionsAllDevices'].nil? + end + + # @param [String] profile_path + # @return [Boolean] + def inhouse?(profile_path) + !adhoc?(profile_path) + end + + # @param [String] profile_path + # @return [Hash] + def analyze_profile(profile_path) + plist = nil + File.open(profile_path) do |profile| + asn1 = OpenSSL::ASN1.decode(profile.read) + plist_str = asn1.value[1].value[0].value[2].value[1].value[0].value + plist = Plist.parse_xml plist_str.force_encoding('UTF-8') + end + plist + end + + # @return [Array] + def profiles + profiles = [] + rule = File::Find.new(:pattern => "*#{PROFILE_EXTNAME}", :path => [profile_dir_path]) + rule.find {|f| profiles.push(f)} + + profiles + end + + # @return [String] + def profile_dir_path + File.join(ENV['HOME'], 'Library/MobileDevice/Provisioning Profiles') end end end diff --git a/spec/deploygate/builds/ios/export_spec.rb b/spec/deploygate/builds/ios/export_spec.rb new file mode 100644 index 0000000..4adc5c5 --- /dev/null +++ b/spec/deploygate/builds/ios/export_spec.rb @@ -0,0 +1,15 @@ +describe DeployGate::Builds::Ios::Export do + describe "#method" do + it "only ad-hoc user" do + allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['adhoc']) + allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(false) + expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::AD_HOC + end + + it "inhouse user" do + allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['inhouse']) + allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(true) + expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::ENTERPRISE + end + end +end From 11752e3c80928480dc05b04f206fa80deccd9e42 Mon Sep 17 00:00:00 2001 From: henteko Date: Thu, 22 Oct 2015 20:17:05 +0900 Subject: [PATCH 14/45] use get-task-allow --- lib/deploygate/builds/ios/export.rb | 9 ++-- spec/deploygate/builds/ios/export_spec.rb | 60 +++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index c9e2f84..d95055a 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -8,9 +8,11 @@ class Export PROFILE_EXTNAME = '.mobileprovision' class << self + # @return [String] def method - result = AD_HOC + result = nil profiles.each do |profile_path| + result = AD_HOC if adhoc?(profile_path) && result.nil? result = ENTERPRISE if inhouse?(profile_path) end @@ -21,13 +23,14 @@ def method # @return [Boolean] def adhoc?(profile_path) plist = analyze_profile(profile_path) - plist['ProvisionsAllDevices'].nil? + !plist['Entitlements']['get-task-allow'] && plist['ProvisionsAllDevices'].nil? end # @param [String] profile_path # @return [Boolean] def inhouse?(profile_path) - !adhoc?(profile_path) + plist = analyze_profile(profile_path) + !plist['Entitlements']['get-task-allow'] && !plist['ProvisionsAllDevices'].nil? end # @param [String] profile_path diff --git a/spec/deploygate/builds/ios/export_spec.rb b/spec/deploygate/builds/ios/export_spec.rb index 4adc5c5..295b6c2 100644 --- a/spec/deploygate/builds/ios/export_spec.rb +++ b/spec/deploygate/builds/ios/export_spec.rb @@ -3,13 +3,73 @@ it "only ad-hoc user" do allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['adhoc']) allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(false) + allow(DeployGate::Builds::Ios::Export).to receive(:adhoc?).and_return(true) expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::AD_HOC end it "inhouse user" do allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['inhouse']) allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(true) + allow(DeployGate::Builds::Ios::Export).to receive(:adhoc?).and_return(true) expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::ENTERPRISE end end + + describe "#adhoc?" do + it "when adhoc plist" do + plist = { + 'ProvisionsAllDevices' => nil, + 'Entitlements' => {'get-task-allow' => false} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_truthy + end + + it "when inhouse plist" do + plist = { + 'ProvisionsAllDevices' => true, + 'Entitlements' => {'get-task-allow' => false} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey + end + + it "when not distribution plist" do + plist = { + 'ProvisionsAllDevices' => nil, + 'Entitlements' => {'get-task-allow' => true} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey + end + end + + describe "#inhouse?" do + it "when adhoc plist" do + plist = { + 'ProvisionsAllDevices' => nil, + 'Entitlements' => {'get-task-allow' => false} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey + end + + it "when inhouse plist" do + plist = { + 'ProvisionsAllDevices' => true, + 'Entitlements' => {'get-task-allow' => false} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_truthy + end + + it "when not distribution plist" do + plist = { + 'ProvisionsAllDevices' => nil, + 'Entitlements' => {'get-task-allow' => true} + } + allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist) + expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey + end + end end From 9ae692ce039958285c97376805d70aea1f7f6ea2 Mon Sep 17 00:00:00 2001 From: henteko Date: Thu, 22 Oct 2015 20:50:13 +0900 Subject: [PATCH 15/45] delete file/find --- deploygate.gemspec | 1 - lib/deploygate.rb | 2 +- lib/deploygate/build.rb | 3 +-- lib/deploygate/builds/ios.rb | 22 ++++++++++++++++++---- lib/deploygate/builds/ios/export.rb | 9 +++++++-- spec/deploygate/build_spec.rb | 9 ++++++--- 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/deploygate.gemspec b/deploygate.gemspec index f84221b..c19db55 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -28,7 +28,6 @@ POST_INSTALL_MESSAGE spec.add_dependency 'httpclient', '~> 2.2.5' spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' - spec.add_dependency 'file-find', '~> 0.3.8' spec.add_dependency 'plist', '~> 3.1.0' # ios build diff --git a/lib/deploygate.rb b/lib/deploygate.rb index a26d8a5..2067adc 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -4,9 +4,9 @@ require "io/console" require "rbconfig" require "color_echo" -require "file/find" require "openssl" require "plist" +require "find" # ios build require "gym" diff --git a/lib/deploygate/build.rb b/lib/deploygate/build.rb index c28ad3f..9368d2c 100644 --- a/lib/deploygate/build.rb +++ b/lib/deploygate/build.rb @@ -5,8 +5,7 @@ class << self # @param [String] path # @return [Boolean] def ios?(path) - workspaces = DeployGate::Builds::Ios.find_workspaces(path) - DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || !workspaces.empty? + DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || DeployGate::Builds::Ios.ios_root?(path) end # @param [String] path diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 05fc2bd..35eef14 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -45,12 +45,26 @@ def project?(path) PROJECT_DIR_EXTNAME == File.extname(path) end - # @param [String] path + def ios_root?(base_path) + Find.find(base_path) do |path| + next if path == base_path + return true if workspace?(path) || project?(path) + Find.prune if FileTest.directory?(path) + end + false + end + + # @param [String] base_path + # @param [Boolean] current_only # @return [Array] - def find_workspaces(path) + def find_workspaces(base_path) projects = [] - rule = File::Find.new(:pattern => "*#{WORK_DIR_EXTNAME}", :path => [path]) - rule.find {|f| projects.push(f)} + Find.find(base_path) do |path| + next if path == base_path + if File.extname(path) == WORK_DIR_EXTNAME + projects.push(path) + end + end projects end diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index d95055a..ac526e5 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -48,8 +48,13 @@ def analyze_profile(profile_path) # @return [Array] def profiles profiles = [] - rule = File::Find.new(:pattern => "*#{PROFILE_EXTNAME}", :path => [profile_dir_path]) - rule.find {|f| profiles.push(f)} + Find.find(profile_dir_path) do |path| + next if path == profile_dir_path + Find.prune if FileTest.directory?(path) + if File.extname(path) == PROFILE_EXTNAME + profiles.push(path) + end + end profiles end diff --git a/spec/deploygate/build_spec.rb b/spec/deploygate/build_spec.rb index 8af802c..55f3971 100644 --- a/spec/deploygate/build_spec.rb +++ b/spec/deploygate/build_spec.rb @@ -1,24 +1,27 @@ describe DeployGate::Build do describe "#ios?" do it "when select workspace" do - allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return([]) + allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false) allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(true) + allow(DeployGate::Builds::Ios).to receive(:project?).and_return(false) result = DeployGate::Build.ios?('path') expect(result).to be_truthy end it "when workspaces" do - allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return(['path']) + allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false) allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false) + allow(DeployGate::Builds::Ios).to receive(:project?).and_return(true) result = DeployGate::Build.ios?('path') expect(result).to be_truthy end it "not ios" do - allow(DeployGate::Builds::Ios).to receive(:find_workspaces).and_return([]) + allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false) allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false) + allow(DeployGate::Builds::Ios).to receive(:project?).and_return(false) result = DeployGate::Build.ios?('path') expect(result).to be_falsey From 096cef353e9ebb13d976dde426b65f167f5348b5 Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 18:32:28 +0900 Subject: [PATCH 16/45] add ios Analyze class --- deploygate.gemspec | 1 + lib/deploygate.rb | 2 + lib/deploygate/builds/ios.rb | 50 +++------------- lib/deploygate/builds/ios/analyze.rb | 79 +++++++++++++++++++++++++ lib/deploygate/builds/ios/export.rb | 18 +++++- lib/deploygate/commands/deploy/build.rb | 14 ++++- 6 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 lib/deploygate/builds/ios/analyze.rb diff --git a/deploygate.gemspec b/deploygate.gemspec index c19db55..4e873a8 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -29,6 +29,7 @@ POST_INSTALL_MESSAGE spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' spec.add_dependency 'plist', '~> 3.1.0' + spec.add_dependency 'pbxplorer', '~> 1.0.0' # ios build spec.add_dependency 'gym', '~> 1.0.0' diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 2067adc..1384a8d 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -7,6 +7,7 @@ require "openssl" require "plist" require "find" +require "pbxplorer" # TODO: error gym # ios build require "gym" @@ -29,6 +30,7 @@ module DeployGate require "deploygate/build" require "deploygate/builds/ios" require "deploygate/builds/ios/export" +require "deploygate/builds/ios/analyze" require "deploygate/message/error" require "deploygate/message/success" require "deploygate/version" diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 35eef14..f401505 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -1,30 +1,26 @@ module DeployGate module Builds module Ios - BASE_WORK_DIR_NAME = 'project.xcworkspace' WORK_DIR_EXTNAME = '.xcworkspace' PROJECT_DIR_EXTNAME = '.xcodeproj' + PBXPROJ_FILE_NAME = 'project.pbxproj' class NotSupportExportMethodError < StandardError end class << self - # @param [Array] workspaces + # @param [Analyze] ios_analyze + # @param [String] target_scheme # @param [String] export_method # @return [String] - def build(workspaces, export_method = Export::AD_HOC) + def build(ios_analyze, target_scheme, export_method = Export::AD_HOC) raise NotSupportExportMethodError, 'Not support export' unless Export::SUPPORT_EXPORT_METHOD.include?(export_method) - scheme_workspace = scheme_workspace(workspaces) - build_workspace = build_workspace(workspaces) - config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => scheme_workspace}) - project = FastlaneCore::Project.new(config) - schemes = project.schemes - values = { :export_method => export_method, - :workspace => build_workspace, - :scheme => schemes.count == 1 ? schemes.first : nil + :workspace => ios_analyze.build_workspace, + :configuration => Analyze::BUILD_CONFIGRATION, + :scheme => target_scheme } v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) @@ -78,38 +74,6 @@ def project_root_path(path) end result end - - # @param [Array] workspaces - # @return [String] - def scheme_workspace(workspaces) - return nil if workspaces.empty? - return workspaces.first if workspaces.count == 1 - - select = nil - workspaces.each do |workspace| - if BASE_WORK_DIR_NAME == File.basename(workspace) - select = workspace - end - end - - select - end - - # @param [Array] workspaces - # @return [String] - def build_workspace(workspaces) - return nil if workspaces.empty? - return workspaces.first if workspaces.count == 1 - - select = nil - workspaces.each do |workspace| - if BASE_WORK_DIR_NAME != File.basename(workspace) - select = workspace - end - end - - select - end end end end diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb new file mode 100644 index 0000000..d2d5512 --- /dev/null +++ b/lib/deploygate/builds/ios/analyze.rb @@ -0,0 +1,79 @@ +module DeployGate + module Builds + module Ios + class Analyze + attr_reader :workspaces, :scheme_workspace, :build_workspace + + class NotLocalProvisioningProfileError < StandardError + end + + BASE_WORK_DIR_NAME = 'project.xcworkspace' + BUILD_CONFIGRATION = 'Release' + + def initialize(workspaces) + @workspaces = workspaces + @scheme_workspace = find_scheme_workspace(workspaces) + @build_workspace = find_build_workspace(workspaces) + end + + def schemes + config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace}) + project = FastlaneCore::Project.new(config) + project.schemes + end + + def run(scheme_name) + identifier = target_bundle_identifier(@scheme_workspace, scheme_name, BUILD_CONFIGRATION) + provisioning_profile = Export.target_provisioning_profile(identifier) + raise NotLocalProvisioningProfileError if provisioning_profile.nil? + + { + :method => Export.adhoc?(provisioning_profile) ? Export::AD_HOC : Export::ENTERPRISE, + :provisoning_profile => provisioning_profile + } + end + + private + + def target_bundle_identifier(scheme_workspace, scheme_name, build_configration) + project_file = XCProjectFile.new(File.join(File.dirname(scheme_workspace), PBXPROJ_FILE_NAME)) + target = project_file.project.targets.reject{|target| target['name'] != scheme_name}.first + conf = target.build_configuration_list.build_configurations.reject{|conf| conf['name'] != build_configration}.first + conf['buildSettings']['PRODUCT_BUNDLE_IDENTIFIER'] + end + + # @param [Array] workspaces + # @return [String] + def find_scheme_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil + workspaces.each do |workspace| + if BASE_WORK_DIR_NAME == File.basename(workspace) + select = workspace + end + end + + select + end + + # @param [Array] workspaces + # @return [String] + def find_build_workspace(workspaces) + return nil if workspaces.empty? + return workspaces.first if workspaces.count == 1 + + select = nil + workspaces.each do |workspace| + if BASE_WORK_DIR_NAME != File.basename(workspace) + select = workspace + end + end + + select + end + end + end + end +end diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index ac526e5..3913529 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -9,11 +9,23 @@ class Export class << self # @return [String] - def method + def target_provisioning_profile(bundle_identifier) result = nil profiles.each do |profile_path| - result = AD_HOC if adhoc?(profile_path) && result.nil? - result = ENTERPRISE if inhouse?(profile_path) + plist = analyze_profile(profile_path) + entities = plist['Entitlements'] + unless entities['get-task-allow'] + team = entities['com.apple.developer.team-identifier'] + application_id = entities['application-identifier'] + application_id.slice!(/^#{team}\./) + if bundle_identifier.match(application_id) + if adhoc?(profile_path) && result.nil? + result = profile_path + elsif inhouse?(profile_path) + result = profile_path + end + end + end end result diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index eb7d949..83b82df 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -24,8 +24,18 @@ def run(args, options) # @param [Hash] options # @return [void] def ios(workspaces, options) - method = DeployGate::Builds::Ios::Export.method - ipa_path = DeployGate::Builds::Ios.build(workspaces, method) + analyze = DeployGate::Builds::Ios::Analyze.new(workspaces) + schemes = analyze.schemes + target_shceme = schemes.first # TODO: select scheme user + + data = nil + begin + data = analyze.run(target_shceme) + rescue DeployGate::Builds::Ios::Analyze::NotLocalProvisioningProfileError => e + raise e # TODO: start fastlane/sigh + end + + ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, data[:method]) Push.upload([ipa_path], options) end end From 8c5a0f601ae229a02f07e2e358273df6b715c1ac Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 18:38:19 +0900 Subject: [PATCH 17/45] fix specs --- spec/deploygate/builds/ios/analyze_spec.rb | 3 ++ spec/deploygate/builds/ios/export_spec.rb | 16 ----------- spec/deploygate/builds/ios_spec.rb | 33 +++++----------------- 3 files changed, 10 insertions(+), 42 deletions(-) create mode 100644 spec/deploygate/builds/ios/analyze_spec.rb diff --git a/spec/deploygate/builds/ios/analyze_spec.rb b/spec/deploygate/builds/ios/analyze_spec.rb new file mode 100644 index 0000000..8bbdc94 --- /dev/null +++ b/spec/deploygate/builds/ios/analyze_spec.rb @@ -0,0 +1,3 @@ +describe DeployGate::Builds::Ios::Analyze do + # TODO: add test +end diff --git a/spec/deploygate/builds/ios/export_spec.rb b/spec/deploygate/builds/ios/export_spec.rb index 295b6c2..6b52d7d 100644 --- a/spec/deploygate/builds/ios/export_spec.rb +++ b/spec/deploygate/builds/ios/export_spec.rb @@ -1,20 +1,4 @@ describe DeployGate::Builds::Ios::Export do - describe "#method" do - it "only ad-hoc user" do - allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['adhoc']) - allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(false) - allow(DeployGate::Builds::Ios::Export).to receive(:adhoc?).and_return(true) - expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::AD_HOC - end - - it "inhouse user" do - allow(DeployGate::Builds::Ios::Export).to receive(:profiles).and_return(['inhouse']) - allow(DeployGate::Builds::Ios::Export).to receive(:inhouse?).and_return(true) - allow(DeployGate::Builds::Ios::Export).to receive(:adhoc?).and_return(true) - expect(DeployGate::Builds::Ios::Export.method).to eq DeployGate::Builds::Ios::Export::ENTERPRISE - end - end - describe "#adhoc?" do it "when adhoc plist" do plist = { diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb index cbb75ec..92e8068 100644 --- a/spec/deploygate/builds/ios_spec.rb +++ b/spec/deploygate/builds/ios_spec.rb @@ -5,6 +5,11 @@ def schemes [] end end + class AnalyzeMock + def build_workspace + '' + end + end end describe "#build" do @@ -16,7 +21,7 @@ def schemes allow(File).to receive(:expand_path).and_return('path') allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) - DeployGate::Builds::Ios.build([]) + DeployGate::Builds::Ios.build(AnalyzeMock.new, '') expect(call_gym_manager).to be_truthy end @@ -28,7 +33,7 @@ def schemes allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) expect { - DeployGate::Builds::Ios.build([], 'not support export method') + DeployGate::Builds::Ios.build(AnalyzeMock.new, '', 'not support export method') }.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError end end @@ -87,28 +92,4 @@ def schemes expect(DeployGate::Builds::Ios.project_root_path('test/')).to eq root_path + '/' end end - - describe "#scheme_workspace" do - it "should select project.xcworkspace" do - workspaces = ['project.xcworkspace', 'test.xcworkspace'] - expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first - end - - it "single workspace" do - workspaces = ['test.xcworkspace'] - expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first - end - end - - describe "#build_workspace" do - it "not select project.xcworkspace" do - workspaces = ['project.xcworkspace', 'test.xcworkspace'] - expect(DeployGate::Builds::Ios.build_workspace(workspaces)).to eq workspaces.last - end - - it "single workspace" do - workspaces = ['project.xcworkspace'] - expect(DeployGate::Builds::Ios.scheme_workspace(workspaces)).to eq workspaces.first - end - end end From dd66b07daa58415aaeed1c9b5795aa6fd8358aa6 Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 18:56:39 +0900 Subject: [PATCH 18/45] support scheme user select --- lib/deploygate/commands/deploy/build.rb | 26 ++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 83b82df..ffd379c 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -26,7 +26,12 @@ def run(args, options) def ios(workspaces, options) analyze = DeployGate::Builds::Ios::Analyze.new(workspaces) schemes = analyze.schemes - target_shceme = schemes.first # TODO: select scheme user + raise 'Scheme empty error' if schemes.empty? + + target_shceme = schemes.first + if schemes.count > 1 + target_shceme = select_schemes(schemes) + end data = nil begin @@ -38,6 +43,25 @@ def ios(workspaces, options) ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, data[:method]) Push.upload([ipa_path], options) end + + def select_schemes(schemes) + result = nil + puts 'Select scheme:' + schemes.each_with_index do |scheme, index| + puts "#{index + 1}. #{scheme}" + end + print '? ' + select = STDIN.gets.chop + begin + result = schemes[Integer(select) - 1] + raise 'not select' if result.nil? + rescue => e + puts 'Please select scheme number' + return select_schemes(schemes) + end + + result + end end end end From aab718f8f8004cbaf0e3a5d30c158a091c4967ed Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 19:00:12 +0900 Subject: [PATCH 19/45] add YARD comment --- lib/deploygate/builds/ios/analyze.rb | 9 +++++++++ lib/deploygate/builds/ios/export.rb | 1 + lib/deploygate/commands/deploy/build.rb | 2 ++ 3 files changed, 12 insertions(+) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index d2d5512..1b9d232 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -10,18 +10,23 @@ class NotLocalProvisioningProfileError < StandardError BASE_WORK_DIR_NAME = 'project.xcworkspace' BUILD_CONFIGRATION = 'Release' + # @param [Array] workspaces + # @return [DeployGate::Builds::Ios::Analyze] def initialize(workspaces) @workspaces = workspaces @scheme_workspace = find_scheme_workspace(workspaces) @build_workspace = find_build_workspace(workspaces) end + # @return [Array] def schemes config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace}) project = FastlaneCore::Project.new(config) project.schemes end + # @param [String] scheme_name + # @return [Hash] def run(scheme_name) identifier = target_bundle_identifier(@scheme_workspace, scheme_name, BUILD_CONFIGRATION) provisioning_profile = Export.target_provisioning_profile(identifier) @@ -35,6 +40,10 @@ def run(scheme_name) private + # @param [String] scheme_workspace + # @param [String] scheme_name + # @param [String] build_configration + # @return [String] def target_bundle_identifier(scheme_workspace, scheme_name, build_configration) project_file = XCProjectFile.new(File.join(File.dirname(scheme_workspace), PBXPROJ_FILE_NAME)) target = project_file.project.targets.reject{|target| target['name'] != scheme_name}.first diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 3913529..4dde957 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -8,6 +8,7 @@ class Export PROFILE_EXTNAME = '.mobileprovision' class << self + # @param [String] bundle_identifier # @return [String] def target_provisioning_profile(bundle_identifier) result = nil diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index ffd379c..8272899 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -44,6 +44,8 @@ def ios(workspaces, options) Push.upload([ipa_path], options) end + # @param [Array] schemes + # @return [String] def select_schemes(schemes) result = nil puts 'Select scheme:' From d4d2a231787eb1db6c4af348d3cb286bc3562f0e Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 19:12:06 +0900 Subject: [PATCH 20/45] get bundle identifier --- lib/deploygate/builds/ios/analyze.rb | 24 +++++++++--------------- lib/deploygate/commands/deploy/build.rb | 8 +++++--- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index 1b9d232..c3b41a9 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -25,32 +25,26 @@ def schemes project.schemes end - # @param [String] scheme_name - # @return [Hash] - def run(scheme_name) - identifier = target_bundle_identifier(@scheme_workspace, scheme_name, BUILD_CONFIGRATION) + # @param [String] identifier + # @return [String] + def run(identifier) provisioning_profile = Export.target_provisioning_profile(identifier) raise NotLocalProvisioningProfileError if provisioning_profile.nil? - { - :method => Export.adhoc?(provisioning_profile) ? Export::AD_HOC : Export::ENTERPRISE, - :provisoning_profile => provisioning_profile - } + Export.adhoc?(provisioning_profile) ? Export::AD_HOC : Export::ENTERPRISE end - private - - # @param [String] scheme_workspace # @param [String] scheme_name - # @param [String] build_configration # @return [String] - def target_bundle_identifier(scheme_workspace, scheme_name, build_configration) - project_file = XCProjectFile.new(File.join(File.dirname(scheme_workspace), PBXPROJ_FILE_NAME)) + def target_bundle_identifier(scheme_name) + project_file = XCProjectFile.new(File.join(File.dirname(@scheme_workspace), PBXPROJ_FILE_NAME)) target = project_file.project.targets.reject{|target| target['name'] != scheme_name}.first - conf = target.build_configuration_list.build_configurations.reject{|conf| conf['name'] != build_configration}.first + conf = target.build_configuration_list.build_configurations.reject{|conf| conf['name'] != BUILD_CONFIGRATION}.first conf['buildSettings']['PRODUCT_BUNDLE_IDENTIFIER'] end + private + # @param [Array] workspaces # @return [String] def find_scheme_workspace(workspaces) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 8272899..11a4cd7 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -33,14 +33,16 @@ def ios(workspaces, options) target_shceme = select_schemes(schemes) end - data = nil + + identifier = analyze.target_bundle_identifier(target_shceme) + method = nil begin - data = analyze.run(target_shceme) + method = analyze.run(identifier) rescue DeployGate::Builds::Ios::Analyze::NotLocalProvisioningProfileError => e raise e # TODO: start fastlane/sigh end - ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, data[:method]) + ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, method) Push.upload([ipa_path], options) end From 505b97a450055ead2febe1c1bb8272a96ae9c427 Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 20:33:23 +0900 Subject: [PATCH 21/45] auto install provisioning profile --- deploygate.gemspec | 2 + lib/deploygate.rb | 3 + lib/deploygate/builds/ios/set_profile.rb | 57 +++++++++++++++++++ lib/deploygate/commands/deploy/build.rb | 17 +++++- .../deploygate/builds/ios/set_profile_spec.rb | 3 + 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 lib/deploygate/builds/ios/set_profile.rb create mode 100644 spec/deploygate/builds/ios/set_profile_spec.rb diff --git a/deploygate.gemspec b/deploygate.gemspec index 4e873a8..1723a2c 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -33,6 +33,8 @@ POST_INSTALL_MESSAGE # ios build spec.add_dependency 'gym', '~> 1.0.0' + spec.add_dependency 'spaceship', '~> 0.12.3' + spec.add_dependency 'sigh', '~> 1.1.0' spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 1384a8d..ec0bf95 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -11,6 +11,8 @@ # ios build require "gym" +require "spaceship" +require "sigh" module DeployGate end @@ -31,6 +33,7 @@ module DeployGate require "deploygate/builds/ios" require "deploygate/builds/ios/export" require "deploygate/builds/ios/analyze" +require "deploygate/builds/ios/set_profile" require "deploygate/message/error" require "deploygate/message/success" require "deploygate/version" diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb new file mode 100644 index 0000000..e8ba061 --- /dev/null +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -0,0 +1,57 @@ +module DeployGate + module Builds + module Ios + class SetProfile + attr_reader :method + + OUTPUT_PATH = '/tmp/dg/provisioning_profile/' + + # @param [String] username + # @param [String] identifier + # @return [DeployGate::Builds::Ios::SetProfile] + def initialize(username, identifier) + @username = username + @identifier = identifier + Spaceship.login(username) + if Spaceship.client.in_house? + @method = Export::ENTERPRISE + else + @method = Export::AD_HOC + end + end + + # @return [Boolean] + def app_id_create + app_created = false + Spaceship.app.all.collect do |app| + if app.bundle_id == @identifier + app_created = true + break + end + end + unless app_created + Spaceship.app.create!(:bundle_id => @identifier, :name => "#{@identifier.split('.').join(' ')}") + return true + end + + false + end + + # @return [void] + def create_provisioning + FileUtils.mkdir_p(OUTPUT_PATH) + values = { + :adhoc => @method == Export::AD_HOC ? true : false, + :app_identifier => @identifier, + :username => @username, + :output_path => OUTPUT_PATH + } + v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values) + Sigh.config = v + Sigh::Manager.start + end + + end + end + end +end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 11a4cd7..7b0a11e 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -39,7 +39,7 @@ def ios(workspaces, options) begin method = analyze.run(identifier) rescue DeployGate::Builds::Ios::Analyze::NotLocalProvisioningProfileError => e - raise e # TODO: start fastlane/sigh + method = create_provisioning(identifier) end ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, method) @@ -66,6 +66,21 @@ def select_schemes(schemes) result end + + # @param [String] identifier + # @return [String] + def create_provisioning(identifier) + print 'Username: ' + username = STDIN.gets.chop + + set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier) + if set_profile.app_id_create + puts "Create #{identifier} app id" + end + set_profile.create_provisioning + + set_profile.method + end end end end diff --git a/spec/deploygate/builds/ios/set_profile_spec.rb b/spec/deploygate/builds/ios/set_profile_spec.rb new file mode 100644 index 0000000..d486cce --- /dev/null +++ b/spec/deploygate/builds/ios/set_profile_spec.rb @@ -0,0 +1,3 @@ +describe DeployGate::Builds::Ios::SetProfile do + # TODO: add test +end From 07ece563cc1b1f69b6f423e07e1337866b8f30d0 Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 20:51:50 +0900 Subject: [PATCH 22/45] delete pbxplorer, use xcodeproj --- deploygate.gemspec | 2 +- lib/deploygate.rb | 2 +- lib/deploygate/builds/ios.rb | 1 - lib/deploygate/builds/ios/analyze.rb | 8 ++++---- lib/deploygate/commands/deploy/build.rb | 1 - 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/deploygate.gemspec b/deploygate.gemspec index 1723a2c..6fd1151 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -29,7 +29,7 @@ POST_INSTALL_MESSAGE spec.add_dependency 'commander', '~> 4.3.5' spec.add_dependency 'color_echo', '~> 2.0.1' spec.add_dependency 'plist', '~> 3.1.0' - spec.add_dependency 'pbxplorer', '~> 1.0.0' + spec.add_dependency 'xcodeproj', '~> 0.28.2' # ios build spec.add_dependency 'gym', '~> 1.0.0' diff --git a/lib/deploygate.rb b/lib/deploygate.rb index ec0bf95..21f716a 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -7,12 +7,12 @@ require "openssl" require "plist" require "find" -require "pbxplorer" # TODO: error gym # ios build require "gym" require "spaceship" require "sigh" +require "xcodeproj" module DeployGate end diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index f401505..33970b5 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -3,7 +3,6 @@ module Builds module Ios WORK_DIR_EXTNAME = '.xcworkspace' PROJECT_DIR_EXTNAME = '.xcodeproj' - PBXPROJ_FILE_NAME = 'project.pbxproj' class NotSupportExportMethodError < StandardError end diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index c3b41a9..bd9e4bf 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -37,10 +37,10 @@ def run(identifier) # @param [String] scheme_name # @return [String] def target_bundle_identifier(scheme_name) - project_file = XCProjectFile.new(File.join(File.dirname(@scheme_workspace), PBXPROJ_FILE_NAME)) - target = project_file.project.targets.reject{|target| target['name'] != scheme_name}.first - conf = target.build_configuration_list.build_configurations.reject{|conf| conf['name'] != BUILD_CONFIGRATION}.first - conf['buildSettings']['PRODUCT_BUNDLE_IDENTIFIER'] + project = Xcodeproj::Project.open(File.dirname(@scheme_workspace)) + target = project.targets.reject{|target| target.name != scheme_name}.first + conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first + conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] end private diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 7b0a11e..5089c0f 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -33,7 +33,6 @@ def ios(workspaces, options) target_shceme = select_schemes(schemes) end - identifier = analyze.target_bundle_identifier(target_shceme) method = nil begin From a30a910c9dceff82e8ab0837e6c976c7d53fc20e Mon Sep 17 00:00:00 2001 From: henteko Date: Mon, 26 Oct 2015 20:55:59 +0900 Subject: [PATCH 23/45] fix wording --- lib/deploygate/commands/deploy/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 5089c0f..19c8ea7 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -69,7 +69,7 @@ def select_schemes(schemes) # @param [String] identifier # @return [String] def create_provisioning(identifier) - print 'Username: ' + print 'apple developer Username: ' username = STDIN.gets.chop set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier) From b9169c4106533ff1239dc240c173c2cb41e2150f Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 15:06:46 +0900 Subject: [PATCH 24/45] add spaceship error handling --- lib/deploygate/builds/ios/analyze.rb | 9 ------- lib/deploygate/builds/ios/export.rb | 20 +++++++------- lib/deploygate/commands/deploy/build.rb | 35 ++++++++++++++++++++----- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index bd9e4bf..3f5550c 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -25,15 +25,6 @@ def schemes project.schemes end - # @param [String] identifier - # @return [String] - def run(identifier) - provisioning_profile = Export.target_provisioning_profile(identifier) - raise NotLocalProvisioningProfileError if provisioning_profile.nil? - - Export.adhoc?(provisioning_profile) ? Export::AD_HOC : Export::ENTERPRISE - end - # @param [String] scheme_name # @return [String] def target_bundle_identifier(scheme_name) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 4dde957..637a965 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -9,9 +9,9 @@ class Export class << self # @param [String] bundle_identifier - # @return [String] - def target_provisioning_profile(bundle_identifier) - result = nil + # @return [Array] + def target_provisioning_profiles(bundle_identifier) + results = [] profiles.each do |profile_path| plist = analyze_profile(profile_path) entities = plist['Entitlements'] @@ -20,16 +20,18 @@ def target_provisioning_profile(bundle_identifier) application_id = entities['application-identifier'] application_id.slice!(/^#{team}\./) if bundle_identifier.match(application_id) - if adhoc?(profile_path) && result.nil? - result = profile_path - elsif inhouse?(profile_path) - result = profile_path - end + results.push(profile_path) end end end - result + results + end + + # @param [String] profile_path + # @return [String] + def method(profile_path) + adhoc?(profile_path) ? AD_HOC : ENTERPRISE end # @param [String] profile_path diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 19c8ea7..2764ff0 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -34,11 +34,15 @@ def ios(workspaces, options) end identifier = analyze.target_bundle_identifier(target_shceme) + provisioning_profiles = DeployGate::Builds::Ios::Export.target_provisioning_profiles(identifier) + method = nil - begin - method = analyze.run(identifier) - rescue DeployGate::Builds::Ios::Analyze::NotLocalProvisioningProfileError => e + if provisioning_profiles.empty? method = create_provisioning(identifier) + elsif provisioning_profiles.count == 1 + method = DeployGate::Builds::Ios::Export.method(provisioning_profiles.first) + elsif provisioning_profiles.count >= 2 + # TODO: user select provisioning profile end ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, method) @@ -72,11 +76,28 @@ def create_provisioning(identifier) print 'apple developer Username: ' username = STDIN.gets.chop - set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier) - if set_profile.app_id_create - puts "Create #{identifier} app id" + begin + set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier) + rescue => e + DeployGate::Message::Error.print("Error: Please login try again") + raise e + end + + begin + if set_profile.app_id_create + puts "Create #{identifier} app id" + end + rescue => e + DeployGate::Message::Error.print("Error: App id create error") + raise e + end + + begin + set_profile.create_provisioning + rescue => e + DeployGate::Message::Error.print("Error: Failed create provisioning") + raise e end - set_profile.create_provisioning set_profile.method end From 420a2722f3d3d0fe7fdf94407ac209dc59a843eb Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 16:59:16 +0900 Subject: [PATCH 25/45] add select teams --- lib/deploygate/builds/ios.rb | 6 ++- lib/deploygate/builds/ios/export.rb | 36 +++++++++++++--- lib/deploygate/builds/ios/set_profile.rb | 3 +- lib/deploygate/commands/deploy/build.rb | 53 ++++++++++++++++++------ 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/lib/deploygate/builds/ios.rb b/lib/deploygate/builds/ios.rb index 33970b5..fca07d7 100644 --- a/lib/deploygate/builds/ios.rb +++ b/lib/deploygate/builds/ios.rb @@ -10,16 +10,18 @@ class NotSupportExportMethodError < StandardError class << self # @param [Analyze] ios_analyze # @param [String] target_scheme + # @param [String] codesigning_identity # @param [String] export_method # @return [String] - def build(ios_analyze, target_scheme, export_method = Export::AD_HOC) + def build(ios_analyze, target_scheme, codesigning_identity, export_method = Export::AD_HOC) raise NotSupportExportMethodError, 'Not support export' unless Export::SUPPORT_EXPORT_METHOD.include?(export_method) values = { :export_method => export_method, :workspace => ios_analyze.build_workspace, :configuration => Analyze::BUILD_CONFIGRATION, - :scheme => target_scheme + :scheme => target_scheme, + :codesigning_identity => codesigning_identity } v = FastlaneCore::Configuration.create(Gym::Options.available_options, values) absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v)) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 637a965..2a1633f 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -9,9 +9,10 @@ class Export class << self # @param [String] bundle_identifier - # @return [Array] - def target_provisioning_profiles(bundle_identifier) - results = [] + # @return [Hash] + def find_local_data(bundle_identifier) + result_profiles = {} + teams = {} profiles.each do |profile_path| plist = analyze_profile(profile_path) entities = plist['Entitlements'] @@ -19,13 +20,38 @@ def target_provisioning_profiles(bundle_identifier) team = entities['com.apple.developer.team-identifier'] application_id = entities['application-identifier'] application_id.slice!(/^#{team}\./) + application_id = '.' + application_id if application_id == '*' if bundle_identifier.match(application_id) - results.push(profile_path) + teams[team] = plist['TeamName'] if teams[team].nil? + result_profiles[team] = [] if result_profiles[team].nil? + result_profiles[team].push(profile_path) end end end - results + { + :teams => teams, + :profiles => result_profiles + } + end + + # @param [Array] profiles + # @return [String] + def select_profile(profiles) + select = nil + + profiles.each do |profile| + select = profile if adhoc?(profile) && select.nil? + select = profile if inhouse?(profile) + end + select + end + + # @param [String] profile_path + # @return [String] + def codesigning_identity(profile_path) + plist = analyze_profile(profile_path) + "iPhone Distribution: #{plist['TeamName']} (#{plist['Entitlements']['com.apple.developer.team-identifier']})" end # @param [String] profile_path diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb index e8ba061..2fc7851 100644 --- a/lib/deploygate/builds/ios/set_profile.rb +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -37,7 +37,7 @@ def app_id_create false end - # @return [void] + # @return [String] def create_provisioning FileUtils.mkdir_p(OUTPUT_PATH) values = { @@ -50,7 +50,6 @@ def create_provisioning Sigh.config = v Sigh::Manager.start end - end end end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 2764ff0..a23451d 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -34,18 +34,22 @@ def ios(workspaces, options) end identifier = analyze.target_bundle_identifier(target_shceme) - provisioning_profiles = DeployGate::Builds::Ios::Export.target_provisioning_profiles(identifier) - - method = nil - if provisioning_profiles.empty? - method = create_provisioning(identifier) - elsif provisioning_profiles.count == 1 - method = DeployGate::Builds::Ios::Export.method(provisioning_profiles.first) - elsif provisioning_profiles.count >= 2 - # TODO: user select provisioning profile + data = DeployGate::Builds::Ios::Export.find_local_data(identifier) + profiles = data[:profiles] + teams = data[:teams] + + target_provisioning_profile = nil + if teams.empty? + target_provisioning_profile = create_provisioning(identifier) + elsif teams.count == 1 + target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first]) + elsif teams.count >= 2 + target_provisioning_profile = select_teams(teams, profiles) end + method = DeployGate::Builds::Ios::Export.method(target_provisioning_profile) + codesigning_identity = DeployGate::Builds::Ios::Export.codesigning_identity(target_provisioning_profile) - ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, method) + ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, codesigning_identity, method) Push.upload([ipa_path], options) end @@ -70,6 +74,31 @@ def select_schemes(schemes) result end + # @param [Hash] teams + # @param [Hash] profiles + # @return [String] + def select_teams(teams, profiles) + result = nil + puts 'Select team:' + teams.each_with_index do |team, index| + puts "#{index + 1}. #{team[1]} (#{team[0]})" + end + print '? ' + select = STDIN.gets.chop + begin + team = teams.keys[Integer(select) - 1] + team_profiles = profiles[team].first + raise 'not select' if team_profiles.nil? + + result = DeployGate::Builds::Ios::Export.select_profile(profiles[team]) + rescue => e + puts 'Please select team number' + return select_teams(teams, profiles) + end + + result + end + # @param [String] identifier # @return [String] def create_provisioning(identifier) @@ -93,13 +122,13 @@ def create_provisioning(identifier) end begin - set_profile.create_provisioning + provisioning_profile_path = set_profile.create_provisioning rescue => e DeployGate::Message::Error.print("Error: Failed create provisioning") raise e end - set_profile.method + provisioning_profile_path end end end From 98dcc46e2b9e10fa6fff65ab998c458700e3796f Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 18:46:14 +0900 Subject: [PATCH 26/45] all certificate profile --- lib/deploygate/builds/ios/export.rb | 1 + lib/deploygate/builds/ios/set_profile.rb | 29 ++++++++++++++++-------- lib/deploygate/commands/deploy/build.rb | 14 ++++++++---- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 2a1633f..9058a2b 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -22,6 +22,7 @@ def find_local_data(bundle_identifier) application_id.slice!(/^#{team}\./) application_id = '.' + application_id if application_id == '*' if bundle_identifier.match(application_id) + # TODO: check provisioning expired teams[team] = plist['TeamName'] if teams[team].nil? result_profiles[team] = [] if result_profiles[team].nil? result_profiles[team].push(profile_path) diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb index 2fc7851..063dc55 100644 --- a/lib/deploygate/builds/ios/set_profile.rb +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -37,18 +37,27 @@ def app_id_create false end - # @return [String] + # @return [Array] def create_provisioning + prod_certs = Spaceship.certificate.production.all + distribution_cert_ids = prod_certs.map(&:id) + FileUtils.mkdir_p(OUTPUT_PATH) - values = { - :adhoc => @method == Export::AD_HOC ? true : false, - :app_identifier => @identifier, - :username => @username, - :output_path => OUTPUT_PATH - } - v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values) - Sigh.config = v - Sigh::Manager.start + provisionings = [] + distribution_cert_ids.each do |cert_id| + values = { + :adhoc => @method == Export::AD_HOC ? true : false, + :app_identifier => @identifier, + :username => @username, + :output_path => OUTPUT_PATH, + :cert_id => cert_id + } + v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values) + Sigh.config = v + provisionings.push(Sigh::Manager.start) + end + + provisionings end end end diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index a23451d..d20cf33 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -42,14 +42,20 @@ def ios(workspaces, options) if teams.empty? target_provisioning_profile = create_provisioning(identifier) elsif teams.count == 1 - target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first]) + target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first]) elsif teams.count >= 2 target_provisioning_profile = select_teams(teams, profiles) end method = DeployGate::Builds::Ios::Export.method(target_provisioning_profile) codesigning_identity = DeployGate::Builds::Ios::Export.codesigning_identity(target_provisioning_profile) - ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, codesigning_identity, method) + begin + ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, codesigning_identity, method) + rescue => e + # TODO: build error handling + raise e + end + Push.upload([ipa_path], options) end @@ -122,13 +128,13 @@ def create_provisioning(identifier) end begin - provisioning_profile_path = set_profile.create_provisioning + provisioning_profiles = set_profile.create_provisioning rescue => e DeployGate::Message::Error.print("Error: Failed create provisioning") raise e end - provisioning_profile_path + DeployGate::Builds::Ios::Export.select_profile(provisioning_profiles) end end end From 0efd64b05f2eea2804281dc19d2675e00e616ceb Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 18:47:17 +0900 Subject: [PATCH 27/45] fix test --- spec/deploygate/builds/ios_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/deploygate/builds/ios_spec.rb b/spec/deploygate/builds/ios_spec.rb index 92e8068..5838f76 100644 --- a/spec/deploygate/builds/ios_spec.rb +++ b/spec/deploygate/builds/ios_spec.rb @@ -21,7 +21,7 @@ def build_workspace allow(File).to receive(:expand_path).and_return('path') allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) - DeployGate::Builds::Ios.build(AnalyzeMock.new, '') + DeployGate::Builds::Ios.build(AnalyzeMock.new, '', '') expect(call_gym_manager).to be_truthy end @@ -33,7 +33,7 @@ def build_workspace allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new) expect { - DeployGate::Builds::Ios.build(AnalyzeMock.new, '', 'not support export method') + DeployGate::Builds::Ios.build(AnalyzeMock.new, '', '', 'not support export method') }.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError end end From bbd4dd62b0d9411964e655d54c65817105bcca2d Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 19:05:51 +0900 Subject: [PATCH 28/45] add apple developer center info --- lib/deploygate/commands/deploy/build.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index d20cf33..e37cf48 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -108,7 +108,10 @@ def select_teams(teams, profiles) # @param [String] identifier # @return [String] def create_provisioning(identifier) - print 'apple developer Username: ' + puts 'Please enter your email address that you are using in the Apple developer center.' + puts 'This information is managed by KeychainAccess.' + puts 'Docs: https://github.com/fastlane/credentials_manager' + print 'Email: ' username = STDIN.gets.chop begin From ecf11947da2cf6e75f22ed1ec960326960869e09 Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 19:58:43 +0900 Subject: [PATCH 29/45] bug fix --- lib/deploygate/builds/ios/analyze.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index 3f5550c..dfd2f7c 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -29,9 +29,13 @@ def schemes # @return [String] def target_bundle_identifier(scheme_name) project = Xcodeproj::Project.open(File.dirname(@scheme_workspace)) - target = project.targets.reject{|target| target.name != scheme_name}.first + target = project.native_targets.reject{|target| target.name != scheme_name}.first + product_name = target.product_name conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first - conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] + identifier = conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] + identifier.gsub!(/\$\(PRODUCT_NAME:.+\)/, product_name) + + identifier end private From b4002d7571761c09e72a39f370b0500c442c03f3 Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 20:11:29 +0900 Subject: [PATCH 30/45] add select team --- lib/deploygate/builds/ios/set_profile.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb index 063dc55..c035e32 100644 --- a/lib/deploygate/builds/ios/set_profile.rb +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -13,6 +13,7 @@ def initialize(username, identifier) @username = username @identifier = identifier Spaceship.login(username) + Spaceship.select_team if Spaceship.client.in_house? @method = Export::ENTERPRISE else @@ -50,7 +51,8 @@ def create_provisioning :app_identifier => @identifier, :username => @username, :output_path => OUTPUT_PATH, - :cert_id => cert_id + :cert_id => cert_id, + :team_id => Spaceship.client.team_id } v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values) Sigh.config = v From 34035a9993593ce80b5944623d772d11f5c05cd0 Mon Sep 17 00:00:00 2001 From: henteko Date: Tue, 27 Oct 2015 20:44:28 +0900 Subject: [PATCH 31/45] support enterprise --- lib/deploygate/builds/ios/export.rb | 6 +++++- lib/deploygate/builds/ios/set_profile.rb | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 9058a2b..d962ee8 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -52,7 +52,11 @@ def select_profile(profiles) # @return [String] def codesigning_identity(profile_path) plist = analyze_profile(profile_path) - "iPhone Distribution: #{plist['TeamName']} (#{plist['Entitlements']['com.apple.developer.team-identifier']})" + method = method(profile_path) + identity = "iPhone Distribution: #{plist['TeamName']}" + identity += " (#{plist['Entitlements']['com.apple.developer.team-identifier']})" if method == AD_HOC + + identity end # @param [String] profile_path diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb index c035e32..07b18b4 100644 --- a/lib/deploygate/builds/ios/set_profile.rb +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -40,7 +40,11 @@ def app_id_create # @return [Array] def create_provisioning - prod_certs = Spaceship.certificate.production.all + if @method == Export::AD_HOC + prod_certs = Spaceship.certificate.production.all + else + prod_certs = Spaceship.certificate.all.reject{|cert| cert.class != Spaceship::Portal::Certificate::InHouse} + end distribution_cert_ids = prod_certs.map(&:id) FileUtils.mkdir_p(OUTPUT_PATH) From dc3b33b2c9c5759d072822c6614ef1fff29618f8 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 00:43:54 +0900 Subject: [PATCH 32/45] delete select_scheme --- lib/deploygate/builds/ios/analyze.rb | 13 ++++------ lib/deploygate/commands/deploy/build.rb | 33 +++---------------------- 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index dfd2f7c..4b7628d 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -2,7 +2,7 @@ module DeployGate module Builds module Ios class Analyze - attr_reader :workspaces, :scheme_workspace, :build_workspace + attr_reader :workspaces, :scheme_workspace, :build_workspace, :scheme class NotLocalProvisioningProfileError < StandardError end @@ -16,20 +16,17 @@ def initialize(workspaces) @workspaces = workspaces @scheme_workspace = find_scheme_workspace(workspaces) @build_workspace = find_build_workspace(workspaces) - end - # @return [Array] - def schemes config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace}) project = FastlaneCore::Project.new(config) - project.schemes + project.select_scheme + @scheme = project.options[:scheme] end - # @param [String] scheme_name # @return [String] - def target_bundle_identifier(scheme_name) + def target_bundle_identifier project = Xcodeproj::Project.open(File.dirname(@scheme_workspace)) - target = project.native_targets.reject{|target| target.name != scheme_name}.first + target = project.native_targets.reject{|target| target.name != @scheme}.first product_name = target.product_name conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first identifier = conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index e37cf48..7370db7 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -25,15 +25,9 @@ def run(args, options) # @return [void] def ios(workspaces, options) analyze = DeployGate::Builds::Ios::Analyze.new(workspaces) - schemes = analyze.schemes - raise 'Scheme empty error' if schemes.empty? + target_scheme = analyze.scheme + identifier = analyze.target_bundle_identifier - target_shceme = schemes.first - if schemes.count > 1 - target_shceme = select_schemes(schemes) - end - - identifier = analyze.target_bundle_identifier(target_shceme) data = DeployGate::Builds::Ios::Export.find_local_data(identifier) profiles = data[:profiles] teams = data[:teams] @@ -50,7 +44,7 @@ def ios(workspaces, options) codesigning_identity = DeployGate::Builds::Ios::Export.codesigning_identity(target_provisioning_profile) begin - ipa_path = DeployGate::Builds::Ios.build(analyze, target_shceme, codesigning_identity, method) + ipa_path = DeployGate::Builds::Ios.build(analyze, target_scheme, codesigning_identity, method) rescue => e # TODO: build error handling raise e @@ -59,27 +53,6 @@ def ios(workspaces, options) Push.upload([ipa_path], options) end - # @param [Array] schemes - # @return [String] - def select_schemes(schemes) - result = nil - puts 'Select scheme:' - schemes.each_with_index do |scheme, index| - puts "#{index + 1}. #{scheme}" - end - print '? ' - select = STDIN.gets.chop - begin - result = schemes[Integer(select) - 1] - raise 'not select' if result.nil? - rescue => e - puts 'Please select scheme number' - return select_schemes(schemes) - end - - result - end - # @param [Hash] teams # @param [Hash] profiles # @return [String] From f8eb9ebc8e3740bf077b72751e114cf630ad1437 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 01:34:02 +0900 Subject: [PATCH 33/45] add find_xcschemes --- lib/deploygate/builds/ios/analyze.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index 4b7628d..0fbaf8a 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -16,6 +16,7 @@ def initialize(workspaces) @workspaces = workspaces @scheme_workspace = find_scheme_workspace(workspaces) @build_workspace = find_build_workspace(workspaces) + @xcodeproj = File.dirname(@scheme_workspace) config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace}) project = FastlaneCore::Project.new(config) @@ -25,8 +26,12 @@ def initialize(workspaces) # @return [String] def target_bundle_identifier - project = Xcodeproj::Project.open(File.dirname(@scheme_workspace)) - target = project.native_targets.reject{|target| target.name != @scheme}.first + scheme_file = find_xcschemes + xs = Xcodeproj::XCScheme.new(scheme_file) + target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name + + project = Xcodeproj::Project.open(@xcodeproj) + target = project.native_targets.reject{|target| target.name != target_name}.first product_name = target.product_name conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first identifier = conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] @@ -37,6 +42,17 @@ def target_bundle_identifier private + def find_xcschemes + shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme| + @scheme != File.basename(scheme, '.xcscheme') + end + user_schemes = Dir[File.join(@xcodeproj, 'xcuserdata', '*.xcuserdatad', 'xcschemes', '*.xcscheme')].reject do |scheme| + @scheme != File.basename(scheme, '.xcscheme') + end + + shared_schemes.concat(user_schemes).first + end + # @param [Array] workspaces # @return [String] def find_scheme_workspace(workspaces) From af24e9b9dc8df8c97b7f29def7ef2a3b2eff6f9c Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 03:28:58 +0900 Subject: [PATCH 34/45] add check local install certificate --- lib/deploygate/builds/ios/export.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index d962ee8..34f9cfc 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -21,7 +21,7 @@ def find_local_data(bundle_identifier) application_id = entities['application-identifier'] application_id.slice!(/^#{team}\./) application_id = '.' + application_id if application_id == '*' - if bundle_identifier.match(application_id) + if bundle_identifier.match(application_id) && installed_certificate?(profile_path) # TODO: check provisioning expired teams[team] = plist['TeamName'] if teams[team].nil? result_profiles[team] = [] if result_profiles[team].nil? @@ -36,6 +36,32 @@ def find_local_data(bundle_identifier) } end + # @param [String] profile_path + # @return [Boolean] + def installed_certificate?(profile_path) + plist = analyze_profile(profile_path) + certificate_str = plist['DeveloperCertificates'].first.read + certificate = OpenSSL::X509::Certificate.new certificate_str + id = OpenSSL::Digest::SHA1.new(certificate.to_der).to_s.upcase! + installed_identies.include?(id) + end + + # @return [Array] + def installed_identies + available = `security find-identity -v -p codesigning` + ids = [] + available.split("\n").each do |current| + next if current.include? "REVOKED" + begin + (ids << current.match(/.*\) (.*) \".*/)[1]) + rescue + # the last line does not match + end + end + + ids + end + # @param [Array] profiles # @return [String] def select_profile(profiles) From e0f7df31c6e7a681742cc47f89c413d5bbcee228 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 03:47:31 +0900 Subject: [PATCH 35/45] check local install certificate --- lib/deploygate/builds/ios/set_profile.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/builds/ios/set_profile.rb b/lib/deploygate/builds/ios/set_profile.rb index 07b18b4..cf457d1 100644 --- a/lib/deploygate/builds/ios/set_profile.rb +++ b/lib/deploygate/builds/ios/set_profile.rb @@ -5,6 +5,7 @@ class SetProfile attr_reader :method OUTPUT_PATH = '/tmp/dg/provisioning_profile/' + CERTIFICATE_OUTPUT_PATH = '/tmp/dg/certificate/' # @param [String] username # @param [String] identifier @@ -45,7 +46,17 @@ def create_provisioning else prod_certs = Spaceship.certificate.all.reject{|cert| cert.class != Spaceship::Portal::Certificate::InHouse} end - distribution_cert_ids = prod_certs.map(&:id) + + # check local install certificate + FileUtils.mkdir_p(CERTIFICATE_OUTPUT_PATH) + distribution_cert_ids = [] + prod_certs.each do |cert| + path = File.join(CERTIFICATE_OUTPUT_PATH, "#{cert.id}.cer") + raw_data = cert.download_raw + File.write(path, raw_data) + distribution_cert_ids.push(cert.id) if FastlaneCore::CertChecker.installed?(path) + end + raise 'Not local install certificate' if distribution_cert_ids.empty? FileUtils.mkdir_p(OUTPUT_PATH) provisionings = [] From 6f19a88f867a7306a7a701854a1c3b4fae5f4e30 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 11:37:46 +0900 Subject: [PATCH 36/45] if scheme_workspace schemes empty then use build_workspace --- lib/deploygate/builds/ios/analyze.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/deploygate/builds/ios/analyze.rb b/lib/deploygate/builds/ios/analyze.rb index 0fbaf8a..936fbcc 100644 --- a/lib/deploygate/builds/ios/analyze.rb +++ b/lib/deploygate/builds/ios/analyze.rb @@ -20,6 +20,10 @@ def initialize(workspaces) config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace}) project = FastlaneCore::Project.new(config) + if project.schemes.empty? + config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @build_workspace}) + project = FastlaneCore::Project.new(config) + end project.select_scheme @scheme = project.options[:scheme] end From e6fb35f5576ec727bf0ccc17b46d163217fd77d8 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 12:17:25 +0900 Subject: [PATCH 37/45] not found identifier error handling --- lib/deploygate/commands/deploy/build.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 7370db7..d4b5640 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -26,7 +26,14 @@ def run(args, options) def ios(workspaces, options) analyze = DeployGate::Builds::Ios::Analyze.new(workspaces) target_scheme = analyze.scheme - identifier = analyze.target_bundle_identifier + begin + identifier = analyze.target_bundle_identifier + rescue + # not found bundle identifier + puts 'Please input bundle identifier' + puts 'Example: com.example.ios' + identifier = input_bundle_identifier + end data = DeployGate::Builds::Ios::Export.find_local_data(identifier) profiles = data[:profiles] @@ -53,6 +60,18 @@ def ios(workspaces, options) Push.upload([ipa_path], options) end + def input_bundle_identifier + print 'bundle identifier: ' + identifier = STDIN.gets.chop + + if identifier == '' || identifier.nil? + puts 'You must input bundle identifier' + return input_bundle_identifier + end + + identifier + end + # @param [Hash] teams # @param [Hash] profiles # @return [String] From 51316ccfa0402967dd5771cd47f7877c2b73cf26 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 15:47:55 +0900 Subject: [PATCH 38/45] support provisining expired --- lib/deploygate/builds/ios/export.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/deploygate/builds/ios/export.rb b/lib/deploygate/builds/ios/export.rb index 34f9cfc..3ee5510 100644 --- a/lib/deploygate/builds/ios/export.rb +++ b/lib/deploygate/builds/ios/export.rb @@ -21,8 +21,10 @@ def find_local_data(bundle_identifier) application_id = entities['application-identifier'] application_id.slice!(/^#{team}\./) application_id = '.' + application_id if application_id == '*' - if bundle_identifier.match(application_id) && installed_certificate?(profile_path) - # TODO: check provisioning expired + if bundle_identifier.match(application_id) && + DateTime.now < plist['ExpirationDate'] && + installed_certificate?(profile_path) + teams[team] = plist['TeamName'] if teams[team].nil? result_profiles[team] = [] if result_profiles[team].nil? result_profiles[team].push(profile_path) From afb04c210247943311149ed0533ea23aa5afc4eb Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:00:12 +0900 Subject: [PATCH 39/45] add open github issue --- deploygate.gemspec | 2 ++ lib/deploygate.rb | 2 ++ lib/deploygate/command_builder.rb | 38 ++++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/deploygate.gemspec b/deploygate.gemspec index 6fd1151..5156720 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -30,6 +30,8 @@ POST_INSTALL_MESSAGE spec.add_dependency 'color_echo', '~> 2.0.1' spec.add_dependency 'plist', '~> 3.1.0' spec.add_dependency 'xcodeproj', '~> 0.28.2' + spec.add_dependency 'github_issue_request', '~> 0.0.2' + spec.add_dependency 'highline', '~> 1.7.8' # ios build spec.add_dependency 'gym', '~> 1.0.0' diff --git a/lib/deploygate.rb b/lib/deploygate.rb index 21f716a..82bbed6 100644 --- a/lib/deploygate.rb +++ b/lib/deploygate.rb @@ -7,6 +7,8 @@ require "openssl" require "plist" require "find" +require "github_issue_request" +require "highline" # ios build require "gym" diff --git a/lib/deploygate/command_builder.rb b/lib/deploygate/command_builder.rb index 85cac8c..ec934f8 100644 --- a/lib/deploygate/command_builder.rb +++ b/lib/deploygate/command_builder.rb @@ -4,6 +4,8 @@ class CommandBuilder attr_reader :arguments def run + GithubIssueRequest::Url.config('deploygate', 'deploygate-cli') + program :name, 'dg' program :version, VERSION program :description, 'You can control to DeployGate in your terminal.' @@ -12,7 +14,12 @@ def run c.syntax = 'dg init' c.description = 'project initial command' c.action do |args, options| - Commands::Init.run + begin + Commands::Init.run + rescue => e + error_handling("Commands::Init Error: #{e.class}", e.message, ['bug', 'Init']) + raise e + end end end @@ -25,7 +32,12 @@ def run c.option '--disable_notify', 'disable notify via email (iOS app only)' c.action do |args, options| options.default :message => '', :user => nil, :open => false, 'disable_notify' => false - Commands::Deploy.run(args, options) + begin + Commands::Deploy.run(args, options) + rescue => e + error_handling("Commands::Deploy Error: #{e.class}", e.message, ['bug', 'Deploy']) + raise e + end end end alias_command :'push', :deploy @@ -34,11 +46,31 @@ def run c.syntax = 'dg logout' c.description = 'logout' c.action do |args, options| - Commands::Logout.run + begin + Commands::Logout.run + rescue => e + error_handling("Commands::Logout Error: #{e.class}", e.message, ['bug', 'Logout']) + raise e + end end end run! end + + def error_handling(title, body, labels) + options = { + :title => title, + :body => body, + :labels => labels + } + url = GithubIssueRequest::Url.new(options).to_s + puts '' + if HighLine.agree('Do you want to report this issue on GitHub? (y/n)') {|q| q.default = "n"} + puts "Please open github issue: #{url}" + system('open', url) if Commands::Deploy::Push.openable? + end + puts '' + end end end From ea555ebc3f4ba4b0c3566ce1e76c59a64d5dc772 Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:28:21 +0900 Subject: [PATCH 40/45] fix apple developer center credentials input message --- lib/deploygate/commands/deploy/build.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index d4b5640..99493ff 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -100,9 +100,17 @@ def select_teams(teams, profiles) # @param [String] identifier # @return [String] def create_provisioning(identifier) - puts 'Please enter your email address that you are using in the Apple developer center.' - puts 'This information is managed by KeychainAccess.' - puts 'Docs: https://github.com/fastlane/credentials_manager' + puts < Date: Wed, 28 Oct 2015 19:29:29 +0900 Subject: [PATCH 41/45] HighLine agree one line --- lib/deploygate/command_builder.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deploygate/command_builder.rb b/lib/deploygate/command_builder.rb index ec934f8..62643ba 100644 --- a/lib/deploygate/command_builder.rb +++ b/lib/deploygate/command_builder.rb @@ -66,7 +66,7 @@ def error_handling(title, body, labels) } url = GithubIssueRequest::Url.new(options).to_s puts '' - if HighLine.agree('Do you want to report this issue on GitHub? (y/n)') {|q| q.default = "n"} + if HighLine.agree('Do you want to report this issue on GitHub? (y/n) ') {|q| q.default = "n"} puts "Please open github issue: #{url}" system('open', url) if Commands::Deploy::Push.openable? end From c1f5027350de21dcba1050b41e717256e757c9ad Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:32:23 +0900 Subject: [PATCH 42/45] fix error wording --- lib/deploygate/commands/deploy/build.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/deploygate/commands/deploy/build.rb b/lib/deploygate/commands/deploy/build.rb index 99493ff..2c6df19 100644 --- a/lib/deploygate/commands/deploy/build.rb +++ b/lib/deploygate/commands/deploy/build.rb @@ -117,23 +117,23 @@ def create_provisioning(identifier) begin set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier) rescue => e - DeployGate::Message::Error.print("Error: Please login try again") + DeployGate::Message::Error.print("Error: Please try login again") raise e end begin if set_profile.app_id_create - puts "Create #{identifier} app id" + puts "App ID #{identifier} was created" end rescue => e - DeployGate::Message::Error.print("Error: App id create error") + DeployGate::Message::Error.print("Error: Failed to create App ID") raise e end begin provisioning_profiles = set_profile.create_provisioning rescue => e - DeployGate::Message::Error.print("Error: Failed create provisioning") + DeployGate::Message::Error.print("Error: Failed to create provisioning profile") raise e end From 22d3f221ace8913f1013a9e46307372323c0ddfd Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:35:23 +0900 Subject: [PATCH 43/45] add error label version --- lib/deploygate/command_builder.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deploygate/command_builder.rb b/lib/deploygate/command_builder.rb index 62643ba..0ab6405 100644 --- a/lib/deploygate/command_builder.rb +++ b/lib/deploygate/command_builder.rb @@ -62,7 +62,7 @@ def error_handling(title, body, labels) options = { :title => title, :body => body, - :labels => labels + :labels => labels.push("v#{DeployGate::VERSION}") } url = GithubIssueRequest::Url.new(options).to_s puts '' From 79ad367bab49484da5fa608aec92bc8b449d4f3d Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:35:52 +0900 Subject: [PATCH 44/45] ver up 0.0.2 --- lib/deploygate/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deploygate/version.rb b/lib/deploygate/version.rb index c0950c6..54b6a83 100644 --- a/lib/deploygate/version.rb +++ b/lib/deploygate/version.rb @@ -1,3 +1,3 @@ module DeployGate - VERSION = "0.0.1" + VERSION = "0.0.2" end From 76066d1e091005a75d6608536649f14bc316ad7a Mon Sep 17 00:00:00 2001 From: henteko Date: Wed, 28 Oct 2015 19:40:46 +0900 Subject: [PATCH 45/45] update README --- README.md | 9 ++++++++- deploygate.gemspec | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 352b506..3256fbb 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,19 @@ $ gem install deploygate ``` ## Usage -Upload an application: + +### Upload apps ``` $ dg deploy [package file path] ``` +### iOS build and upload + +``` +$ dg deploy [ios project path] +``` + ## License Copyright (C) 2015 DeployGate All rights reserved. diff --git a/deploygate.gemspec b/deploygate.gemspec index 5156720..bdbb466 100644 --- a/deploygate.gemspec +++ b/deploygate.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |spec| dg installed! To get started fast: - $ dg deploy [app_file_path] + $ dg deploy Or see the docs at: