deploygate 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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