deploygate 0.0.6 → 0.1.0

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.
Files changed (31) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +4 -0
  3. data/.travis.yml +4 -4
  4. data/README.md +3 -3
  5. data/lib/deploygate/android/gradle_deploy.rb +95 -0
  6. data/lib/deploygate/android/gradle_plugin_installer.rb +101 -0
  7. data/lib/deploygate/android/gradle_project.rb +14 -0
  8. data/lib/deploygate/commands/deploy/build.rb +15 -154
  9. data/lib/deploygate/{build.rb → project.rb} +3 -3
  10. data/lib/deploygate/version.rb +1 -1
  11. data/lib/deploygate/xcode/analyze.rb +116 -0
  12. data/lib/deploygate/xcode/export.rb +281 -0
  13. data/lib/deploygate/{builds → xcode}/ios.rb +13 -5
  14. data/lib/deploygate/xcode/member_center.rb +52 -0
  15. data/lib/deploygate/xcode/member_centers/app.rb +35 -0
  16. data/lib/deploygate/xcode/member_centers/provisioning_profile.rb +99 -0
  17. data/lib/deploygate.rb +14 -5
  18. data/spec/deploygate/project_spec.rb +39 -0
  19. data/spec/deploygate/xcode/analyze_spec.rb +3 -0
  20. data/spec/deploygate/{builds/ios → xcode}/export_spec.rb +21 -21
  21. data/spec/deploygate/{builds → xcode}/ios_spec.rb +12 -12
  22. data/spec/deploygate/xcode/member_center_spec.rb +21 -0
  23. data/spec/deploygate/xcode/member_centers/app_spec.rb +60 -0
  24. data/spec/deploygate/xcode/member_centers/provisioning_profile_spec.rb +3 -0
  25. metadata +70 -66
  26. data/lib/deploygate/builds/ios/analyze.rb +0 -111
  27. data/lib/deploygate/builds/ios/export.rb +0 -188
  28. data/lib/deploygate/builds/ios/set_profile.rb +0 -128
  29. data/spec/deploygate/build_spec.rb +0 -37
  30. data/spec/deploygate/builds/ios/analyze_spec.rb +0 -3
  31. data/spec/deploygate/builds/ios/set_profile_spec.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9d1564cd1f5e82528502eb8a2289415866047edc
4
- data.tar.gz: 39bda05af733c6793dbb4c8f7090aea7db8a573d
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjgxYTY1MzAxYWExNTlhMTJhNDdkMTZlZTQwMjcxNWZhYTIyYWY1Nw==
5
+ data.tar.gz: !binary |-
6
+ Mjc2MjA3YzZjZDJhMWJhYzVmYmIzNGFjYmUxMWIxYzk0YjQyZTYyOQ==
5
7
  SHA512:
6
- metadata.gz: a935a3bfc0a63a7a1d02c58b7bc2d7ffb6c9d335353b020776fe6c68359d7e4d76e4023acbc36abbeee6c2910a6b793aac5351256b060b86555a628789e210ee
7
- data.tar.gz: 0a2cf62fe44fe62608e21e0e8efd2a18638620017f6cc946fa9e8a582eac08a96fbb0f15e435b7208255bbb4e855e95c2b091628e1bbef879baecd7a1a8a3f91
8
+ metadata.gz: !binary |-
9
+ NDUwM2Y0NjYxOGZhOTQ3NjRjOWYwNTBjOTM5ZDJlN2I3YzE4Y2E2MmRkZjg5
10
+ MGQyMGJjYjJhYmI1NDZjNWE4OTM0ZWYyNDQ4NmJiZjRhNmM5NTBkNGZkNTAz
11
+ NzYzMTdiMmEyMTAyMDJkMmVkOWQ5ZDRjZjJmM2RiZDQwNWM2NmE=
12
+ data.tar.gz: !binary |-
13
+ MmYxMTUwMzYwZmY1NzFjZTNjYzYzODJlMTg4NjZjZTRhYTgyZjBhYmQ0YzIx
14
+ YTVmMDNkZGExNjA1OGFhZjA3M2ZkYTBhZjhjNTM2Y2ZlNjc0MjQ2MjIwOGIz
15
+ YmJhNWQ5MThmMjg4ZmE0OTYyZTJjZWE3YzU0YjY5NjZiNzhkNmY=
data/.gitignore CHANGED
@@ -22,3 +22,7 @@ deploygate-cli.iml
22
22
 
