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.
- checksums.yaml +13 -5
- data/.gitignore +4 -0
- data/.travis.yml +4 -4
- data/README.md +3 -3
- data/lib/deploygate/android/gradle_deploy.rb +95 -0
- data/lib/deploygate/android/gradle_plugin_installer.rb +101 -0
- data/lib/deploygate/android/gradle_project.rb +14 -0
- data/lib/deploygate/commands/deploy/build.rb +15 -154
- data/lib/deploygate/{build.rb → project.rb} +3 -3
- data/lib/deploygate/version.rb +1 -1
- data/lib/deploygate/xcode/analyze.rb +116 -0
- data/lib/deploygate/xcode/export.rb +281 -0
- data/lib/deploygate/{builds → xcode}/ios.rb +13 -5
- data/lib/deploygate/xcode/member_center.rb +52 -0
- data/lib/deploygate/xcode/member_centers/app.rb +35 -0
- data/lib/deploygate/xcode/member_centers/provisioning_profile.rb +99 -0
- data/lib/deploygate.rb +14 -5
- data/spec/deploygate/project_spec.rb +39 -0
- data/spec/deploygate/xcode/analyze_spec.rb +3 -0
- data/spec/deploygate/{builds/ios → xcode}/export_spec.rb +21 -21
- data/spec/deploygate/{builds → xcode}/ios_spec.rb +12 -12
- data/spec/deploygate/xcode/member_center_spec.rb +21 -0
- data/spec/deploygate/xcode/member_centers/app_spec.rb +60 -0
- data/spec/deploygate/xcode/member_centers/provisioning_profile_spec.rb +3 -0
- metadata +70 -66
- data/lib/deploygate/builds/ios/analyze.rb +0 -111
- data/lib/deploygate/builds/ios/export.rb +0 -188
- data/lib/deploygate/builds/ios/set_profile.rb +0 -128
- data/spec/deploygate/build_spec.rb +0 -37
- data/spec/deploygate/builds/ios/analyze_spec.rb +0 -3
- data/spec/deploygate/builds/ios/set_profile_spec.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjgxYTY1MzAxYWExNTlhMTJhNDdkMTZlZTQwMjcxNWZhYTIyYWY1Nw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Mjc2MjA3YzZjZDJhMWJhYzVmYmIzNGFjYmUxMWIxYzk0YjQyZTYyOQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NDUwM2Y0NjYxOGZhOTQ3NjRjOWYwNTBjOTM5ZDJlN2I3YzE4Y2E2MmRkZjg5
|
10
|
+
MGQyMGJjYjJhYmI1NDZjNWE4OTM0ZWYyNDQ4NmJiZjRhNmM5NTBkNGZkNTAz
|
11
|
+
NzYzMTdiMmEyMTAyMDJkMmVkOWQ5ZDRjZjJmM2RiZDQwNWM2NmE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MmYxMTUwMzYwZmY1NzFjZTNjYzYzODJlMTg4NjZjZTRhYTgyZjBhYmQ0YzIx
|
14
|
+
YTVmMDNkZGExNjA1OGFhZjA3M2ZkYTBhZjhjNTM2Y2ZlNjc0MjQ2MjIwOGIz
|
15
|
+
YmJhNWQ5MThmMjg4ZmE0OTYyZTJjZWE3YzU0YjY5NjZiNzhkNmY=
|
data/.gitignore
CHANGED
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:
|
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:
|
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 [
|
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 [
|
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
|
@@ -11,14 +11,12 @@ module DeployGate
|
|
11
11
|
# android/ios build
|
12
12
|
work_dir = args.first
|
13
13
|
|
14
|
-
if DeployGate::
|
15
|
-
|
16
|
-
|
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::
|
20
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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 =
|
48
|
-
|
49
|
-
|
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
|
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::
|
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
|
-
|
14
|
+
DeployGate::Android::GradleProject.root_dir?(path)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/deploygate/version.rb
CHANGED
@@ -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
|