deploygate 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 425bc06e86baa217dc4261b4c11f68649be3db03
4
- data.tar.gz: fd3b686f1d21df377ce9d0649edff68789df5622
3
+ metadata.gz: 7c7a9d3a21ab949bc31c5c7193684a256bf72515
4
+ data.tar.gz: a373351cda7d9ea2a43aa1bbb56aa7760c1d7a0c
5
5
  SHA512:
6
- metadata.gz: c35ebded8826cbabc698c7ddb2c7522c1d20bdf3be3134975db1851c84fc3546d480c9b5f3689c0eb418a93001ee6b45ab80c28c1fc2f971a708f395e9656a7f
7
- data.tar.gz: 9cd0682d323368b3bed67439271894e69295dea387a0e26701c5d303a593cb36b82b906832303b4d5171847c339473c3a7f4ab2a212f900579ef29eb06cc6cd2
6
+ metadata.gz: 810651a47faf6673824a467c50ec396983e227d2394edd286f1fb967c58f6e76f653fb764caead90b094f71545cfc9bb2f9687383cfe29e3623a958d5e3872f3
7
+ data.tar.gz: d45e2210454cea075b77415f7a6bf8be863667bfcbd4bda275c5e9eb2cb1b05b57e12d38db91cfb2e5a855dd2b911625928ac44700775c387fdc4b105ccd1a92
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # deploygate-cli
2
+ [![Gem Version](https://badge.fury.io/rb/deploygate.svg)](https://badge.fury.io/rb/deploygate)
2
3
  [![Build Status](https://travis-ci.org/DeployGate/deploygate-cli.svg?branch=master)](https://travis-ci.org/DeployGate/deploygate-cli)
3
4
 
4
5
  ## This is a beta version
data/deploygate.gemspec CHANGED
@@ -32,6 +32,7 @@ POST_INSTALL_MESSAGE
32
32
  spec.add_dependency 'xcodeproj', '~> 0.28.2'
33
33
  spec.add_dependency 'github_issue_request', '~> 0.0.2'
34
34
  spec.add_dependency 'highline', '~> 1.7.8'
35
+ spec.add_dependency 'uuid', '~> 2.3.8'
35
36
 
36
37
  # ios build
37
38
  spec.add_dependency 'gym', '~> 1.0.0'
@@ -30,22 +30,38 @@ module DeployGate
30
30
 
31
31
  # @return [String]
32
32
  def target_bundle_identifier
33
- scheme_file = find_xcschemes
34
- xs = Xcodeproj::XCScheme.new(scheme_file)
35
- target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name
36
-
37
- project = Xcodeproj::Project.open(@xcodeproj)
38
- target = project.native_targets.reject{|target| target.name != target_name}.first
39
- product_name = target.product_name
40
- conf = target.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first
41
- identifier = conf.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
33
+ product_name = target_product_name
34
+ identifier = target_build_configration.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
42
35
  identifier.gsub!(/\$\(PRODUCT_NAME:.+\)/, product_name)
43
36
 
44
37
  identifier
45
38
  end
46
39
 
40
+ # @return [String]
41
+ def target_xcode_setting_provisioning_profile_uuid
42
+ uuid = target_build_configration.build_settings['PROVISIONING_PROFILE']
43
+ UUID.validate(uuid) ? uuid : nil
44
+ end
45
+
47
46
  private
48
47
 
48
+ def target_build_configration
49
+ target_project_setting.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first
50
+ end
51
+
52
+ def target_product_name
53
+ target_project_setting.product_name
54
+ end
55
+
56
+ def target_project_setting
57
+ scheme_file = find_xcschemes
58
+ xs = Xcodeproj::XCScheme.new(scheme_file)
59
+ target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name
60
+
61
+ project = Xcodeproj::Project.open(@xcodeproj)
62
+ project.native_targets.reject{|target| target.name != target_name}.first
63
+ end
64
+
49
65
  def find_xcschemes
50
66
  shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme|
51
67
  @scheme != File.basename(scheme, '.xcscheme')
@@ -9,25 +9,29 @@ module DeployGate
9
9
 
10
10
  class << self
11
11
  # @param [String] bundle_identifier
12
+ # @param [String] uuid
12
13
  # @return [Hash]
13
- def find_local_data(bundle_identifier)
14
+ def find_local_data(bundle_identifier, uuid = nil)
14
15
  result_profiles = {}
15
16
  teams = {}
16
- profiles.each do |profile_path|
17
- plist = analyze_profile(profile_path)
18
- entities = plist['Entitlements']
17
+ profile_paths = load_profile_paths
18
+ profiles = profile_paths.map{|p| profile_to_plist(p)}
19
+ profiles.reject! {|profile| profile['UUID'] != uuid} unless uuid.nil?
20
+
21
+ profiles.each do |profile|
22
+ entities = profile['Entitlements']
19
23
  unless entities['get-task-allow']
20
24
  team = entities['com.apple.developer.team-identifier']
21
25
  application_id = entities['application-identifier']
22
26
  application_id.slice!(/^#{team}\./)
23
27
  application_id = '.' + application_id if application_id == '*'
24
28
  if bundle_identifier.match(application_id) &&
25
- DateTime.now < plist['ExpirationDate'] &&
26
- installed_certificate?(profile_path)
29
+ DateTime.now < profile['ExpirationDate'] &&
30
+ installed_certificate?(profile['Path'])
27
31
 
28
- teams[team] = plist['TeamName'] if teams[team].nil?
32
+ teams[team] = profile['TeamName'] if teams[team].nil?
29
33
  result_profiles[team] = [] if result_profiles[team].nil?
30
- result_profiles[team].push(profile_path)
34
+ result_profiles[team].push(profile['Path'])
31
35
  end
32
36
  end
33
37
  end
@@ -41,11 +45,14 @@ module DeployGate
41
45
  # @param [String] profile_path
42
46
  # @return [Boolean]
43
47
  def installed_certificate?(profile_path)
44
- plist = analyze_profile(profile_path)
45
- certificate_str = plist['DeveloperCertificates'].first.read
46
- certificate = OpenSSL::X509::Certificate.new certificate_str
47
- id = OpenSSL::Digest::SHA1.new(certificate.to_der).to_s.upcase!
48
- installed_identies.include?(id)
48
+ profile = profile_to_plist(profile_path)
49
+ certs = profile['DeveloperCertificates'].map do |cert|
50
+ certificate_str = cert.read
51
+ certificate = OpenSSL::X509::Certificate.new certificate_str
52
+ id = OpenSSL::Digest::SHA1.new(certificate.to_der).to_s.upcase!
53
+ installed_identies.include?(id)
54
+ end
55
+ certs.include?(true)
49
56
  end
50
57
 
51
58
  # @return [Array]
@@ -64,14 +71,14 @@ module DeployGate
64
71
  ids
65
72
  end
66
73
 
67
- # @param [Array] profiles
74
+ # @param [Array] profile_paths
68
75
  # @return [String]
69
- def select_profile(profiles)
76
+ def select_profile(profile_paths)
70
77
  select = nil
71
78
 
72
- profiles.each do |profile|
73
- select = profile if adhoc?(profile) && select.nil?
74
- select = profile if inhouse?(profile)
79
+ profile_paths.each do |path|
80
+ select = path if adhoc?(path) && select.nil?
81
+ select = path if inhouse?(path)
75
82
  end
76
83
  select
77
84
  end
@@ -79,10 +86,24 @@ module DeployGate
79
86
  # @param [String] profile_path
80
87
  # @return [String]
81
88
  def codesigning_identity(profile_path)
82
- plist = analyze_profile(profile_path)
83
- method = method(profile_path)
84
- identity = "iPhone Distribution: #{plist['TeamName']}"
85
- identity += " (#{plist['Entitlements']['com.apple.developer.team-identifier']})" if method == AD_HOC
89
+ profile = profile_to_plist(profile_path)
90
+ identity = nil
91
+
92
+ profile['DeveloperCertificates'].each do |cert|
93
+ certificate_str = cert.read
94
+ certificate = OpenSSL::X509::Certificate.new certificate_str
95
+ id = OpenSSL::Digest::SHA1.new(certificate.to_der).to_s.upcase!
96
+
97
+ available = `security find-identity -v -p codesigning`
98
+ available.split("\n").each do |current|
99
+ next if current.include? "REVOKED"
100
+ begin
101
+ search = current.match(/.*\) (.*) \"(.*)\"/)
102
+ identity = search[2] if id == search[1]
103
+ rescue
104
+ end
105
+ end
106
+ end
86
107
 
87
108
  identity
88
109
  end
@@ -96,46 +117,32 @@ module DeployGate
96
117
  # @param [String] profile_path
97
118
  # @return [Boolean]
98
119
  def adhoc?(profile_path)
99
- plist = analyze_profile(profile_path)
100
- !plist['Entitlements']['get-task-allow'] && plist['ProvisionsAllDevices'].nil?
120
+ profile = profile_to_plist(profile_path)
121
+ !profile['Entitlements']['get-task-allow'] && profile['ProvisionsAllDevices'].nil?
101
122
  end
102
123
 
103
124
  # @param [String] profile_path
104
125
  # @return [Boolean]
105
126
  def inhouse?(profile_path)
106
- plist = analyze_profile(profile_path)
107
- !plist['Entitlements']['get-task-allow'] && !plist['ProvisionsAllDevices'].nil?
127
+ profile = profile_to_plist(profile_path)
128
+ !profile['Entitlements']['get-task-allow'] && !profile['ProvisionsAllDevices'].nil?
129
+ end
130
+
131
+ def load_profile_paths
132
+ profiles_path = File.expand_path("~") + "/Library/MobileDevice/Provisioning Profiles/*.mobileprovision"
133
+ Dir[profiles_path]
108
134
  end
109
135
 
110
136
  # @param [String] profile_path
111
137
  # @return [Hash]
112
- def analyze_profile(profile_path)
113
- plist = nil
138
+ def profile_to_plist(profile_path)
114
139
  File.open(profile_path) do |profile|
115
140
  asn1 = OpenSSL::ASN1.decode(profile.read)
116
141
  plist_str = asn1.value[1].value[0].value[2].value[1].value[0].value
117
142
  plist = Plist.parse_xml plist_str.force_encoding('UTF-8')
143
+ plist['Path'] = profile_path
144
+ return plist
118
145
  end
119
- plist
120
- end
121
-
122
- # @return [Array]
123
- def profiles
124
- profiles = []
125
- Find.find(profile_dir_path) do |path|
126
- next if path == profile_dir_path
127
- Find.prune if FileTest.directory?(path)
128
- if File.extname(path) == PROFILE_EXTNAME
129
- profiles.push(path)
130
- end
131
- end
132
-
133
- profiles
134
- end
135
-
136
- # @return [String]
137
- def profile_dir_path
138
- File.join(ENV['HOME'], 'Library/MobileDevice/Provisioning Profiles')
139
146
  end
140
147
  end
141
148
  end
@@ -39,8 +39,54 @@ module DeployGate
39
39
  false
40
40
  end
41
41
 
42
+ # @param [String] uuid
42
43
  # @return [Array]
43
- def create_provisioning
44
+ def create_provisioning(uuid)
45
+ FileUtils.mkdir_p(OUTPUT_PATH)
46
+
47
+ if uuid.nil?
48
+ return install_provisioning
49
+ else
50
+ return select_uuid_provisioning(uuid)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def select_uuid_provisioning(uuid)
57
+ adhoc_profiles = Spaceship.provisioning_profile.ad_hoc.all
58
+ inhouse_profiles = Spaceship.provisioning_profile.in_house.all
59
+
60
+ adhoc_profiles.reject!{|p| p.uuid != uuid}
61
+ inhouse_profiles.reject!{|p| p.uuid != uuid}
62
+ select_profile = nil
63
+ method = nil
64
+ unless adhoc_profiles.empty?
65
+ select_profile = adhoc_profiles.first
66
+ method = Export::AD_HOC
67
+ end
68
+ unless inhouse_profiles.empty?
69
+ select_profile = inhouse_profiles.first
70
+ method = Export::ENTERPRISE
71
+ end
72
+ raise 'Not Xcode selected Provisioning Profile' if select_profile.nil?
73
+
74
+ values = {
75
+ :adhoc => method == Export::AD_HOC ? true : false,
76
+ :app_identifier => @identifier,
77
+ :username => @username,
78
+ :output_path => OUTPUT_PATH,
79
+ :provisioning_name => select_profile.name,
80
+ :team_id => Spaceship.client.team_id
81
+ }
82
+ v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values)
83
+ Sigh.config = v
84
+ download_profile_path = Sigh::Manager.start
85
+
86
+ [download_profile_path]
87
+ end
88
+
89
+ def install_provisioning
44
90
  if @method == Export::AD_HOC
45
91
  prod_certs = Spaceship.certificate.production.all
46
92
  else
@@ -58,7 +104,6 @@ module DeployGate
58
104
  end
59
105
  raise 'Not local install certificate' if distribution_cert_ids.empty?
60
106
 
61
- FileUtils.mkdir_p(OUTPUT_PATH)
62
107
  provisionings = []
63
108
  distribution_cert_ids.each do |cert_id|
64
109
  values = {
@@ -71,7 +116,8 @@ module DeployGate
71
116
  }
72
117
  v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values)
73
118
  Sigh.config = v
74
- provisionings.push(Sigh::Manager.start)
119
+ download_profile_path = Sigh::Manager.start
120
+ provisionings.push(download_profile_path)
75
121
  end
76
122
 
77
123
  provisionings
@@ -17,7 +17,7 @@ module DeployGate
17
17
  begin
18
18
  Commands::Init.run
19
19
  rescue => e
20
- error_handling("Commands::Init Error: #{e.class}", e.message, ['bug', 'Init'])
20
+ error_handling("Commands::Init Error: #{e.class}", create_error_issue_body(e), ['bug', 'Init'])
21
21
  raise e
22
22
  end
23
23
  end
@@ -35,7 +35,7 @@ module DeployGate
35
35
  begin
36
36
  Commands::Deploy.run(args, options)
37
37
  rescue => e
38
- error_handling("Commands::Deploy Error: #{e.class}", e.message, ['bug', 'Deploy'])
38
+ error_handling("Commands::Deploy Error: #{e.class}", create_error_issue_body(e), ['bug', 'Deploy'])
39
39
  raise e
40
40
  end
41
41
  end
@@ -49,7 +49,7 @@ module DeployGate
49
49
  begin
50
50
  Commands::Logout.run
51
51
  rescue => e
52
- error_handling("Commands::Logout Error: #{e.class}", e.message, ['bug', 'Logout'])
52
+ error_handling("Commands::Logout Error: #{e.class}", create_error_issue_body(e), ['bug', 'Logout'])
53
53
  raise e
54
54
  end
55
55
  end
@@ -58,6 +58,23 @@ module DeployGate
58
58
  run!
59
59
  end
60
60
 
61
+ # @param [Exception] error
62
+ # @return [String]
63
+ def create_error_issue_body(error)
64
+ return <<EOF
65
+ # Error message
66
+ #{error.message}
67
+
68
+ # Backtrace
69
+ ```
70
+ #{error.backtrace.join("\n")}
71
+ ```
72
+ EOF
73
+ end
74
+
75
+ # @param [String] title
76
+ # @param [String] body
77
+ # @param [Array] labels
61
78
  def error_handling(title, body, labels)
62
79
  options = {
63
80
  :title => title,
@@ -34,14 +34,15 @@ module DeployGate
34
34
  puts 'Example: com.example.ios'
35
35
  identifier = input_bundle_identifier
36
36
  end
37
+ uuid = analyze.target_xcode_setting_provisioning_profile_uuid
37
38
 
38
- data = DeployGate::Builds::Ios::Export.find_local_data(identifier)
39
+ data = DeployGate::Builds::Ios::Export.find_local_data(identifier, uuid)
39
40
  profiles = data[:profiles]
40
41
  teams = data[:teams]
41
42
 
42
43
  target_provisioning_profile = nil
43
44
  if teams.empty?
44
- target_provisioning_profile = create_provisioning(identifier)
45
+ target_provisioning_profile = create_provisioning(identifier, uuid)
45
46
  elsif teams.count == 1
46
47
  target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first])
47
48
  elsif teams.count >= 2
@@ -98,8 +99,9 @@ module DeployGate
98
99
  end
99
100
 
100
101
  # @param [String] identifier
102
+ # @param [String] uuid
101
103
  # @return [String]
102
- def create_provisioning(identifier)
104
+ def create_provisioning(identifier, uuid)
103
105
  puts <<EOF
104
106
 
105
107
  No suitable provisioning profile found to export the app.
@@ -131,7 +133,7 @@ EOF
131
133
  end
132
134
 
133
135
  begin
134
- provisioning_profiles = set_profile.create_provisioning
136
+ provisioning_profiles = set_profile.create_provisioning(uuid)
135
137
  rescue => e
136
138
  DeployGate::Message::Error.print("Error: Failed to create provisioning profile")
137
139
  raise e
@@ -1,3 +1,3 @@
1
1
  module DeployGate
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/deploygate.rb CHANGED
@@ -9,6 +9,7 @@ require "plist"
9
9
  require "find"
10
10
  require "github_issue_request"
11
11
  require "highline"
12
+ require "uuid"
12
13
 
13
14
  # ios build
14
15
  require "gym"
@@ -1,58 +1,58 @@
1
1
  describe DeployGate::Builds::Ios::Export do
2
2
  describe "#adhoc?" do
3
3
  it "when adhoc plist" do
4
- plist = {
4
+ profile = {
5
5
  'ProvisionsAllDevices' => nil,
6
6
  'Entitlements' => {'get-task-allow' => false}
7
7
  }
8
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
8
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
9
9
  expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_truthy
10
10
  end
11
11
 
12
12
  it "when inhouse plist" do
13
- plist = {
13
+ profile = {
14
14
  'ProvisionsAllDevices' => true,
15
15
  'Entitlements' => {'get-task-allow' => false}
16
16
  }
17
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
17
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
18
18
  expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey
19
19
  end
20
20
 
21
21
  it "when not distribution plist" do
22
- plist = {
22
+ profile = {
23
23
  'ProvisionsAllDevices' => nil,
24
24
  'Entitlements' => {'get-task-allow' => true}
25
25
  }
26
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
26
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
27
27
  expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey
28
28
  end
29
29
  end
30
30
 
31
31
  describe "#inhouse?" do
32
32
  it "when adhoc plist" do
33
- plist = {
33
+ profile = {
34
34
  'ProvisionsAllDevices' => nil,
35
35
  'Entitlements' => {'get-task-allow' => false}
36
36
  }
37
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
37
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
38
38
  expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey
39
39
  end
40
40
 
41
41
  it "when inhouse plist" do
42
- plist = {
42
+ profile = {
43
43
  'ProvisionsAllDevices' => true,
44
44
  'Entitlements' => {'get-task-allow' => false}
45
45
  }
46
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
46
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
47
47
  expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_truthy
48
48
  end
49
49
 
50
50
  it "when not distribution plist" do
51
- plist = {
51
+ profile = {
52
52
  'ProvisionsAllDevices' => nil,
53
53
  'Entitlements' => {'get-task-allow' => true}
54
54
  }
55
- allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
55
+ allow(DeployGate::Builds::Ios::Export).to receive(:profile_to_plist).and_return(profile)
56
56
  expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey
57
57
  end
58
58
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deploygate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - deploygate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-28 00:00:00.000000000 Z
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 1.7.8
125
+ - !ruby/object:Gem::Dependency
126
+ name: uuid
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.3.8
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.3.8
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: gym
127
141
  requirement: !ruby/object:Gem::Requirement