23
23
  # test file
24
24
  spec/test_files/.dg
25
+
26
+ # binary files
27
+ *.app.dSYM.zip
28
+ *.ipa
data/.travis.yml CHANGED
@@ -1,15 +1,15 @@
1
1
  language: ruby
2
- rvm:
3
- - 2.0.0
4
2
  env:
5
3
  global:
6
- secure: IpGM1CW5bsn8DGgcKGMf5jmlJMMVYVZ3c55d8MpGALgxbBHu2GLdOpA/msG1Ura1jR7sNZkrn1SlwQZ2Quo311RPb3UpgPQOlzphVPd6PzYbrNSccEeiD5cemm+J4zUUc6vSFLVwfDE4lV8Ge4Zbt+TclgBgJ4mw42/YB7N/Dmg=
4
+ secure: gGY+C54Cfp082o5Oaf6tZqzfOlXsWSMcVNvTpoOgMfJGsHo//d9t/si9Bn1pFaFyjJedW+IcC0pt+FcKVCDgnsUaL0Y0HT/ZsGkV8k7vv9F5nbHOde4nk189Sr2HtHR3wdr7KaMh2/DialisnqllxgzxA/wRLfHKsjqRsjWUw/VWL5E7Z734mzpTGE2mVJNRj02/cs0Y/izZgdi6wrt4lEZfxE3jS+QkJZHMjGNfcwvH26whU6oX1PiJ4o5xl0Rr8Q8xav3wbtTCcOJNPSeMkkiH5sSXuqrjI6kgwvjlByKhyg2Ws0GvZLxAfTml+Vo5po1uWsohdZJaJcEhd4GsGfbMZWCFuBP2mCE+gVmkkMeJxRKnWoi6NotgPmqG1JWlzGngDB/hJ4wuuh+swa0KJvZGiMEJ5P3GNydCybEPOsk1Ww+lUkXRHxD+/LW03EkxMd5LA3He/nYXz3pWCYA6qcFgrYMmq+3ozjSaQr+1d/Iu14Awv5+cwCltPfl5bERDno0jc0TdSs/7qplAL/efpjBsP7DkGE5r521gg8mIiXx509jU08i9S60SXiw0RBnYyjE5SzlsiOqaFdJxVygDGcDIAA/GTefLHO9i3SinZHFS6jr3Xi/vpOIc7Jz4W2Jmuqv+CJP4gspPoAxdWOE/QipTt0Jv4kCMf7dJwd9jaRc=
5
+ rvm:
6
+ - 2.0.0
7
7
  script:
8
8
  - bundle exec rake
9
9
  deploy:
10
10
  provider: rubygems
11
11
  api_key:
12
- secure: GMEt+VCHGTvSIx/Z6iCTXE3eAbtNt6WB5Qr8AgMDOLjhuDcKCeGm6QEzcmBljnrtZmJhU1BIapzez5tS40H8wy/aRPknSsAOU+kt+BUIMfoQIv0KlVtWxI45R61+bytOfnrGqqLZKVC9mi/nI+qyHkLYuBa3FTEe9u4iyF8Ul/E=
12
+ secure: sy649ijrSPFvCtR7cg/Hy2I7iY3WQxROyyw3hjoOU5wFxjNYh+DoDXmZiMmdRSNjO2GQIbeuX5sPhgHTleIlOl0c8QtYxwiky6O9WnT3lwOkxtnhI1H+sQCJxWV9Ur99GtYCzosfOgqvoiXqOIllI/mNzhO4Vru3Nc+E9pM1aM9jU9TIulDxOCSyteXvX+23DaiW8CNicFWEGhT4rSdDGqKbmZTjDKP2SanEthUp1N0AqZR9ACvqGCz7Q/5cXjoUFz89uBaNwyp3UrYhfP1niVgR3dp8ev23RbMUGsmVz8WVMOkrBbA2nSBF+fRsxuj5YO+J0knQY32sXpNH06jvJ8GvnbOwWD6wm7q4h1UOjvb29PamtRF4lSfxhZb848eHtipkNyuqCfWaeCrlpn5b49poBPZ1FTOC8C6o1LbFPAJwchttj5fcVReNVsa8+xt6TO6p/vti0WMptVUUHU5xSxG7t3FzRF1WTM09oSNnmfyI/rOQv1qgOP2RmNaJQl9iRCbyCTgU8kpL8BR2vswntxILj5Q9zl2M83zGo7mYB8EjvbPjWqVURzvww5Jl5BSJfiIgeLBq/cjb7h/oqvRqgolkfqwaudagRUY+Fgtlmic15gjs8aA9OfzShBigf5We/aZRaXLWjtOwJ5+GKsBbmi73mkyTn0cMFbTpDv3RVNE=
13
13
  gem: deploygate
