deploygate 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +9 -1
- data/deploygate.gemspec +10 -1
- data/lib/deploygate/build.rb +18 -0
- data/lib/deploygate/builds/ios/analyze.rb +94 -0
- data/lib/deploygate/builds/ios/export.rb +144 -0
- data/lib/deploygate/builds/ios/set_profile.rb +82 -0
- data/lib/deploygate/builds/ios.rb +81 -0
- data/lib/deploygate/command_builder.rb +35 -3
- data/lib/deploygate/commands/deploy/build.rb +146 -0
- data/lib/deploygate/commands/deploy.rb +11 -1
- data/lib/deploygate/version.rb +1 -1
- data/lib/deploygate.rb +17 -0
- data/spec/deploygate/api/v1/push_spec.rb +1 -2
- data/spec/deploygate/build_spec.rb +37 -0
- data/spec/deploygate/builds/ios/analyze_spec.rb +3 -0
- data/spec/deploygate/builds/ios/export_spec.rb +59 -0
- data/spec/deploygate/builds/ios/set_profile_spec.rb +3 -0
- data/spec/deploygate/builds/ios_spec.rb +95 -0
- metadata +117 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 425bc06e86baa217dc4261b4c11f68649be3db03
|
4
|
+
data.tar.gz: fd3b686f1d21df377ce9d0649edff68789df5622
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c35ebded8826cbabc698c7ddb2c7522c1d20bdf3be3134975db1851c84fc3546d480c9b5f3689c0eb418a93001ee6b45ab80c28c1fc2f971a708f395e9656a7f
|
7
|
+
data.tar.gz: 9cd0682d323368b3bed67439271894e69295dea387a0e26701c5d303a593cb36b82b906832303b4d5171847c339473c3a7f4ab2a212f900579ef29eb06cc6cd2
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# deploygate-cli
|
2
|
+
[](https://travis-ci.org/DeployGate/deploygate-cli)
|
2
3
|
|
3
4
|
## This is a beta version
|
4
5
|
|
@@ -25,12 +26,19 @@ $ gem install deploygate
|
|
25
26
|
```
|
26
27
|
|
27
28
|
## Usage
|
28
|
-
|
29
|
+
|
30
|
+
### Upload apps
|
29
31
|
|
30
32
|
```
|
31
33
|
$ dg deploy [package file path]
|
32
34
|
```
|
33
35
|
|
36
|
+
### iOS build and upload
|
37
|
+
|
38
|
+
```
|
39
|
+
$ dg deploy [ios project path]
|
40
|
+
```
|
41
|
+
|
34
42
|
## License
|
35
43
|
|
36
44
|
Copyright (C) 2015 DeployGate All rights reserved.
|
data/deploygate.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
dg installed! To get started fast:
|
18
18
|
|
19
|
-
$ dg deploy
|
19
|
+
$ dg deploy
|
20
20
|
|
21
21
|
Or see the docs at:
|
22
22
|
|
@@ -28,6 +28,15 @@ POST_INSTALL_MESSAGE
|
|
28
28
|
spec.add_dependency 'httpclient', '~> 2.2.5'
|
29
29
|
spec.add_dependency 'commander', '~> 4.3.5'
|
30
30
|
spec.add_dependency 'color_echo', '~> 2.0.1'
|
31
|
+
spec.add_dependency 'plist', '~> 3.1.0'
|
32
|
+
spec.add_dependency 'xcodeproj', '~> 0.28.2'
|
33
|
+
spec.add_dependency 'github_issue_request', '~> 0.0.2'
|
34
|
+
spec.add_dependency 'highline', '~> 1.7.8'
|
35
|
+
|
36
|
+
# ios build
|
37
|
+
spec.add_dependency 'gym', '~> 1.0.0'
|
38
|
+
spec.add_dependency 'spaceship', '~> 0.12.3'
|
39
|
+
spec.add_dependency 'sigh', '~> 1.1.0'
|
31
40
|
|
32
41
|
spec.add_development_dependency "bundler", "~> 1.3"
|
33
42
|
spec.add_development_dependency "rake"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module DeployGate
|
2
|
+
class Build
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# @param [String] path
|
6
|
+
# @return [Boolean]
|
7
|
+
def ios?(path)
|
8
|
+
DeployGate::Builds::Ios.workspace?(path) || DeployGate::Builds::Ios.project?(path) || DeployGate::Builds::Ios.ios_root?(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [String] path
|
12
|
+
# @return [Boolean]
|
13
|
+
def android?(path)
|
14
|
+
false # TODO: support android build
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Builds
|
3
|
+
module Ios
|
4
|
+
class Analyze
|
5
|
+
attr_reader :workspaces, :scheme_workspace, :build_workspace, :scheme
|
6
|
+
|
7
|
+
class NotLocalProvisioningProfileError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
BASE_WORK_DIR_NAME = 'project.xcworkspace'
|
11
|
+
BUILD_CONFIGRATION = 'Release'
|
12
|
+
|
13
|
+
# @param [Array] workspaces
|
14
|
+
# @return [DeployGate::Builds::Ios::Analyze]
|
15
|
+
def initialize(workspaces)
|
16
|
+
@workspaces = workspaces
|
17
|
+
@scheme_workspace = find_scheme_workspace(workspaces)
|
18
|
+
@build_workspace = find_build_workspace(workspaces)
|
19
|
+
@xcodeproj = File.dirname(@scheme_workspace)
|
20
|
+
|
21
|
+
config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @scheme_workspace})
|
22
|
+
project = FastlaneCore::Project.new(config)
|
23
|
+
if project.schemes.empty?
|
24
|
+
config = FastlaneCore::Configuration.create(Gym::Options.available_options, {:workspace => @build_workspace})
|
25
|
+
project = FastlaneCore::Project.new(config)
|
26
|
+
end
|
27
|
+
project.select_scheme
|
28
|
+
@scheme = project.options[:scheme]
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String]
|
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']
|
42
|
+
identifier.gsub!(/\$\(PRODUCT_NAME:.+\)/, product_name)
|
43
|
+
|
44
|
+
identifier
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def find_xcschemes
|
50
|
+
shared_schemes = Dir[File.join(@xcodeproj, 'xcshareddata', 'xcschemes', '*.xcscheme')].reject do |scheme|
|
51
|
+
@scheme != File.basename(scheme, '.xcscheme')
|
52
|
+
end
|
53
|
+
user_schemes = Dir[File.join(@xcodeproj, 'xcuserdata', '*.xcuserdatad', 'xcschemes', '*.xcscheme')].reject do |scheme|
|
54
|
+
@scheme != File.basename(scheme, '.xcscheme')
|
55
|
+
end
|
56
|
+
|
57
|
+
shared_schemes.concat(user_schemes).first
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param [Array] workspaces
|
61
|
+
# @return [String]
|
62
|
+
def find_scheme_workspace(workspaces)
|
63
|
+
return nil if workspaces.empty?
|
64
|
+
return workspaces.first if workspaces.count == 1
|
65
|
+
|
66
|
+
select = nil
|
67
|
+
workspaces.each do |workspace|
|
68
|
+
if BASE_WORK_DIR_NAME == File.basename(workspace)
|
69
|
+
select = workspace
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
select
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param [Array] workspaces
|
77
|
+
# @return [String]
|
78
|
+
def find_build_workspace(workspaces)
|
79
|
+
return nil if workspaces.empty?
|
80
|
+
return workspaces.first if workspaces.count == 1
|
81
|
+
|
82
|
+
select = nil
|
83
|
+
workspaces.each do |workspace|
|
84
|
+
if BASE_WORK_DIR_NAME != File.basename(workspace)
|
85
|
+
select = workspace
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
select
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Builds
|
3
|
+
module Ios
|
4
|
+
class Export
|
5
|
+
AD_HOC = 'ad-hoc'
|
6
|
+
ENTERPRISE = 'enterprise'
|
7
|
+
SUPPORT_EXPORT_METHOD = [AD_HOC, ENTERPRISE]
|
8
|
+
PROFILE_EXTNAME = '.mobileprovision'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @param [String] bundle_identifier
|
12
|
+
# @return [Hash]
|
13
|
+
def find_local_data(bundle_identifier)
|
14
|
+
result_profiles = {}
|
15
|
+
teams = {}
|
16
|
+
profiles.each do |profile_path|
|
17
|
+
plist = analyze_profile(profile_path)
|
18
|
+
entities = plist['Entitlements']
|
19
|
+
unless entities['get-task-allow']
|
20
|
+
team = entities['com.apple.developer.team-identifier']
|
21
|
+
application_id = entities['application-identifier']
|
22
|
+
application_id.slice!(/^#{team}\./)
|
23
|
+
application_id = '.' + application_id if application_id == '*'
|
24
|
+
if bundle_identifier.match(application_id) &&
|
25
|
+
DateTime.now < plist['ExpirationDate'] &&
|
26
|
+
installed_certificate?(profile_path)
|
27
|
+
|
28
|
+
teams[team] = plist['TeamName'] if teams[team].nil?
|
29
|
+
result_profiles[team] = [] if result_profiles[team].nil?
|
30
|
+
result_profiles[team].push(profile_path)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
{
|
36
|
+
:teams => teams,
|
37
|
+
:profiles => result_profiles
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] profile_path
|
42
|
+
# @return [Boolean]
|
43
|
+
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)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Array]
|
52
|
+
def installed_identies
|
53
|
+
available = `security find-identity -v -p codesigning`
|
54
|
+
ids = []
|
55
|
+
available.split("\n").each do |current|
|
56
|
+
next if current.include? "REVOKED"
|
57
|
+
begin
|
58
|
+
(ids << current.match(/.*\) (.*) \".*/)[1])
|
59
|
+
rescue
|
60
|
+
# the last line does not match
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ids
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [Array] profiles
|
68
|
+
# @return [String]
|
69
|
+
def select_profile(profiles)
|
70
|
+
select = nil
|
71
|
+
|
72
|
+
profiles.each do |profile|
|
73
|
+
select = profile if adhoc?(profile) && select.nil?
|
74
|
+
select = profile if inhouse?(profile)
|
75
|
+
end
|
76
|
+
select
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param [String] profile_path
|
80
|
+
# @return [String]
|
81
|
+
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
|
86
|
+
|
87
|
+
identity
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param [String] profile_path
|
91
|
+
# @return [String]
|
92
|
+
def method(profile_path)
|
93
|
+
adhoc?(profile_path) ? AD_HOC : ENTERPRISE
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param [String] profile_path
|
97
|
+
# @return [Boolean]
|
98
|
+
def adhoc?(profile_path)
|
99
|
+
plist = analyze_profile(profile_path)
|
100
|
+
!plist['Entitlements']['get-task-allow'] && plist['ProvisionsAllDevices'].nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param [String] profile_path
|
104
|
+
# @return [Boolean]
|
105
|
+
def inhouse?(profile_path)
|
106
|
+
plist = analyze_profile(profile_path)
|
107
|
+
!plist['Entitlements']['get-task-allow'] && !plist['ProvisionsAllDevices'].nil?
|
108
|
+
end
|
109
|
+
|
110
|
+
# @param [String] profile_path
|
111
|
+
# @return [Hash]
|
112
|
+
def analyze_profile(profile_path)
|
113
|
+
plist = nil
|
114
|
+
File.open(profile_path) do |profile|
|
115
|
+
asn1 = OpenSSL::ASN1.decode(profile.read)
|
116
|
+
plist_str = asn1.value[1].value[0].value[2].value[1].value[0].value
|
117
|
+
plist = Plist.parse_xml plist_str.force_encoding('UTF-8')
|
118
|
+
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
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Builds
|
3
|
+
module Ios
|
4
|
+
class SetProfile
|
5
|
+
attr_reader :method
|
6
|
+
|
7
|
+
OUTPUT_PATH = '/tmp/dg/provisioning_profile/'
|
8
|
+
CERTIFICATE_OUTPUT_PATH = '/tmp/dg/certificate/'
|
9
|
+
|
10
|
+
# @param [String] username
|
11
|
+
# @param [String] identifier
|
12
|
+
# @return [DeployGate::Builds::Ios::SetProfile]
|
13
|
+
def initialize(username, identifier)
|
14
|
+
@username = username
|
15
|
+
@identifier = identifier
|
16
|
+
Spaceship.login(username)
|
17
|
+
Spaceship.select_team
|
18
|
+
if Spaceship.client.in_house?
|
19
|
+
@method = Export::ENTERPRISE
|
20
|
+
else
|
21
|
+
@method = Export::AD_HOC
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Boolean]
|
26
|
+
def app_id_create
|
27
|
+
app_created = false
|
28
|
+
Spaceship.app.all.collect do |app|
|
29
|
+
if app.bundle_id == @identifier
|
30
|
+
app_created = true
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
unless app_created
|
35
|
+
Spaceship.app.create!(:bundle_id => @identifier, :name => "#{@identifier.split('.').join(' ')}")
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Array]
|
43
|
+
def create_provisioning
|
44
|
+
if @method == Export::AD_HOC
|
45
|
+
prod_certs = Spaceship.certificate.production.all
|
46
|
+
else
|
47
|
+
prod_certs = Spaceship.certificate.all.reject{|cert| cert.class != Spaceship::Portal::Certificate::InHouse}
|
48
|
+
end
|
49
|
+
|
50
|
+
# check local install certificate
|
51
|
+
FileUtils.mkdir_p(CERTIFICATE_OUTPUT_PATH)
|
52
|
+
distribution_cert_ids = []
|
53
|
+
prod_certs.each do |cert|
|
54
|
+
path = File.join(CERTIFICATE_OUTPUT_PATH, "#{cert.id}.cer")
|
55
|
+
raw_data = cert.download_raw
|
56
|
+
File.write(path, raw_data)
|
57
|
+
distribution_cert_ids.push(cert.id) if FastlaneCore::CertChecker.installed?(path)
|
58
|
+
end
|
59
|
+
raise 'Not local install certificate' if distribution_cert_ids.empty?
|
60
|
+
|
61
|
+
FileUtils.mkdir_p(OUTPUT_PATH)
|
62
|
+
provisionings = []
|
63
|
+
distribution_cert_ids.each do |cert_id|
|
64
|
+
values = {
|
65
|
+
:adhoc => @method == Export::AD_HOC ? true : false,
|
66
|
+
:app_identifier => @identifier,
|
67
|
+
:username => @username,
|
68
|
+
:output_path => OUTPUT_PATH,
|
69
|
+
:cert_id => cert_id,
|
70
|
+
:team_id => Spaceship.client.team_id
|
71
|
+
}
|
72
|
+
v = FastlaneCore::Configuration.create(Sigh::Options.available_options, values)
|
73
|
+
Sigh.config = v
|
74
|
+
provisionings.push(Sigh::Manager.start)
|
75
|
+
end
|
76
|
+
|
77
|
+
provisionings
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Builds
|
3
|
+
module Ios
|
4
|
+
WORK_DIR_EXTNAME = '.xcworkspace'
|
5
|
+
PROJECT_DIR_EXTNAME = '.xcodeproj'
|
6
|
+
|
7
|
+
class NotSupportExportMethodError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @param [Analyze] ios_analyze
|
12
|
+
# @param [String] target_scheme
|
13
|
+
# @param [String] codesigning_identity
|
14
|
+
# @param [String] export_method
|
15
|
+
# @return [String]
|
16
|
+
def build(ios_analyze, target_scheme, codesigning_identity, export_method = Export::AD_HOC)
|
17
|
+
raise NotSupportExportMethodError, 'Not support export' unless Export::SUPPORT_EXPORT_METHOD.include?(export_method)
|
18
|
+
|
19
|
+
values = {
|
20
|
+
:export_method => export_method,
|
21
|
+
:workspace => ios_analyze.build_workspace,
|
22
|
+
:configuration => Analyze::BUILD_CONFIGRATION,
|
23
|
+
:scheme => target_scheme,
|
24
|
+
:codesigning_identity => codesigning_identity
|
25
|
+
}
|
26
|
+
v = FastlaneCore::Configuration.create(Gym::Options.available_options, values)
|
27
|
+
absolute_ipa_path = File.expand_path(Gym::Manager.new.work(v))
|
28
|
+
absolute_dsym_path = absolute_ipa_path.gsub(".ipa", ".app.dSYM.zip") # TODO: upload to deploygate
|
29
|
+
|
30
|
+
absolute_ipa_path
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [String] path
|
34
|
+
# @return [Boolean]
|
35
|
+
def workspace?(path)
|
36
|
+
WORK_DIR_EXTNAME == File.extname(path)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [String] path
|
40
|
+
# @return [Boolean]
|
41
|
+
def project?(path)
|
42
|
+
PROJECT_DIR_EXTNAME == File.extname(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def ios_root?(base_path)
|
46
|
+
Find.find(base_path) do |path|
|
47
|
+
next if path == base_path
|
48
|
+
return true if workspace?(path) || project?(path)
|
49
|
+
Find.prune if FileTest.directory?(path)
|
50
|
+
end
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param [String] base_path
|
55
|
+
# @param [Boolean] current_only
|
56
|
+
# @return [Array]
|
57
|
+
def find_workspaces(base_path)
|
58
|
+
projects = []
|
59
|
+
Find.find(base_path) do |path|
|
60
|
+
next if path == base_path
|
61
|
+
if File.extname(path) == WORK_DIR_EXTNAME
|
62
|
+
projects.push(path)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
projects
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param [String] path
|
70
|
+
# @return [String]
|
71
|
+
def project_root_path(path)
|
72
|
+
result = path
|
73
|
+
if workspace?(path) || project?(path)
|
74
|
+
result = project_root_path(File.dirname(path))
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -4,6 +4,8 @@ module DeployGate
|
|
4
4
|
attr_reader :arguments
|
5
5
|
|
6
6
|
def run
|
7
|
+
GithubIssueRequest::Url.config('deploygate', 'deploygate-cli')
|
8
|
+
|
7
9
|
program :name, 'dg'
|
8
10
|
program :version, VERSION
|
9
11
|
program :description, 'You can control to DeployGate in your terminal.'
|
@@ -12,7 +14,12 @@ module DeployGate
|
|
12
14
|
c.syntax = 'dg init'
|
13
15
|
c.description = 'project initial command'
|
14
16
|
c.action do |args, options|
|
15
|
-
|
17
|
+
begin
|
18
|
+
Commands::Init.run
|
19
|
+
rescue => e
|
20
|
+
error_handling("Commands::Init Error: #{e.class}", e.message, ['bug', 'Init'])
|
21
|
+
raise e
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
25
|
|
@@ -25,7 +32,12 @@ module DeployGate
|
|
25
32
|
c.option '--disable_notify', 'disable notify via email (iOS app only)'
|
26
33
|
c.action do |args, options|
|
27
34
|
options.default :message => '', :user => nil, :open => false, 'disable_notify' => false
|
28
|
-
|
35
|
+
begin
|
36
|
+
Commands::Deploy.run(args, options)
|
37
|
+
rescue => e
|
38
|
+
error_handling("Commands::Deploy Error: #{e.class}", e.message, ['bug', 'Deploy'])
|
39
|
+
raise e
|
40
|
+
end
|
29
41
|
end
|
30
42
|
end
|
31
43
|
alias_command :'push', :deploy
|
@@ -34,11 +46,31 @@ module DeployGate
|
|
34
46
|
c.syntax = 'dg logout'
|
35
47
|
c.description = 'logout'
|
36
48
|
c.action do |args, options|
|
37
|
-
|
49
|
+
begin
|
50
|
+
Commands::Logout.run
|
51
|
+
rescue => e
|
52
|
+
error_handling("Commands::Logout Error: #{e.class}", e.message, ['bug', 'Logout'])
|
53
|
+
raise e
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
40
57
|
|
41
58
|
run!
|
42
59
|
end
|
60
|
+
|
61
|
+
def error_handling(title, body, labels)
|
62
|
+
options = {
|
63
|
+
:title => title,
|
64
|
+
:body => body,
|
65
|
+
:labels => labels.push("v#{DeployGate::VERSION}")
|
66
|
+
}
|
67
|
+
url = GithubIssueRequest::Url.new(options).to_s
|
68
|
+
puts ''
|
69
|
+
if HighLine.agree('Do you want to report this issue on GitHub? (y/n) ') {|q| q.default = "n"}
|
70
|
+
puts "Please open github issue: #{url}"
|
71
|
+
system('open', url) if Commands::Deploy::Push.openable?
|
72
|
+
end
|
73
|
+
puts ''
|
74
|
+
end
|
43
75
|
end
|
44
76
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Commands
|
3
|
+
module Deploy
|
4
|
+
class Build
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# @param [Array] args
|
8
|
+
# @param [Hash] options
|
9
|
+
# @return [void]
|
10
|
+
def run(args, options)
|
11
|
+
# android/ios build
|
12
|
+
work_dir = args.first
|
13
|
+
|
14
|
+
if DeployGate::Build.ios?(work_dir)
|
15
|
+
root_path = DeployGate::Builds::Ios.project_root_path(work_dir)
|
16
|
+
workspaces = DeployGate::Builds::Ios.find_workspaces(root_path)
|
17
|
+
ios(workspaces, options)
|
18
|
+
elsif DeployGate::Build.android?(work_dir)
|
19
|
+
# TODO: support android build
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Array] workspaces
|
24
|
+
# @param [Hash] options
|
25
|
+
# @return [void]
|
26
|
+
def ios(workspaces, options)
|
27
|
+
analyze = DeployGate::Builds::Ios::Analyze.new(workspaces)
|
28
|
+
target_scheme = analyze.scheme
|
29
|
+
begin
|
30
|
+
identifier = analyze.target_bundle_identifier
|
31
|
+
rescue
|
32
|
+
# not found bundle identifier
|
33
|
+
puts 'Please input bundle identifier'
|
34
|
+
puts 'Example: com.example.ios'
|
35
|
+
identifier = input_bundle_identifier
|
36
|
+
end
|
37
|
+
|
38
|
+
data = DeployGate::Builds::Ios::Export.find_local_data(identifier)
|
39
|
+
profiles = data[:profiles]
|
40
|
+
teams = data[:teams]
|
41
|
+
|
42
|
+
target_provisioning_profile = nil
|
43
|
+
if teams.empty?
|
44
|
+
target_provisioning_profile = create_provisioning(identifier)
|
45
|
+
elsif teams.count == 1
|
46
|
+
target_provisioning_profile = DeployGate::Builds::Ios::Export.select_profile(profiles[teams.keys.first])
|
47
|
+
elsif teams.count >= 2
|
48
|
+
target_provisioning_profile = select_teams(teams, profiles)
|
49
|
+
end
|
50
|
+
method = DeployGate::Builds::Ios::Export.method(target_provisioning_profile)
|
51
|
+
codesigning_identity = DeployGate::Builds::Ios::Export.codesigning_identity(target_provisioning_profile)
|
52
|
+
|
53
|
+
begin
|
54
|
+
ipa_path = DeployGate::Builds::Ios.build(analyze, target_scheme, codesigning_identity, method)
|
55
|
+
rescue => e
|
56
|
+
# TODO: build error handling
|
57
|
+
raise e
|
58
|
+
end
|
59
|
+
|
60
|
+
Push.upload([ipa_path], options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def input_bundle_identifier
|
64
|
+
print 'bundle identifier: '
|
65
|
+
identifier = STDIN.gets.chop
|
66
|
+
|
67
|
+
if identifier == '' || identifier.nil?
|
68
|
+
puts 'You must input bundle identifier'
|
69
|
+
return input_bundle_identifier
|
70
|
+
end
|
71
|
+
|
72
|
+
identifier
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param [Hash] teams
|
76
|
+
# @param [Hash] profiles
|
77
|
+
# @return [String]
|
78
|
+
def select_teams(teams, profiles)
|
79
|
+
result = nil
|
80
|
+
puts 'Select team:'
|
81
|
+
teams.each_with_index do |team, index|
|
82
|
+
puts "#{index + 1}. #{team[1]} (#{team[0]})"
|
83
|
+
end
|
84
|
+
print '? '
|
85
|
+
select = STDIN.gets.chop
|
86
|
+
begin
|
87
|
+
team = teams.keys[Integer(select) - 1]
|
88
|
+
team_profiles = profiles[team].first
|
89
|
+
raise 'not select' if team_profiles.nil?
|
90
|
+
|
91
|
+
result = DeployGate::Builds::Ios::Export.select_profile(profiles[team])
|
92
|
+
rescue => e
|
93
|
+
puts 'Please select team number'
|
94
|
+
return select_teams(teams, profiles)
|
95
|
+
end
|
96
|
+
|
97
|
+
result
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param [String] identifier
|
101
|
+
# @return [String]
|
102
|
+
def create_provisioning(identifier)
|
103
|
+
puts <<EOF
|
104
|
+
|
105
|
+
No suitable provisioning profile found to export the app.
|
106
|
+
|
107
|
+
Please enter your email and password for Apple Developer Center
|
108
|
+
to set up/download provisioning profile automatically so you can
|
109
|
+
export the app without any extra steps.
|
110
|
+
|
111
|
+
Note: Your password will be stored to Keychain and never be sent to DeployGate.
|
112
|
+
|
113
|
+
EOF
|
114
|
+
print 'Email: '
|
115
|
+
username = STDIN.gets.chop
|
116
|
+
|
117
|
+
begin
|
118
|
+
set_profile = DeployGate::Builds::Ios::SetProfile.new(username, identifier)
|
119
|
+
rescue => e
|
120
|
+
DeployGate::Message::Error.print("Error: Please try login again")
|
121
|
+
raise e
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
if set_profile.app_id_create
|
126
|
+
puts "App ID #{identifier} was created"
|
127
|
+
end
|
128
|
+
rescue => e
|
129
|
+
DeployGate::Message::Error.print("Error: Failed to create App ID")
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
|
133
|
+
begin
|
134
|
+
provisioning_profiles = set_profile.create_provisioning
|
135
|
+
rescue => e
|
136
|
+
DeployGate::Message::Error.print("Error: Failed to create provisioning profile")
|
137
|
+
raise e
|
138
|
+
end
|
139
|
+
|
140
|
+
DeployGate::Builds::Ios::Export.select_profile(provisioning_profiles)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -6,8 +6,18 @@ module DeployGate
|
|
6
6
|
# @param [Array] args
|
7
7
|
# @param [Commander::Command::Options] options
|
8
8
|
def run(args, options)
|
9
|
+
Init.login unless DeployGate::Session.new.login?
|
10
|
+
|
9
11
|
# push or build(android/ios)
|
10
|
-
|
12
|
+
args.push(Dir.pwd) if args.empty?
|
13
|
+
|
14
|
+
work_file_path = args.first
|
15
|
+
if File.directory?(work_file_path)
|
16
|
+
Build.run(args, options)
|
17
|
+
else
|
18
|
+
# file upload
|
19
|
+
Push.upload(args, options)
|
20
|
+
end
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
data/lib/deploygate/version.rb
CHANGED
data/lib/deploygate.rb
CHANGED
@@ -4,6 +4,17 @@ require "httpclient"
|
|
4
4
|
require "io/console"
|
5
5
|
require "rbconfig"
|
6
6
|
require "color_echo"
|
7
|
+
require "openssl"
|
8
|
+
require "plist"
|
9
|
+
require "find"
|
10
|
+
require "github_issue_request"
|
11
|
+
require "highline"
|
12
|
+
|
13
|
+
# ios build
|
14
|
+
require "gym"
|
15
|
+
require "spaceship"
|
16
|
+
require "sigh"
|
17
|
+
require "xcodeproj"
|
7
18
|
|
8
19
|
module DeployGate
|
9
20
|
end
|
@@ -16,9 +27,15 @@ require "deploygate/commands/init"
|
|
16
27
|
require "deploygate/commands/logout"
|
17
28
|
require "deploygate/commands/deploy"
|
18
29
|
require "deploygate/commands/deploy/push"
|
30
|
+
require "deploygate/commands/deploy/build"
|
19
31
|
require "deploygate/config"
|
20
32
|
require "deploygate/session"
|
21
33
|
require "deploygate/deploy"
|
34
|
+
require "deploygate/build"
|
35
|
+
require "deploygate/builds/ios"
|
36
|
+
require "deploygate/builds/ios/export"
|
37
|
+
require "deploygate/builds/ios/analyze"
|
38
|
+
require "deploygate/builds/ios/set_profile"
|
22
39
|
require "deploygate/message/error"
|
23
40
|
require "deploygate/message/success"
|
24
41
|
require "deploygate/version"
|
@@ -21,7 +21,7 @@ describe DeployGate::API::V1::Push do
|
|
21
21
|
to_return(:body => response.to_json)
|
22
22
|
|
23
23
|
call_process_block = false
|
24
|
-
results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message)
|
24
|
+
results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message)
|
25
25
|
expect(results).to eq ({
|
26
26
|
:error => response[:error],
|
27
27
|
:message => response[:because],
|
@@ -31,7 +31,6 @@ describe DeployGate::API::V1::Push do
|
|
31
31
|
:revision => response[:results][:revision],
|
32
32
|
:web_url => DeployGate::API::V1::Base::BASE_URL + response[:results][:path]
|
33
33
|
})
|
34
|
-
expect(call_process_block).to be_truthy
|
35
34
|
end
|
36
35
|
|
37
36
|
it "failed" do
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe DeployGate::Build do
|
2
|
+
describe "#ios?" do
|
3
|
+
it "when select workspace" do
|
4
|
+
allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false)
|
5
|
+
allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(true)
|
6
|
+
allow(DeployGate::Builds::Ios).to receive(:project?).and_return(false)
|
7
|
+
|
8
|
+
result = DeployGate::Build.ios?('path')
|
9
|
+
expect(result).to be_truthy
|
10
|
+
end
|
11
|
+
|
12
|
+
it "when workspaces" do
|
13
|
+
allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false)
|
14
|
+
allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false)
|
15
|
+
allow(DeployGate::Builds::Ios).to receive(:project?).and_return(true)
|
16
|
+
|
17
|
+
result = DeployGate::Build.ios?('path')
|
18
|
+
expect(result).to be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
it "not ios" do
|
22
|
+
allow(DeployGate::Builds::Ios).to receive(:ios_root?).and_return(false)
|
23
|
+
allow(DeployGate::Builds::Ios).to receive(:workspace?).and_return(false)
|
24
|
+
allow(DeployGate::Builds::Ios).to receive(:project?).and_return(false)
|
25
|
+
|
26
|
+
result = DeployGate::Build.ios?('path')
|
27
|
+
expect(result).to be_falsey
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#android?" do
|
32
|
+
it "android not support" do
|
33
|
+
result = DeployGate::Build.android?('path')
|
34
|
+
expect(result).to be_falsey
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
describe DeployGate::Builds::Ios::Export do
|
2
|
+
describe "#adhoc?" do
|
3
|
+
it "when adhoc plist" do
|
4
|
+
plist = {
|
5
|
+
'ProvisionsAllDevices' => nil,
|
6
|
+
'Entitlements' => {'get-task-allow' => false}
|
7
|
+
}
|
8
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
9
|
+
expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_truthy
|
10
|
+
end
|
11
|
+
|
12
|
+
it "when inhouse plist" do
|
13
|
+
plist = {
|
14
|
+
'ProvisionsAllDevices' => true,
|
15
|
+
'Entitlements' => {'get-task-allow' => false}
|
16
|
+
}
|
17
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
18
|
+
expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey
|
19
|
+
end
|
20
|
+
|
21
|
+
it "when not distribution plist" do
|
22
|
+
plist = {
|
23
|
+
'ProvisionsAllDevices' => nil,
|
24
|
+
'Entitlements' => {'get-task-allow' => true}
|
25
|
+
}
|
26
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
27
|
+
expect(DeployGate::Builds::Ios::Export.adhoc?('path')).to be_falsey
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#inhouse?" do
|
32
|
+
it "when adhoc plist" do
|
33
|
+
plist = {
|
34
|
+
'ProvisionsAllDevices' => nil,
|
35
|
+
'Entitlements' => {'get-task-allow' => false}
|
36
|
+
}
|
37
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
38
|
+
expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey
|
39
|
+
end
|
40
|
+
|
41
|
+
it "when inhouse plist" do
|
42
|
+
plist = {
|
43
|
+
'ProvisionsAllDevices' => true,
|
44
|
+
'Entitlements' => {'get-task-allow' => false}
|
45
|
+
}
|
46
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
47
|
+
expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_truthy
|
48
|
+
end
|
49
|
+
|
50
|
+
it "when not distribution plist" do
|
51
|
+
plist = {
|
52
|
+
'ProvisionsAllDevices' => nil,
|
53
|
+
'Entitlements' => {'get-task-allow' => true}
|
54
|
+
}
|
55
|
+
allow(DeployGate::Builds::Ios::Export).to receive(:analyze_profile).and_return(plist)
|
56
|
+
expect(DeployGate::Builds::Ios::Export.inhouse?('path')).to be_falsey
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
describe DeployGate::Builds::Ios do
|
2
|
+
before do
|
3
|
+
class ProjectMock
|
4
|
+
def schemes
|
5
|
+
[]
|
6
|
+
end
|
7
|
+
end
|
8
|
+
class AnalyzeMock
|
9
|
+
def build_workspace
|
10
|
+
''
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#build" do
|
16
|
+
it "should call Gym Manager" do
|
17
|
+
call_gym_manager = false
|
18
|
+
allow(FastlaneCore::Configuration).to receive(:create) {}
|
19
|
+
allow_any_instance_of(Gym::Manager).to receive(:work) { call_gym_manager = true }
|
20
|
+
allow(File).to receive(:exist?).and_return(true)
|
21
|
+
allow(File).to receive(:expand_path).and_return('path')
|
22
|
+
allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new)
|
23
|
+
|
24
|
+
DeployGate::Builds::Ios.build(AnalyzeMock.new, '', '')
|
25
|
+
expect(call_gym_manager).to be_truthy
|
26
|
+
end
|
27
|
+
|
28
|
+
it "raise not support export" do
|
29
|
+
allow(FastlaneCore::Configuration).to receive(:create) {}
|
30
|
+
allow_any_instance_of(Gym::Manager).to receive(:work) {}
|
31
|
+
allow(File).to receive(:exist?).and_return(true)
|
32
|
+
allow(File).to receive(:expand_path).and_return('path')
|
33
|
+
allow(FastlaneCore::Project).to receive(:new).and_return(ProjectMock.new)
|
34
|
+
|
35
|
+
expect {
|
36
|
+
DeployGate::Builds::Ios.build(AnalyzeMock.new, '', '', 'not support export method')
|
37
|
+
}.to raise_error DeployGate::Builds::Ios::NotSupportExportMethodError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#workspace?" do
|
42
|
+
it "pod workspace" do
|
43
|
+
allow(File).to receive(:extname).and_return('.xcworkspace')
|
44
|
+
|
45
|
+
result = DeployGate::Builds::Ios.workspace?('path')
|
46
|
+
expect(result).to be_truthy
|
47
|
+
end
|
48
|
+
|
49
|
+
it "xcode project" do
|
50
|
+
allow(File).to receive(:extname).and_return('.xcodeproj')
|
51
|
+
|
52
|
+
result = DeployGate::Builds::Ios.workspace?('path')
|
53
|
+
expect(result).to be_falsey
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#project?" do
|
58
|
+
it "pod workspace" do
|
59
|
+
allow(File).to receive(:extname).and_return('.xcworkspace')
|
60
|
+
|
61
|
+
result = DeployGate::Builds::Ios.project?('path')
|
62
|
+
expect(result).to be_falsey
|
63
|
+
end
|
64
|
+
|
65
|
+
it "xcode project" do
|
66
|
+
allow(File).to receive(:extname).and_return('.xcodeproj')
|
67
|
+
|
68
|
+
result = DeployGate::Builds::Ios.project?('path')
|
69
|
+
expect(result).to be_truthy
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#find_workspaces" do
|
74
|
+
# TODO: add test
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#project_root_path" do
|
78
|
+
let(:root_path) {'test'}
|
79
|
+
it "when test/test.xcodeproj/project.xcworkspace" do
|
80
|
+
expect(DeployGate::Builds::Ios.project_root_path('test/test.xcodeproj/project.xcworkspace')).to eq root_path
|
81
|
+
end
|
82
|
+
|
83
|
+
it "when test/test.xcodeproj" do
|
84
|
+
expect(DeployGate::Builds::Ios.project_root_path('test/test.xcodeproj')).to eq root_path
|
85
|
+
end
|
86
|
+
|
87
|
+
it "when test/test.xcworkspace" do
|
88
|
+
expect(DeployGate::Builds::Ios.project_root_path('test/test.xcworkspace')).to eq root_path
|
89
|
+
end
|
90
|
+
|
91
|
+
it "when test/" do
|
92
|
+
expect(DeployGate::Builds::Ios.project_root_path('test/')).to eq root_path + '/'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
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.
|
4
|
+
version: 0.0.2
|
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-
|
11
|
+
date: 2015-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -66,6 +66,104 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 2.0.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: plist
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.1.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.1.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: xcodeproj
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.28.2
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.28.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: github_issue_request
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.0.2
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.0.2
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: highline
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.7.8
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.7.8
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: gym
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.0.0
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.0.0
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: spaceship
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.12.3
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.12.3
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: sigh
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 1.1.0
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 1.1.0
|
69
167
|
- !ruby/object:Gem::Dependency
|
70
168
|
name: bundler
|
71
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -143,8 +241,14 @@ files:
|
|
143
241
|
- lib/deploygate/api/v1/base.rb
|
144
242
|
- lib/deploygate/api/v1/push.rb
|
145
243
|
- lib/deploygate/api/v1/session.rb
|
244
|
+
- lib/deploygate/build.rb
|
245
|
+
- lib/deploygate/builds/ios.rb
|
246
|
+
- lib/deploygate/builds/ios/analyze.rb
|
247
|
+
- lib/deploygate/builds/ios/export.rb
|
248
|
+
- lib/deploygate/builds/ios/set_profile.rb
|
146
249
|
- lib/deploygate/command_builder.rb
|
147
250
|
- lib/deploygate/commands/deploy.rb
|
251
|
+
- lib/deploygate/commands/deploy/build.rb
|
148
252
|
- lib/deploygate/commands/deploy/push.rb
|
149
253
|
- lib/deploygate/commands/init.rb
|
150
254
|
- lib/deploygate/commands/logout.rb
|
@@ -156,6 +260,11 @@ files:
|
|
156
260
|
- lib/deploygate/version.rb
|
157
261
|
- spec/deploygate/api/v1/push_spec.rb
|
158
262
|
- spec/deploygate/api/v1/session_spec.rb
|
263
|
+
- spec/deploygate/build_spec.rb
|
264
|
+
- spec/deploygate/builds/ios/analyze_spec.rb
|
265
|
+
- spec/deploygate/builds/ios/export_spec.rb
|
266
|
+
- spec/deploygate/builds/ios/set_profile_spec.rb
|
267
|
+
- spec/deploygate/builds/ios_spec.rb
|
159
268
|
- spec/deploygate/config_spec.rb
|
160
269
|
- spec/deploygate/deploy_spec.rb
|
161
270
|
- spec/deploygate/session_spec.rb
|
@@ -169,7 +278,7 @@ post_install_message: |2+
|
|
169
278
|
|
170
279
|
dg installed! To get started fast:
|
171
280
|
|
172
|
-
$ dg deploy
|
281
|
+
$ dg deploy
|
173
282
|
|
174
283
|
Or see the docs at:
|
175
284
|
|
@@ -197,6 +306,11 @@ summary: A command-line interface for DeployGate
|
|
197
306
|
test_files:
|
198
307
|
- spec/deploygate/api/v1/push_spec.rb
|
199
308
|
- spec/deploygate/api/v1/session_spec.rb
|
309
|
+
- spec/deploygate/build_spec.rb
|
310
|
+
- spec/deploygate/builds/ios/analyze_spec.rb
|
311
|
+
- spec/deploygate/builds/ios/export_spec.rb
|
312
|
+
- spec/deploygate/builds/ios/set_profile_spec.rb
|
313
|
+
- spec/deploygate/builds/ios_spec.rb
|
200
314
|
- spec/deploygate/config_spec.rb
|
201
315
|
- spec/deploygate/deploy_spec.rb
|
202
316
|
- spec/deploygate/session_spec.rb
|