deploygate 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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