14
14
  on:
15
15
  tags: true
data/README.md CHANGED
@@ -31,13 +31,13 @@ $ gem install deploygate
31
31
  ### Upload apps
32
32
 
33
33
  ```
34
- $ dg deploy [package file path]
34
+ $ dg deploy [apk/ipa file path]
35
35
  ```
36
36
 
37
- ### iOS build and upload
37
+ ### Android/iOS build and upload
38
38
 
39
39
  ```
40
- $ dg deploy [ios project path]
40
+ $ dg deploy [Android/iOS project path]
41
41
  ```
42
42
 
43
43
  ## License
@@ -0,0 +1,95 @@
1
+ module DeployGate
2
+ module Android
3
+ class GradleDeploy
4
+
5
+ GRADLE_DEPLOY_USER_NAME_ENV = 'DEPLOYGATE_USER_NAME'
6
+ GRADLE_DEPLOY_MESSAGE_ENV = 'DEPLOYGATE_MESSAGE'
7
+ GRADLE_DEPLOY_DISTRIBUTION_KEY_ENV = 'DEPLOYGATE_DISTRIBUTION_KEY'
8
+
9
+ def initialize (dir, options)
10
+ @dir = dir
11
+ @cli = HighLine.new
12
+
13
+ GradleProject.root_dir?(@dir) or raise "#{@dir} is not the root directory of Android project"
14
+ Dir.chdir(@dir) or raise "Cannot chdir to #{@dir}"
15
+ @gradle = find_gradle_executable or raise 'Gradle executable not found.'
16
+ @deploy_env = env(options)
17
+ end
18
+
19
+ def deploy
20
+ print 'Looking for DeployGate tasks...'
21
+ tasks = get_deploygate_tasks
22
+ puts
23
+
24
+ task = case tasks.size
25
+ when 0
26
+ install_plugin and return deploy
27
+ when 1
28
+ tasks[0]
29
+ else
30
+ choose(tasks)
31
+ end
32
+
33
+ run_task task unless task.nil?
34
+ end
35
+
36
+ private
37
+
38
+ def find_gradle_executable
39
+ if File.exist?('gradlew')
40
+ './gradlew'
41
+ else
42
+ cmd = %x(which gradle)
43
+ !cmd.empty? and cmd
44
+ end
45
+ end
46
+
47
+ def install_plugin
48
+ if @cli.agree("<%= color('Looks like Gradle DeployGate plugin isn\\'t available on your project.', BOLD) %> Install? ") {|q| q.default = 'y'}
49
+ GradlePluginInstaller.new.install
50
+ end
51
+ end
52
+
53
+ def choose(tasks)
54
+ @cli.choose do |menu|
55
+ menu.prompt = 'Please choose a task to run: '
56
+ menu.choices(*tasks) do |task|
57
+ return task
58
+ end
59
+ end
60
+ end
61
+
62
+ def run_task(task)
63
+ command = "#{@deploy_env} #{@gradle} #{task}"
64
+ @cli.say "Running <%= color(\"#{command}\", BOLD) %>"
65
+ system command
66
+ end
67
+
68
+ def get_deploygate_tasks
69
+ %x(#{@gradle} -q --configure-on-demand tasks --all).
70
+ split(/\n/).
71
+ grep(/uploadDeployGate(?!.*signingConfig).+$/).
72
+ map { |line| line.split(/\s/, 2).first }.
73
+ sort
74
+ end
75
+
76
+ # @param [Hash] options
77
+ # @return [String]
78
+ def env(options)
79
+ result = ''
80
+
81
+ owner = options.user
82
+ message = options.message
83
+ distribution_key = options.distribution_key
84
+ open = options.open
85
+
86
+ result += "#{GRADLE_DEPLOY_USER_NAME_ENV}=#{owner} " if owner
87
+ result += "#{GRADLE_DEPLOY_MESSAGE_ENV}=#{message} " if message != nil && message != ''
88
+ result += "#{GRADLE_DEPLOY_DISTRIBUTION_KEY_ENV}=#{distribution_key} " if distribution_key
89
+ puts @cli.color('Not supported browser open', HighLine::YELLOW) if open
90
+
91
+ result
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,101 @@
1
+ module DeployGate
2
+ module Android
3
+ class GradlePluginInstaller
4
+ MAVEN_METADATA_URL = 'https://repo1.maven.org/maven2/com/deploygate/gradle/maven-metadata.xml'
5
+
6
+ def initialize
7
+ @cli = HighLine.new
8
+ end
9
+
10
+ def install
11
+ patch = create_patch
12
+ print_diff patch
13
+ if @cli.agree("<%= color('These lines will be added to activate the plugin.', BOLD) %> Apply changes? ") {|q| q.default = 'y'}
14
+ apply patch
15
+ end
16
+ end
17
+
18
+ def create_patch
19
+ create_root_patch + create_projects_patch
20
+ end
21
+
22
+ def create_root_patch
23
+ make_diff 'build.gradle',
24
+ /classpath\s*['"]com\.android\.tools\.build:gradle:/,
25
+ "classpath 'com.deploygate:gradle:#{recent_plugin_version}'"
26
+ end
27
+
28
+ def recent_plugin_version
29
+ @plugin_version ||= fetch_recent_plugin_version
30
+ end
31
+
32
+ def fetch_recent_plugin_version
33
+ open(MAVEN_METADATA_URL) do |io|
34
+ REXML::Document.new(io).elements['metadata/versioning/release'].text
35
+ end
36
+ end
37
+
38
+ def create_projects_patch
39
+ files = find_project_scripts
40
+ files.map do |file|
41
+ make_diff file,
42
+ /apply plugin:\s*["'](android|com\.android\.application)["']/,
43
+ "apply plugin: 'deploygate'"
44
+ end.join "\n"
45
+ end
46
+
47
+ def find_project_scripts
48
+ %x(grep -REl --include build.gradle "apply plugin:[ ]*[\\"'](android|com.android.application)[\\"']" .).
49
+ split(/\n/)
50
+ end
51
+
52
+ def make_diff(file, match, insert)
53
+ tmpfile = Tempfile.open(%w(build .gradle))
54
+ File.readlines(file).each do |line|
55
+ tmpfile.print line
56
+ if (md = line.match(match))
57
+ tmpfile.puts "#{' '*md.begin(0)}#{insert}"
58
+ end
59
+ end
60
+ tmpfile.close
61
+ %x(diff -u "#{file}" "#{tmpfile.path}")
62
+ end
63
+
64
+ def print_diff(patch)
65
+ puts
66
+ patch.each_line do |line|
67
+ line.chomp!
68
+ if line.match(/^(\+\+\+|---) /)
69
+ puts @cli.color(line, HighLine::BOLD)
70
+ elsif line.match(/^@@.+@@$/)
71
+ puts @cli.color(line, HighLine::CYAN)
72
+ elsif line.match(/^\+/)
73
+ puts @cli.color(line, HighLine::GREEN)
74
+ elsif line.match(/^\-/)
75
+ puts @cli.color(line, HighLine::RED)
76
+ else
77
+ puts line
78
+ end
79
+ end
80
+ puts
81
+ end
82
+
83
+ def apply(patch)
84
+ Open3.popen3('patch -p0') do |stdin, stdout, stderr, wait_thr|
85
+ stdin.puts patch
86
+ stdin.close_write
87
+ out = stdout.read
88
+ error = stderr.read
89
+ if !error.empty?
90
+ print out
91
+ print @cli.color(error, HighLine::RED)
92
+ false
93
+ else
94
+ print @cli.color(out, HighLine::GREEN)
95
+ true
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,14 @@
1
+ module DeployGate
2
+ module Android
3
+ class GradleProject
4
+ class << self
5
+
6
+ # @param [String] dir
7
+ # @return [Boolean]
8
+ def root_dir?(dir)
9
+ File.exists? File.join(dir, 'settings.gradle')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -11,14 +11,12 @@ module DeployGate
11
11
  # android/ios build
12
12
  work_dir = args.first
13
13
 
14
- if DeployGate::Build.ios?(work_dir)
15
- check_local_certificates()
16
- root_path = DeployGate::Builds::Ios.project_root_path(work_dir)
17
- workspaces = DeployGate::Builds::Ios.find_workspaces(root_path)
14
+ if DeployGate::Project.ios?(work_dir)
15
+ root_path = DeployGate::Xcode::Ios.project_root_path(work_dir)
16
+ workspaces = DeployGate::Xcode::Ios.find_workspaces(root_path)
18
17
  ios(workspaces, options)
19
- elsif DeployGate::Build.android?(work_dir)
20
- # TODO: support android build
21
- print_no_target
18
+ elsif DeployGate::Project.android?(work_dir)
19
+ DeployGate::Android::GradleDeploy.new(work_dir, options).deploy
22
20
  else
23
21
  print_no_target
24
22
  end
@@ -28,167 +26,30 @@ module DeployGate
28
26
  # @param [Hash] options
29
27
  # @return [void]
30
28
  def ios(workspaces, options)
31
- analyze = DeployGate::Builds::Ios::Analyze.new(workspaces)
32
- target_scheme = analyze.scheme
33
- begin
34
- identifier = analyze.target_bundle_identifier
35
- rescue
36
- # not found bundle identifier
37
- puts 'Please input bundle identifier'
38
- puts 'Example: com.example.ios'
39
- identifier = input_bundle_identifier
40
- end
41
- uuid = analyze.target_xcode_setting_provisioning_profile_uuid
29
+ DeployGate::Xcode::Export.check_local_certificates
42
30
 
43
- data = DeployGate::Builds::Ios::Export.find_local_data(identifier, uuid)
44
- profiles = data[:profiles]
45
- teams = data[:teams]
31
+ analyze = DeployGate::Xcode::Analyze.new(workspaces)
32
+ target_scheme = analyze.scheme
33
+ bundle_identifier = analyze.target_bundle_identifier
34
+ xcode_provisioning_profile_uuid = analyze.target_xcode_setting_provisioning_profile_uuid
46
35
 
47
- target_provisioning_profile = nil
48
- if teams.empty?
49
- target_provisioning_profile = create_provisioning(identifier, uuid)
50
- elsif teams.count == 1
51
- target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first])
52
- elsif teams.count >= 2
53
- target_provisioning_profile = select_teams(teams, profiles)
54
- end
55
- method = DeployGate::Builds::Ios::Export.method(target_provisioning_profile)
56
- codesigning_identity = DeployGate::Builds::Ios::Export.codesigning_identity(target_provisioning_profile)
57
-
58
- begin
59
- ipa_path = DeployGate::Builds::Ios.build(analyze, target_scheme, codesigning_identity, method)
60
- rescue => e
61
- # TODO: build error handling
62
- use_xcode_path = `xcode-select -p`
63
- DeployGate::Message::Error.print("Current Xcode used to build: #{use_xcode_path} (via xcode-select)")
64
- raise e
65
- end
36
+ target_provisioning_profile = DeployGate::Xcode::Export.provisioning_profile(bundle_identifier, xcode_provisioning_profile_uuid)
37
+ method = DeployGate::Xcode::Export.method(target_provisioning_profile)
38
+ codesigning_identity = DeployGate::Xcode::Export.codesigning_identity(target_provisioning_profile)
66
39
 
40
+ ipa_path = DeployGate::Xcode::Ios.build(analyze, target_scheme, codesigning_identity, method)
67
41
  Push.upload([ipa_path], options)
68
42
  end
69
43
 
70
- def input_bundle_identifier
71
- print 'bundle identifier: '
72
- identifier = STDIN.gets.chop
73
-
74
- if identifier == '' || identifier.nil?
75
- puts 'You must input bundle identifier'
76
- return input_bundle_identifier
77
- end
78
-
79
- identifier
80
- end
81
-
82
- # @param [Hash] teams
83
- # @param [Hash] profiles
84
- # @return [String]
85
- def select_teams(teams, profiles)
86
- result = nil
87
- puts 'Select team:'
88
- teams.each_with_index do |team, index|
89
- puts "#{index + 1}. #{team[1]} (#{team[0]})"
90
- end
91
- print '? '
92
- select = STDIN.gets.chop
93
- begin
94
- team = teams.keys[Integer(select) - 1]
95
- team_profiles = profiles[team].first
96
- raise 'not select' if team_profiles.nil?
97
-
98
- result = DeployGate::Builds::Ios::Export.select_profile(profiles[team])
99
- rescue => e
100
- puts 'Please select team number'
101
- return select_teams(teams, profiles)
102
- end
103
-
104
- result
105
- end
106
-
107
- # @param [String] identifier
108
- # @param [String] uuid
109
- # @return [String]
110
- def create_provisioning(identifier, uuid)
111
- puts <<EOF
112
-
113
- No suitable provisioning profile found to export the app.
114
-
115
- Please enter your email and password for Apple Developer Center
116
- to set up/download provisioning profile automatically so you can
117
- export the app without any extra steps.
118
-
119
- Note: Your password will be stored to Keychain and never be sent to DeployGate.
120
-
121
- EOF
122
- print 'Email: '
123
- username = STDIN.gets.chop
124
-
125
- begin
126
- set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier)
127
- rescue => e
128
- DeployGate::Message::Error.print("Error: Please try login again")
129
- raise e
130
- end
131
-
132
- begin
133
- if set_profile.app_id_create
134
- puts "App ID #{identifier} was created"
135
- end
136
- rescue => e
137
- DeployGate::Message::Error.print("Error: Failed to create App ID")
138
- raise e
139
- end
140
-
141
- begin
142
- provisioning_profiles = set_profile.create_provisioning(uuid)
143
- rescue => e
144
- DeployGate::Message::Error.print("Error: Failed to create provisioning profile")
145
- raise e
146
- end
147
-
148
- DeployGate::Builds::Ios::Export.select_profile(provisioning_profiles)
149
- end
150
-
151
44
  def print_no_target
