deploygate 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +8 -0
- data/README.md +42 -0
- data/Rakefile +5 -0
- data/bin/dg +6 -0
- data/deploygate.gemspec +42 -0
- data/lib/deploygate/api/v1/base.rb +62 -0
- data/lib/deploygate/api/v1/push.rb +46 -0
- data/lib/deploygate/api/v1/session.rb +44 -0
- data/lib/deploygate/command_builder.rb +44 -0
- data/lib/deploygate/commands/deploy/push.rb +72 -0
- data/lib/deploygate/commands/deploy.rb +15 -0
- data/lib/deploygate/commands/init.rb +44 -0
- data/lib/deploygate/commands/logout.rb +16 -0
- data/lib/deploygate/config.rb +35 -0
- data/lib/deploygate/deploy.rb +33 -0
- data/lib/deploygate/message/error.rb +12 -0
- data/lib/deploygate/message/success.rb +12 -0
- data/lib/deploygate/session.rb +61 -0
- data/lib/deploygate/version.rb +3 -0
- data/lib/deploygate.rb +24 -0
- data/spec/deploygate/api/v1/push_spec.rb +54 -0
- data/spec/deploygate/api/v1/session_spec.rb +82 -0
- data/spec/deploygate/config_spec.rb +28 -0
- data/spec/deploygate/deploy_spec.rb +39 -0
- data/spec/deploygate/session_spec.rb +72 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/test_files/DeployGateSample.apk +0 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 26683c6657e25c8cfc28d840870758aff18b911d
|
4
|
+
data.tar.gz: c6aab88672af12a275b127b604454a077416f78c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79894fef7c9c59ca78ba2535eebe1bc31f3af01bb776f21c17835e8ca6eb4e7cdfadb60fa9c2b27d4d0ac0327ca5d6c1579f739e27a7bf431820f253f15bd2fd
|
7
|
+
data.tar.gz: a318661ff7a3991e289e76f8d96fa63e711a45f855b633468b5fa921165858f9f129506f77276e0c9ea706cad75f7f9e7e440c98f890546c0168f4f1e657c792
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
|
19
|
+
# IntelliJ IDEA
|
20
|
+
.idea
|
21
|
+
deploygate-cli.iml
|
22
|
+
|
23
|
+
# test file
|
24
|
+
spec/test_files/.dg
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Copyright (C) 2015 DeployGate All rights reserved.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
4
|
+
|
5
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
+
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# deploygate-cli
|
2
|
+
|
3
|
+
## This is a beta version
|
4
|
+
|
5
|
+
A command-line interface for DeployGate
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```
|
12
|
+
gem 'deploygate'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```
|
18
|
+
$ bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ gem install deploygate
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
Upload an application:
|
29
|
+
|
30
|
+
```
|
31
|
+
$ dg deploy [package file path]
|
32
|
+
```
|
33
|
+
|
34
|
+
## License
|
35
|
+
|
36
|
+
Copyright (C) 2015 DeployGate All rights reserved.
|
37
|
+
|
38
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
39
|
+
|
40
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
41
|
+
|
42
|
+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
data/Rakefile
ADDED
data/bin/dg
ADDED
data/deploygate.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'deploygate/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "deploygate"
|
8
|
+
spec.version = DeployGate::VERSION
|
9
|
+
spec.authors = ["deploygate"]
|
10
|
+
spec.email = ["contact@deploygate.com"]
|
11
|
+
spec.description = %q{You can control to DeployGate in your terminal}
|
12
|
+
spec.summary = %q{A command-line interface for DeployGate}
|
13
|
+
spec.homepage = "https://deploygate.com"
|
14
|
+
spec.license = "Apache-2.0"
|
15
|
+
spec.post_install_message = <<"POST_INSTALL_MESSAGE"
|
16
|
+
|
17
|
+
dg installed! To get started fast:
|
18
|
+
|
19
|
+
$ dg deploy [app_file_path]
|
20
|
+
|
21
|
+
Or see the docs at:
|
22
|
+
|
23
|
+
https://deploygate.com/docs/cli
|
24
|
+
|
25
|
+
POST_INSTALL_MESSAGE
|
26
|
+
|
27
|
+
spec.add_dependency 'json', '~> 1.8.2'
|
28
|
+
spec.add_dependency 'httpclient', '~> 2.2.5'
|
29
|
+
spec.add_dependency 'commander', '~> 4.3.5'
|
30
|
+
spec.add_dependency 'color_echo', '~> 2.0.1'
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
33
|
+
spec.add_development_dependency "rake"
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.3.0"
|
35
|
+
spec.add_development_dependency "webmock", "~> 1.21.0"
|
36
|
+
|
37
|
+
spec.files = `git ls-files`.split($/)
|
38
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
39
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
40
|
+
spec.require_paths = ["lib"]
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module API
|
3
|
+
module V1
|
4
|
+
class Base
|
5
|
+
BASE_URL = 'https://deploygate.com'
|
6
|
+
API_BASE_URL = "#{BASE_URL}/api"
|
7
|
+
|
8
|
+
# @param [String] token
|
9
|
+
# @return [DeployGate::API::V1::Base]
|
10
|
+
def initialize(token = nil)
|
11
|
+
@token = token
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [String] path
|
15
|
+
# @param [Hash] params
|
16
|
+
# @return [Hash] Responce parse json
|
17
|
+
def get(path, params)
|
18
|
+
url = API_BASE_URL + path
|
19
|
+
|
20
|
+
res = client.get(url, params, headers)
|
21
|
+
JSON.parse(res.body)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [String] path
|
25
|
+
# @param [Hash] params
|
26
|
+
# @yield Upload process block
|
27
|
+
# @return [Hash] Responce parse json
|
28
|
+
def post(path, params, &process_block)
|
29
|
+
url = API_BASE_URL + path
|
30
|
+
|
31
|
+
connection = client.post_async(url, params, headers)
|
32
|
+
while true
|
33
|
+
break if connection.finished?
|
34
|
+
process_block.call unless process_block.nil?
|
35
|
+
end
|
36
|
+
io = connection.pop.content
|
37
|
+
body = ''
|
38
|
+
while str = io.read(40)
|
39
|
+
body += str
|
40
|
+
end
|
41
|
+
|
42
|
+
JSON.parse(body)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def client
|
48
|
+
HTTPClient.new(:agent_name => "dg/#{DeployGate::VERSION}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def headers
|
52
|
+
extheaders = []
|
53
|
+
unless @token.nil?
|
54
|
+
extheaders.push(['AUTHORIZATION', @token])
|
55
|
+
end
|
56
|
+
|
57
|
+
extheaders
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module API
|
3
|
+
module V1
|
4
|
+
class Push
|
5
|
+
ENDPOINT = "/users/%s/apps"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# @param [String] file_path
|
10
|
+
# @param [String] target_user
|
11
|
+
# @param [String] token
|
12
|
+
# @param [String] message
|
13
|
+
# @param [Boolean] disable_notify
|
14
|
+
# @yield Upload process block
|
15
|
+
# @return [Hash]
|
16
|
+
def upload(file_path, target_user, token, message, disable_notify = false, &process_block)
|
17
|
+
res = nil
|
18
|
+
open(file_path) do |file|
|
19
|
+
res = Base.new(token).post(
|
20
|
+
sprintf(ENDPOINT, target_user),
|
21
|
+
{ :file => file , :message => message, :disable_notify => disable_notify ? 'yes' : 'no' }) { process_block.call unless process_block.nil? }
|
22
|
+
end
|
23
|
+
|
24
|
+
upload_results = {
|
25
|
+
:error => res['error'],
|
26
|
+
:message => res['because']
|
27
|
+
}
|
28
|
+
|
29
|
+
results = res['results']
|
30
|
+
unless results.nil?
|
31
|
+
upload_results.merge!({
|
32
|
+
:application_name => results['name'],
|
33
|
+
:owner_name => results['user']['name'],
|
34
|
+
:package_name => results['package_name'],
|
35
|
+
:revision => results['revision'],
|
36
|
+
:web_url => Base::BASE_URL + results['path']
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
upload_results
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module API
|
3
|
+
module V1
|
4
|
+
class Session
|
5
|
+
ENDPOINT = '/sessions'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# @param [String] name
|
10
|
+
# @param [String] token
|
11
|
+
# @return [Boolean]
|
12
|
+
def check(name, token)
|
13
|
+
res = Base.new(token).get(ENDPOINT + '/user', {})
|
14
|
+
return false if res['error']
|
15
|
+
|
16
|
+
name == res['results']['name']
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [String] email
|
20
|
+
# @param [String] password
|
21
|
+
# @return [Hash]
|
22
|
+
def login(email, password)
|
23
|
+
res = Base.new().post(ENDPOINT, {:email => email, :password => password})
|
24
|
+
|
25
|
+
login_results = {
|
26
|
+
:error => res['error'],
|
27
|
+
:message => res['because']
|
28
|
+
}
|
29
|
+
|
30
|
+
results = res['results']
|
31
|
+
unless results.nil?
|
32
|
+
login_results.merge!({
|
33
|
+
:name => results['name'],
|
34
|
+
:token => results['api_token']
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
login_results
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module DeployGate
|
2
|
+
class CommandBuilder
|
3
|
+
include Commander::Methods
|
4
|
+
attr_reader :arguments
|
5
|
+
|
6
|
+
def run
|
7
|
+
program :name, 'dg'
|
8
|
+
program :version, VERSION
|
9
|
+
program :description, 'You can control to DeployGate in your terminal.'
|
10
|
+
|
11
|
+
command :init do |c|
|
12
|
+
c.syntax = 'dg init'
|
13
|
+
c.description = 'project initial command'
|
14
|
+
c.action do |args, options|
|
15
|
+
Commands::Init.run
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
command :deploy do |c|
|
20
|
+
c.syntax = 'dg deploy /path/to/app'
|
21
|
+
c.description = 'upload to deploygate'
|
22
|
+
c.option '--message STRING', String, 'release message'
|
23
|
+
c.option '--user STRING', String, 'owner name or group name'
|
24
|
+
c.option '--open', 'open browser (OSX only)'
|
25
|
+
c.option '--disable_notify', 'disable notify via email (iOS app only)'
|
26
|
+
c.action do |args, options|
|
27
|
+
options.default :message => '', :user => nil, :open => false, 'disable_notify' => false
|
28
|
+
Commands::Deploy.run(args, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias_command :'push', :deploy
|
32
|
+
|
33
|
+
command :logout do |c|
|
34
|
+
c.syntax = 'dg logout'
|
35
|
+
c.description = 'logout'
|
36
|
+
c.action do |args, options|
|
37
|
+
Commands::Logout.run
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
run!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Commands
|
3
|
+
module Deploy
|
4
|
+
class Push
|
5
|
+
BASE_URL = 'https://deploygate.com'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# @param [Array] args
|
10
|
+
# @param [Commander::Command::Options] options
|
11
|
+
# @return [void]
|
12
|
+
def upload(args, options)
|
13
|
+
session = DeployGate::Session.new()
|
14
|
+
unless session.login?
|
15
|
+
Init.login
|
16
|
+
session = DeployGate::Session.new()
|
17
|
+
end
|
18
|
+
|
19
|
+
message = options.message
|
20
|
+
owner = options.user || session.name
|
21
|
+
open = options.open
|
22
|
+
disable_notify = options.disable_notify
|
23
|
+
file_path = args.first
|
24
|
+
|
25
|
+
data = nil
|
26
|
+
print "Uploading to #{owner}.."
|
27
|
+
begin
|
28
|
+
data = DeployGate::Deploy.push(file_path, owner, message, disable_notify) {
|
29
|
+
print '.'
|
30
|
+
sleep 0.2
|
31
|
+
}
|
32
|
+
rescue => e
|
33
|
+
upload_error(e)
|
34
|
+
end
|
35
|
+
|
36
|
+
upload_success(data, open)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Boolean]
|
40
|
+
def openable?
|
41
|
+
RbConfig::CONFIG['host_os'].include?('darwin')
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [Hash] data
|
45
|
+
# @param [Boolean] open
|
46
|
+
# @return [void]
|
47
|
+
def upload_success(data, open)
|
48
|
+
Message::Success.print('done')
|
49
|
+
data_message = <<EOS
|
50
|
+
Name: \t\t #{data[:application_name]}
|
51
|
+
Owner: \t\t #{data[:owner_name]}
|
52
|
+
Package: \t #{data[:package_name]}
|
53
|
+
Revision: \t #{data[:revision]}
|
54
|
+
URL: \t\t #{data[:web_url]}
|
55
|
+
EOS
|
56
|
+
puts(data_message)
|
57
|
+
if((open || data[:revision] == 1) && openable?)
|
58
|
+
system "open #{data[:web_url]}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [StandardError] error
|
63
|
+
# @return [void]
|
64
|
+
def upload_error(error)
|
65
|
+
Message::Error.print('failed')
|
66
|
+
raise error
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Commands
|
3
|
+
module Deploy
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# @param [Array] args
|
7
|
+
# @param [Commander::Command::Options] options
|
8
|
+
def run(args, options)
|
9
|
+
# push or build(android/ios)
|
10
|
+
Push.upload(args, options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Commands
|
3
|
+
class Init
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# @return [void]
|
7
|
+
def run
|
8
|
+
login unless Session.new().login?
|
9
|
+
|
10
|
+
finish
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [void]
|
14
|
+
def login
|
15
|
+
puts 'Welcome to DeployGate!'
|
16
|
+
puts ''
|
17
|
+
print 'Email: '
|
18
|
+
email= STDIN.gets.chop
|
19
|
+
print 'Password: '
|
20
|
+
password = STDIN.noecho(&:gets).chop
|
21
|
+
puts ''
|
22
|
+
|
23
|
+
begin
|
24
|
+
Session.login(email, password)
|
25
|
+
rescue Session::LoginError => e
|
26
|
+
# login failed
|
27
|
+
Message::Error.print('Login failed...')
|
28
|
+
Message::Error.print('Please try again')
|
29
|
+
raise e
|
30
|
+
end
|
31
|
+
|
32
|
+
# login success
|
33
|
+
session = Session.new
|
34
|
+
Message::Success.print("Hello #{session.name}!")
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [void]
|
38
|
+
def finish
|
39
|
+
Message::Success.print('Enjoy development!')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DeployGate
|
2
|
+
module Commands
|
3
|
+
class Logout
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# @return [void]
|
7
|
+
def run
|
8
|
+
DeployGate::Session.delete
|
9
|
+
|
10
|
+
Message::Success.print('Logout success!')
|
11
|
+
Message::Success.print('Goodbye! :)')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module DeployGate
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# @return [String]
|
6
|
+
def file_path
|
7
|
+
File.join(ENV["HOME"], '.dg/credentials')
|
8
|
+
end
|
9
|
+
|
10
|
+
# @param [Hash] config
|
11
|
+
# @return [void]
|
12
|
+
def write(config)
|
13
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
14
|
+
|
15
|
+
data = JSON.generate(config)
|
16
|
+
file = File.open(file_path, "w+")
|
17
|
+
file.print data
|
18
|
+
file.close
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Hash]
|
22
|
+
def read
|
23
|
+
file = File.open(file_path)
|
24
|
+
data = file.read
|
25
|
+
file.close
|
26
|
+
JSON.parse(data)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Boolean]
|
30
|
+
def exist?
|
31
|
+
File.exist?(file_path)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DeployGate
|
2
|
+
class Deploy
|
3
|
+
class NotLoginError < StandardError
|
4
|
+
end
|
5
|
+
class NotFileExistError < StandardError
|
6
|
+
end
|
7
|
+
class UploadError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
# @param [String] file_path
|
13
|
+
# @param [String] target_user
|
14
|
+
# @param [String] message
|
15
|
+
# @param [Boolean] disable_notify
|
16
|
+
# @yield Upload process block
|
17
|
+
# @return [Hash]
|
18
|
+
def push(file_path, target_user, message, disable_notify = false, &process_block)
|
19
|
+
raise NotFileExistError, 'Target file is not found' if file_path.nil? || !File.exist?(file_path)
|
20
|
+
|
21
|
+
session = DeployGate::Session.new()
|
22
|
+
raise NotLoginError, 'Must login user' unless session.login?
|
23
|
+
token = session.token
|
24
|
+
|
25
|
+
|
26
|
+
data = API::V1::Push.upload(file_path, target_user, token, message, disable_notify) { process_block.call unless process_block.nil? }
|
27
|
+
raise UploadError, data[:message] if data[:error]
|
28
|
+
|
29
|
+
data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DeployGate
|
2
|
+
class Session
|
3
|
+
class LoginError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
attr_reader :name, :token
|
7
|
+
|
8
|
+
@@login = nil
|
9
|
+
|
10
|
+
# @return [DeployGate::Session]
|
11
|
+
def initialize
|
12
|
+
load_setting
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Boolean]
|
16
|
+
def login?
|
17
|
+
@@login = @@login.nil? ? API::V1::Session.check(@name, @token) : @@login
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [String] email
|
21
|
+
# @param [String] password
|
22
|
+
# @return [void]
|
23
|
+
def self.login(email, password)
|
24
|
+
data = API::V1::Session.login(email, password)
|
25
|
+
raise LoginError, data[:message] if data[:error]
|
26
|
+
|
27
|
+
name = data[:name]
|
28
|
+
token = data[:token]
|
29
|
+
save(name, token)
|
30
|
+
@@login = true
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [String] name
|
34
|
+
# @param [String] token
|
35
|
+
# @return [void]
|
36
|
+
def self.save(name, token)
|
37
|
+
settings = {
|
38
|
+
:name => name,
|
39
|
+
:token => token
|
40
|
+
}
|
41
|
+
Config.write(settings)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [void]
|
45
|
+
def self.delete
|
46
|
+
save('', '') # delete config values
|
47
|
+
@@login = false
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @return [void]
|
53
|
+
def load_setting
|
54
|
+
return unless Config.exist?
|
55
|
+
settings = Config.read
|
56
|
+
@name = settings['name']
|
57
|
+
@token = settings['token']
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/lib/deploygate.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "commander"
|
2
|
+
require "json"
|
3
|
+
require "httpclient"
|
4
|
+
require "io/console"
|
5
|
+
require "rbconfig"
|
6
|
+
require "color_echo"
|
7
|
+
|
8
|
+
module DeployGate
|
9
|
+
end
|
10
|
+
|
11
|
+
require "deploygate/api/v1/base"
|
12
|
+
require "deploygate/api/v1/session"
|
13
|
+
require "deploygate/api/v1/push"
|
14
|
+
require "deploygate/command_builder"
|
15
|
+
require "deploygate/commands/init"
|
16
|
+
require "deploygate/commands/logout"
|
17
|
+
require "deploygate/commands/deploy"
|
18
|
+
require "deploygate/commands/deploy/push"
|
19
|
+
require "deploygate/config"
|
20
|
+
require "deploygate/session"
|
21
|
+
require "deploygate/deploy"
|
22
|
+
require "deploygate/message/error"
|
23
|
+
require "deploygate/message/success"
|
24
|
+
require "deploygate/version"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
describe DeployGate::API::V1::Push do
|
2
|
+
describe "#upload" do
|
3
|
+
it "success" do
|
4
|
+
target_user = 'test'
|
5
|
+
token = 'token'
|
6
|
+
message = 'message'
|
7
|
+
response = {
|
8
|
+
:error => false,
|
9
|
+
:because => '',
|
10
|
+
:results => {
|
11
|
+
:name => 'application_name',
|
12
|
+
:user => {:name => 'user name'},
|
13
|
+
:package_name => 'com.example.package.name',
|
14
|
+
:revision => 1,
|
15
|
+
:path => '/path/to/app'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
stub_request(:post, "#{API_ENDPOINT}/users/#{target_user}/apps").
|
20
|
+
with(:headers => { 'AUTHORIZATION' => token }).
|
21
|
+
to_return(:body => response.to_json)
|
22
|
+
|
23
|
+
call_process_block = false
|
24
|
+
results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message) {call_process_block = true}
|
25
|
+
expect(results).to eq ({
|
26
|
+
:error => response[:error],
|
27
|
+
:message => response[:because],
|
28
|
+
:application_name => response[:results][:name],
|
29
|
+
:owner_name => response[:results][:user][:name],
|
30
|
+
:package_name => response[:results][:package_name],
|
31
|
+
:revision => response[:results][:revision],
|
32
|
+
:web_url => DeployGate::API::V1::Base::BASE_URL + response[:results][:path]
|
33
|
+
})
|
34
|
+
expect(call_process_block).to be_truthy
|
35
|
+
end
|
36
|
+
|
37
|
+
it "failed" do
|
38
|
+
target_user = 'test'
|
39
|
+
token = 'token'
|
40
|
+
message = 'message'
|
41
|
+
response = {
|
42
|
+
:error => true,
|
43
|
+
:because => 'error message'
|
44
|
+
}
|
45
|
+
|
46
|
+
stub_request(:post, "#{API_ENDPOINT}/users/#{target_user}/apps").
|
47
|
+
with(:headers => { 'AUTHORIZATION' => token }).
|
48
|
+
to_return(:body => response.to_json)
|
49
|
+
|
50
|
+
results = DeployGate::API::V1::Push.upload(test_file_path, target_user, token, message)
|
51
|
+
expect(results).to eq ({:error => response[:error], :message => response[:because]})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
describe DeployGate::API::V1::Session do
|
2
|
+
describe "#check" do
|
3
|
+
it "logined" do
|
4
|
+
token = 'token'
|
5
|
+
name = 'test'
|
6
|
+
response = {
|
7
|
+
:error => false,
|
8
|
+
:because => '',
|
9
|
+
:results => {:name => name}
|
10
|
+
}
|
11
|
+
stub_request(:get, "#{API_ENDPOINT}/sessions/user").
|
12
|
+
with(:headers => { 'AUTHORIZATION' => token }).
|
13
|
+
to_return(:body => response.to_json)
|
14
|
+
|
15
|
+
|
16
|
+
result = DeployGate::API::V1::Session.check(name, token)
|
17
|
+
expect(result).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it "not login" do
|
21
|
+
token = 'token'
|
22
|
+
name = 'test'
|
23
|
+
response = {
|
24
|
+
:error => true,
|
25
|
+
:because => 'error message'
|
26
|
+
}
|
27
|
+
stub_request(:get, "#{API_ENDPOINT}/sessions/user").
|
28
|
+
with(:headers => { 'AUTHORIZATION' => token }).
|
29
|
+
to_return(:body => response.to_json)
|
30
|
+
|
31
|
+
result = DeployGate::API::V1::Session.check(name, token)
|
32
|
+
expect(result).to be_falsey
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#login" do
|
37
|
+
it "success" do
|
38
|
+
email = 'test@example.com'
|
39
|
+
pass = 'examplepass'
|
40
|
+
token = 'token'
|
41
|
+
name = 'test'
|
42
|
+
|
43
|
+
response = {
|
44
|
+
:error => false,
|
45
|
+
:because => '',
|
46
|
+
:results => {:name => name, :api_token => token}
|
47
|
+
}
|
48
|
+
stub_request(:post, "#{API_ENDPOINT}/sessions").
|
49
|
+
with(:body => {:email => email, :password => pass}).
|
50
|
+
to_return(:body => response.to_json)
|
51
|
+
|
52
|
+
results = DeployGate::API::V1::Session.login(email, pass)
|
53
|
+
expect(results).to eq ({
|
54
|
+
:error => response[:error],
|
55
|
+
:message => response[:because],
|
56
|
+
:name => name,
|
57
|
+
:token => token
|
58
|
+
})
|
59
|
+
end
|
60
|
+
|
61
|
+
it "failed" do
|
62
|
+
email = 'test@example.com'
|
63
|
+
pass = 'examplepass'
|
64
|
+
token = 'token'
|
65
|
+
name = 'test'
|
66
|
+
|
67
|
+
response = {
|
68
|
+
:error => true,
|
69
|
+
:because => 'error message'
|
70
|
+
}
|
71
|
+
stub_request(:post, "#{API_ENDPOINT}/sessions").
|
72
|
+
with(:body => {:email => email, :password => pass}).
|
73
|
+
to_return(:body => response.to_json)
|
74
|
+
|
75
|
+
results = DeployGate::API::V1::Session.login(email, pass)
|
76
|
+
expect(results).to eq ({
|
77
|
+
:error => response[:error],
|
78
|
+
:message => response[:because]
|
79
|
+
})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
describe DeployGate::Config do
|
2
|
+
describe "#write" do
|
3
|
+
it "write data" do
|
4
|
+
write_data = {
|
5
|
+
:name => 'test',
|
6
|
+
:token => 'token'
|
7
|
+
}
|
8
|
+
allow(File).to receive(:open).and_return(StringIO.new("", "w+"))
|
9
|
+
DeployGate::Config.write(write_data)
|
10
|
+
|
11
|
+
file = File.open(DeployGate::Config.file_path)
|
12
|
+
expect(file.string).to eq(write_data.to_json.to_s)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#read" do
|
17
|
+
it "read data" do
|
18
|
+
write_data = {
|
19
|
+
:name => 'test',
|
20
|
+
:token => 'token'
|
21
|
+
}.to_json.to_s
|
22
|
+
allow(File).to receive(:open).and_return(StringIO.new(write_data))
|
23
|
+
data = DeployGate::Config.read
|
24
|
+
|
25
|
+
expect(data).to eq(JSON.parse(write_data))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
describe DeployGate::Deploy do
|
2
|
+
describe "#push" do
|
3
|
+
context "raise error" do
|
4
|
+
it "NotLoginError" do
|
5
|
+
allow_any_instance_of(DeployGate::Session).to receive(:login?) { false }
|
6
|
+
|
7
|
+
expect {
|
8
|
+
DeployGate::Deploy.push(test_file_path, 'test', 'message')
|
9
|
+
}.to raise_error DeployGate::Deploy::NotLoginError
|
10
|
+
end
|
11
|
+
|
12
|
+
it "NotFileExistError" do
|
13
|
+
expect {
|
14
|
+
DeployGate::Deploy.push('no_file_path', 'test', 'message')
|
15
|
+
}.to raise_error DeployGate::Deploy::NotFileExistError
|
16
|
+
end
|
17
|
+
|
18
|
+
it "UploadError" do
|
19
|
+
allow_any_instance_of(DeployGate::Session).to receive(:login?) { true }
|
20
|
+
allow(DeployGate::API::V1::Push).to receive(:upload).and_return({:error => true, :message => 'error message'})
|
21
|
+
|
22
|
+
expect {
|
23
|
+
DeployGate::Deploy.push(test_file_path, 'test', 'message')
|
24
|
+
}.to raise_error DeployGate::Deploy::UploadError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "success" do
|
29
|
+
it "default" do
|
30
|
+
allow(DeployGate::API::V1::Push).to receive(:upload).and_return({:error => false})
|
31
|
+
allow_any_instance_of(DeployGate::Session).to receive(:login?) { true }
|
32
|
+
|
33
|
+
expect {
|
34
|
+
DeployGate::Deploy.push(test_file_path, 'test', 'message')
|
35
|
+
}.not_to raise_error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
describe DeployGate::Session do
|
2
|
+
describe "#login?" do
|
3
|
+
it "call check api" do
|
4
|
+
call_check = false
|
5
|
+
allow(DeployGate::API::V1::Session).to receive(:check) { call_check = true }
|
6
|
+
|
7
|
+
DeployGate::Session.new.login?
|
8
|
+
expect(call_check).to be_truthy
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#login" do
|
13
|
+
it "success" do
|
14
|
+
data = {
|
15
|
+
:error => false,
|
16
|
+
:name => 'test',
|
17
|
+
:token => 'token'
|
18
|
+
}
|
19
|
+
call_save = false
|
20
|
+
allow(DeployGate::API::V1::Session).to receive(:login).and_return(data)
|
21
|
+
allow(DeployGate::Session).to receive(:save) { call_save = true }
|
22
|
+
|
23
|
+
DeployGate::Session.delete
|
24
|
+
expect {
|
25
|
+
DeployGate::Session.login('test@example.com', 'test')
|
26
|
+
}.not_to raise_error
|
27
|
+
expect(call_save).to be_truthy
|
28
|
+
expect(DeployGate::Session.new.login?).to be_truthy
|
29
|
+
end
|
30
|
+
|
31
|
+
it "failed" do
|
32
|
+
data = {
|
33
|
+
:error => true,
|
34
|
+
:message => 'error message'
|
35
|
+
}
|
36
|
+
allow(DeployGate::API::V1::Session).to receive(:login).and_return(data)
|
37
|
+
|
38
|
+
expect {
|
39
|
+
DeployGate::Session.login('test@example.com', 'test')
|
40
|
+
}.to raise_error(DeployGate::Session::LoginError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#save" do
|
45
|
+
it "call Config.write" do
|
46
|
+
config_data = {
|
47
|
+
:name => 'test',
|
48
|
+
:token => 'token'
|
49
|
+
}
|
50
|
+
call_config_write_and_fix_config = false
|
51
|
+
allow(DeployGate::Config).to receive(:write) { |c| call_config_write_and_fix_config = c == config_data}
|
52
|
+
|
53
|
+
|
54
|
+
DeployGate::Session.save(config_data[:name], config_data[:token])
|
55
|
+
expect(call_config_write_and_fix_config).to be_truthy
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#delete" do
|
60
|
+
it "call save" do
|
61
|
+
call_save = false
|
62
|
+
allow(DeployGate::Session).to receive(:save) { |name, token| call_save = (name == '' && token == '')}
|
63
|
+
|
64
|
+
|
65
|
+
DeployGate::Session.delete
|
66
|
+
expect(call_save).to be_truthy
|
67
|
+
|
68
|
+
login = DeployGate::Session.new.login?
|
69
|
+
expect(login).to be_falsey
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "webmock/rspec"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
require "deploygate"
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.before :each do
|
8
|
+
# config file mock
|
9
|
+
allow(DeployGate::Config).to receive(:file_path).and_return(File.join(SPEC_FILE_PATH, 'test_files/.dg/credentials'))
|
10
|
+
# config dir mock
|
11
|
+
allow(FileUtils).to receive(:mkdir_p) {}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
API_ENDPOINT = "https://deploygate.com/api"
|
16
|
+
SPEC_FILE_PATH = File.dirname(__FILE__)
|
17
|
+
|
18
|
+
def test_file_path
|
19
|
+
File.join(SPEC_FILE_PATH, 'test_files/DeployGateSample.apk')
|
20
|
+
end
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deploygate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- deploygate
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.8.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.8.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httpclient
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.5
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: commander
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.3.5
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.3.5
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: color_echo
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.0.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.3.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.3.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.21.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.21.0
|
125
|
+
description: You can control to DeployGate in your terminal
|
126
|
+
email:
|
127
|
+
- contact@deploygate.com
|
128
|
+
executables:
|
129
|
+
- dg
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- ".rspec"
|
135
|
+
- ".travis.yml"
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/dg
|
141
|
+
- deploygate.gemspec
|
142
|
+
- lib/deploygate.rb
|
143
|
+
- lib/deploygate/api/v1/base.rb
|
144
|
+
- lib/deploygate/api/v1/push.rb
|
145
|
+
- lib/deploygate/api/v1/session.rb
|
146
|
+
- lib/deploygate/command_builder.rb
|
147
|
+
- lib/deploygate/commands/deploy.rb
|
148
|
+
- lib/deploygate/commands/deploy/push.rb
|
149
|
+
- lib/deploygate/commands/init.rb
|
150
|
+
- lib/deploygate/commands/logout.rb
|
151
|
+
- lib/deploygate/config.rb
|
152
|
+
- lib/deploygate/deploy.rb
|
153
|
+
- lib/deploygate/message/error.rb
|
154
|
+
- lib/deploygate/message/success.rb
|
155
|
+
- lib/deploygate/session.rb
|
156
|
+
- lib/deploygate/version.rb
|
157
|
+
- spec/deploygate/api/v1/push_spec.rb
|
158
|
+
- spec/deploygate/api/v1/session_spec.rb
|
159
|
+
- spec/deploygate/config_spec.rb
|
160
|
+
- spec/deploygate/deploy_spec.rb
|
161
|
+
- spec/deploygate/session_spec.rb
|
162
|
+
- spec/spec_helper.rb
|
163
|
+
- spec/test_files/DeployGateSample.apk
|
164
|
+
homepage: https://deploygate.com
|
165
|
+
licenses:
|
166
|
+
- Apache-2.0
|
167
|
+
metadata: {}
|
168
|
+
post_install_message: |2+
|
169
|
+
|
170
|
+
dg installed! To get started fast:
|
171
|
+
|
172
|
+
$ dg deploy [app_file_path]
|
173
|
+
|
174
|
+
Or see the docs at:
|
175
|
+
|
176
|
+
https://deploygate.com/docs/cli
|
177
|
+
|
178
|
+
rdoc_options: []
|
179
|
+
require_paths:
|
180
|
+
- lib
|
181
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
requirements: []
|
192
|
+
rubyforge_project:
|
193
|
+
rubygems_version: 2.4.5
|
194
|
+
signing_key:
|
195
|
+
specification_version: 4
|
196
|
+
summary: A command-line interface for DeployGate
|
197
|
+
test_files:
|
198
|
+
- spec/deploygate/api/v1/push_spec.rb
|
199
|
+
- spec/deploygate/api/v1/session_spec.rb
|
200
|
+
- spec/deploygate/config_spec.rb
|
201
|
+
- spec/deploygate/deploy_spec.rb
|
202
|
+
- spec/deploygate/session_spec.rb
|
203
|
+
- spec/spec_helper.rb
|
204
|
+
- spec/test_files/DeployGateSample.apk
|