152
45
  message = <<EOF
153
46
 
154
47
  No deploy target found.
155
- Please run on the root directory of iOS project or specify .apk/.ipa file to deploy.
48
+ Please run on the root directory of Android/iOS project or specify .apk/.ipa file to deploy.
156
49
 
157
50
  EOF
158
51
  DeployGate::Message::Warning.print(message)
159
52
  end
160
-
161
- def check_local_certificates
162
- if DeployGate::Builds::Ios::Export.installed_distribution_certificate_ids.count == 0
163
- # not local install certificate
164
- DeployGate::Message::Error.print("Error: Not local install distribution certificate")
165
- puts <<EOF
166
-
167
- Not local install iPhone Distribution certificates.
168
- Please install certificate.
169
-
170
- Docs: https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html
171
-
172
- EOF
173
- exit
174
- end
175
-
176
- conflicting_certificates = DeployGate::Builds::Ios::Export.installed_distribution_conflicting_certificates
177
- if conflicting_certificates.count > 0
178
- DeployGate::Message::Error.print("Error: Conflicting local install certificates")
179
- puts <<EOF
180
-
181
- Conflicting local install certificates.
182
- Please uninstall certificates.
183
- EOF
184
- conflicting_certificates.each do |certificate|
185
- puts certificate
186
- end
187
- puts ""
188
-
189
- exit
190
- end
191
- end
192
53
  end
193
54
  end
194
55
  end
@@ -1,17 +1,17 @@
1
1
  module DeployGate
2
- class Build
2
+ class Project
3
3
  class << self
4
4
 
5
5
  # @param [String] path
6
6
  # @return [Boolean]
7
7
  def ios?(path)
8
- DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || DeployGate::Builds::Ios.ios_root?(path)
8
+ DeployGate::Xcode::Ios.workspace?(path) || DeployGate::Xcode::Ios.project?(path) || DeployGate::Xcode::Ios.ios_root?(path)
9
9
  end
10
10
 
11
11
  # @param [String] path
12
12
  # @return [Boolean]
13
13
  def android?(path)
14
- false # TODO: support android build
14
+ DeployGate::Android::GradleProject.root_dir?(path)
15
15
  end
16
16
  end
17
17
  end
@@ -1,3 +1,3 @@
1
1
  module DeployGate
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,116 @@
1
+ module DeployGate
2
+ module Xcode
3
+ class Analyze
4
+ attr_reader :workspaces, :scheme_workspace, :build_workspace, :scheme
5
+
6
+ class NotLocalProvisioningProfileError < StandardError
7
+ end
8
+
9
+ BASE_WORK_DIR_NAME = 'project.xcworkspace'
10
+ BUILD_CONFIGRATION = 'Release'
11
+
12
+ # @param [Array] workspaces
13
+ # @return [DeployGate::Xcode::Analyze]
14
+ def initialize(workspaces)
15
+ @workspaces = workspaces
16
+ @scheme_workspace = find_scheme_workspace(workspaces)
17
+ @build_workspace = find_build_workspace(workspaces)
18
+ @xcodeproj = File.dirname(@scheme_workspace)
19
+
20
+ config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace})
21
+ project = FastlaneCore::Project.new(config)
22
+ if project.schemes.empty?
23
+ config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @build_workspace})
24
+ project = FastlaneCore::Project.new(config)
25
+ end
26
+ project.select_scheme
27
+ @scheme = project.options[:scheme]
28
+ end
29
+
30
+ # Support Xcode7 more
31
+ # @return [String]
32
+ def target_bundle_identifier
33
+ begin
34
+ product_name = target_product_name
35
+ identifier = target_build_configration.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
36
+ identifier.gsub!(/\$\(PRODUCT_NAME:.+\)/, product_name)
37
+ rescue
38
+ cli = HighLine.new
39
+ cli.say('Please input bundle identifier')
40
+ cli.say('Example: com.example.ios')
41
+ identifier = cli.ask('Enter your bundle identifier: ') { |q| q.validate = /^(\w+)\.(\w+).*\w$/ }
42
+ end
43
+
44
+ identifier
45
+ end
46
+
47
+ # @return [String]
48
+ def target_xcode_setting_provisioning_profile_uuid
49
+ uuid = target_build_configration.build_settings['PROVISIONING_PROFILE']
50
+ UUID.validate(uuid) ? uuid : nil
51
+ end
52
+
53
+ private
54
+
55
+ def target_build_configration
56
+ target_project_setting.build_configuration_list.build_configurations.reject{|conf| conf.name != BUILD_CONFIGRATION}.first
57
+ end
58
+
59
+ def target_product_name
60
+ target_project_setting.product_name
61
+ end
62
+
63
+ def target_project_setting
64
+ scheme_file = find_xcschemes
65
+ xs = Xcodeproj::XCScheme.new(scheme_file)
66
+ target_name = xs.profile_action.buildable_product_runnable.buildable_reference.target_name
67
+
68
+ project = Xcodeproj::Project.open(@xcodeproj)
69
+ project.native_targets.reject{|target| target.name != target_name}.first
70
+ end
71
+
72
+ def find_xcschemes
73
+ shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme|
74
+ @scheme != File.basename(scheme, '.xcscheme')
75
+ end
76
+ user_schemes = Dir[File.join(@xcodeproj, 'xcuserdata', '*.xcuserdatad', 'xcschemes', '*.xcscheme')].reject do |scheme|
77
+ @scheme != File.basename(scheme, '.xcscheme')
78
+ end
79
+
80
+ shared_schemes.concat(user_schemes).first
81
+ end
82
+
83
+ # @param [Array] workspaces
84
+ # @return [String]
85
+ def find_scheme_workspace(workspaces)
86
+ return nil if workspaces.empty?
87
+ return workspaces.first if workspaces.count == 1
88
+
89
+ select = nil
90
+ workspaces.each do |workspace|
91
+ if BASE_WORK_DIR_NAME == File.basename(workspace)
92
+ select = workspace
93
+ end
94
+ end
95
+
96
+ select
97
+ end
98
+
99
+ # @param [Array] workspaces
100
+ # @return [String]
101
+ def find_build_workspace(workspaces)
102
+ return nil if workspaces.empty?
103
+ return workspaces.first if workspaces.count == 1
104
+
105
+ select = nil
106
+ workspaces.each do |workspace|
107
+ if BASE_WORK_DIR_NAME != File.basename(workspace)
108
+ select = workspace
109
+ end
110
+ end
111
+
112
+ select
113
+ end
114
+ end
115
+ end
116
+ end