dpl 1.7.12.travis.742.4 → 1.7.12.travis.748.4
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 +8 -8
- data/README.md +31 -2
- data/lib/dpl/provider.rb +1 -0
- data/lib/dpl/provider/testfairy.rb +184 -0
- data/spec/provider/testfairy_spec.rb +80 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
NGI1NmM1NTEzMjg0MjBjZWI3MWM0ZmZkYThlNjlkYmJkYmU3MDZiNA==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
YzM0YmEyNTcyOTJhOWU4ZmIxYTIyNzMwM2U0NWEwMTI0YjBmNGFkNw==
|
|
7
7
|
SHA512:
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
MGI2MjBmZWU2YzNhZjVlZWExY2YyNDdjZjI1OGNmYjAzODQ0NTVhYjE5NDE2
|
|
10
|
+
MWJhMTI1YTMxMGM4N2MwY2UyY2Q2NmQxZDg5YTBkMDcyZmNmNjg5YmU3YjZk
|
|
11
|
+
MWUxMWQ3NDg3YTZmMWQxYTk3MjFiYzI3OGE4MTVhM2VkMGU5MDA=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
ZDYwNTdlNzk4ZTg2NjhjNzYxZjllZDVlODU0ZTg1NDQ1N2E4MjVmYmNiYmVl
|
|
14
|
+
NGRmNWIxYzkxZGViODcwODM0N2RiZDEwNGQ5NDgzNTZjYWJiMjMxMzUzM2Y5
|
|
15
|
+
MjYxOGYyZWI0ZTQzYjJlODExNTI1YWIyMGMyM2NlZjdlYjc2OWE=
|
data/README.md
CHANGED
|
@@ -33,6 +33,7 @@ Dpl supports the following providers:
|
|
|
33
33
|
* [packagecloud](#packagecloud)
|
|
34
34
|
* [Chef Supermarket](#chef-supermarket)
|
|
35
35
|
* [Lambda](#lambda)
|
|
36
|
+
* [TestFairy](#testfairy)
|
|
36
37
|
|
|
37
38
|
## Installation:
|
|
38
39
|
|
|
@@ -50,8 +51,6 @@ Running dpl in a terminal that saves history is insecure as your password/api ke
|
|
|
50
51
|
###Global Flags
|
|
51
52
|
* `--provider=<provider>` sets the provider you want to deploy to. Every provider has slightly different flags, which are documented in the section about your provider following.
|
|
52
53
|
* Dpl will deploy by default from the latest commit. Use the `--skip_cleanup` flag to deploy from the current file state. Note that many providers deploy by git and could ignore this option.
|
|
53
|
-
|
|
54
|
-
|
|
55
54
|
### Heroku:
|
|
56
55
|
|
|
57
56
|
#### Options:
|
|
@@ -492,3 +491,33 @@ Deploy contents of a specific directory using specific module name:
|
|
|
492
491
|
--module_name="copy" \
|
|
493
492
|
--handler_name="handler";
|
|
494
493
|
```
|
|
494
|
+
|
|
495
|
+
### TestFairy:
|
|
496
|
+
|
|
497
|
+
Your Android(apk)/iOS(ipa) file will be uploaded to TestFairy,
|
|
498
|
+
and your testers can start testing your app.
|
|
499
|
+
|
|
500
|
+
#### Options:
|
|
501
|
+
* **api-key**: TestFairy API Key (https://app.testfairy.com/settings/) run "travis encrypt --add deploy.api-key" on your repo.
|
|
502
|
+
* **app-file**: Path to the app file that will be generated after the build (APK/IPA).
|
|
503
|
+
* **symbols-file**: Path to the symbols file.
|
|
504
|
+
* **keystore-file**: Path to your keystore-file (must, only for android). http://docs.travis-ci.com/user/encrypting-files/
|
|
505
|
+
* **storepass**: storepass (must, only for android).
|
|
506
|
+
* **alias**: alias (must, only for android).
|
|
507
|
+
* **testers-groups**: You can set a tester group to be notified about this build (group1,group1).
|
|
508
|
+
* **notify**: If true, an email you a changelog will be sent to your users.
|
|
509
|
+
* **auto-update**: If true, all the previous installations of this app will be automatically all upgraded to this version.
|
|
510
|
+
* **video-quality**: Video quality settings, "high", "medium" or "low". Default is "high".
|
|
511
|
+
* **screenshot-interval**: You can choose "1"\"2"\"10" sec.
|
|
512
|
+
* **max-duration**: Maximum session recording length, eg "20m" or "1h". Default is "10m". Maximum "24h".
|
|
513
|
+
* **advanced-options**: For example (option1,option2)
|
|
514
|
+
* **data-only-wifi**: If true, video and recorded metrics will be sent only when connected to a wifi network.
|
|
515
|
+
* **record-on-background**: If true, data will be collected while the app on background.
|
|
516
|
+
* **video**: If true, Video recording settings "true", "false". Default is "true".
|
|
517
|
+
* **icon-watermark**: Add a small watermark to app icon. Default is "false".
|
|
518
|
+
* **metrics**: Comma-separated list of metrics to record. View list on http://docs.testfairy.com/Upload_API.html.
|
|
519
|
+
|
|
520
|
+
#### Examples:
|
|
521
|
+
|
|
522
|
+
dpl --provider=testfairy --api-key=<api-key> --app-file="out/Sample.apk" --keystore-file="out/keystore" --storepass=<storepass> --alias=<alias>
|
|
523
|
+
|
data/lib/dpl/provider.rb
CHANGED
|
@@ -37,6 +37,7 @@ module DPL
|
|
|
37
37
|
autoload :PuppetForge, 'dpl/provider/puppet_forge'
|
|
38
38
|
autoload :Packagecloud, 'dpl/provider/packagecloud'
|
|
39
39
|
autoload :ChefSupermarket, 'dpl/provider/chef_supermarket'
|
|
40
|
+
autoload :TestFairy, 'dpl/provider/testfairy'
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def self.new(context, options)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
module DPL
|
|
2
|
+
class Provider
|
|
3
|
+
class TestFairy < Provider
|
|
4
|
+
|
|
5
|
+
require "net/http"
|
|
6
|
+
require 'net/http/post/multipart'
|
|
7
|
+
require 'json'
|
|
8
|
+
require 'tempfile'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
VERSION = "0.1"
|
|
12
|
+
TAG = "-TestFairy-"
|
|
13
|
+
SERVER = "http://api.testfairy.com"
|
|
14
|
+
UPLOAD_URL_PATH = "/api/upload";
|
|
15
|
+
UPLOAD_SIGNED_URL_PATH = "/api/upload-signed";
|
|
16
|
+
|
|
17
|
+
def check_auth
|
|
18
|
+
if android?
|
|
19
|
+
storepassToPrint = option(:storepass).clone
|
|
20
|
+
aliasToPrint = option(:alias).clone
|
|
21
|
+
puts "keystore-file = #{option(:keystore_file)} storepass = #{storepassToPrint.sub! storepassToPrint[1..-2], '****'} alias = #{aliasToPrint.sub! aliasToPrint[1..-2], '****'}"
|
|
22
|
+
end
|
|
23
|
+
puts "api-key = #{option(:api_key).gsub(/[123456789]/, '*')} symbols-file = #{options[:symbols_file]}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def needs_key?
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def push_app
|
|
31
|
+
puts "push_app #{TAG}"
|
|
32
|
+
response = upload_app
|
|
33
|
+
if android?
|
|
34
|
+
puts response['instrumented_url']
|
|
35
|
+
instrumentedFile = download_from_url response['instrumented_url']
|
|
36
|
+
signedApk = signing_apk instrumentedFile
|
|
37
|
+
response = upload_signed_apk signedApk
|
|
38
|
+
end
|
|
39
|
+
puts "Upload success!, check your build on #{response['build_url']}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def android?
|
|
43
|
+
option(:app_file).include? "apk"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def signing_apk(instrumentedFile)
|
|
50
|
+
signed = Tempfile.new(['instrumented-signed', '.apk'])
|
|
51
|
+
zipOutput = %x[#{zip_path} -qd #{instrumentedFile} META-INF/*]
|
|
52
|
+
if zipOutput.include? 'error'
|
|
53
|
+
raise Error, zipOutput
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
jarSignerOutput = %x[#{jarsigner_path} -keystore #{option(:keystore_file)} -storepass #{option(:storepass)} -digestalg SHA1 -sigalg MD5withRSA #{instrumentedFile} #{option(:alias)}]
|
|
57
|
+
if jarSignerOutput.include? 'error'
|
|
58
|
+
raise Error, jarSignerOutput
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
verifyOutput = %x[#{jarsigner_path} -verify #{instrumentedFile}]
|
|
62
|
+
if !verifyOutput.include? 'jar verified'
|
|
63
|
+
raise Error, verifyOutput
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
zipAlignOutput = %x[#{zipalign_path} -f 4 #{instrumentedFile} #{signed.path}]
|
|
67
|
+
|
|
68
|
+
puts "signing Apk finished: #{signed.path()} (file size:#{File.size(signed.path())} )"
|
|
69
|
+
signed.path()
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def download_from_url(url)
|
|
73
|
+
puts "downloading from #{url} "
|
|
74
|
+
uri = URI.parse(url)
|
|
75
|
+
instrumentedFile = Net::HTTP.start(uri.host, uri.port) do |http|
|
|
76
|
+
resp = http.get(uri.path)
|
|
77
|
+
file = Tempfile.new(['instrumented', '.apk'])
|
|
78
|
+
file.write(resp.body)
|
|
79
|
+
file.flush
|
|
80
|
+
file
|
|
81
|
+
end
|
|
82
|
+
puts "Done #{instrumentedFile.path()} (file size:#{File.size(instrumentedFile.path())} )"
|
|
83
|
+
instrumentedFile.path()
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def upload_app
|
|
87
|
+
uploadUrl = SERVER + UPLOAD_URL_PATH
|
|
88
|
+
params = get_params
|
|
89
|
+
post uploadUrl, params
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def upload_signed_apk apkPath
|
|
93
|
+
uploadSignedUrl = SERVER + UPLOAD_SIGNED_URL_PATH
|
|
94
|
+
|
|
95
|
+
params = {"api_key" => "#{option(:api_key)}"}
|
|
96
|
+
add_file_param params , 'apk_file', apkPath
|
|
97
|
+
add_file_param params, 'symbols_file', options[:symbols_file]
|
|
98
|
+
add_param params, 'testers-groups', options[:testers_groups]
|
|
99
|
+
add_boolean_param params, 'notify', options[:notify]
|
|
100
|
+
add_boolean_param params, 'auto-update', options[:auto_update]
|
|
101
|
+
|
|
102
|
+
post uploadSignedUrl, params
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def post url, params
|
|
106
|
+
puts "Upload parameters = #{get_printable_params params} \nto #{url}"
|
|
107
|
+
uri = URI.parse(url)
|
|
108
|
+
request = Net::HTTP::Post::Multipart.new(uri.path, params, 'User-Agent' => "Travis plugin version=#{VERSION}")
|
|
109
|
+
res = Net::HTTP.start(uri.host, uri.port) do |http|
|
|
110
|
+
http.request(request)
|
|
111
|
+
end
|
|
112
|
+
puts res.body
|
|
113
|
+
resBody = JSON.parse(res.body)
|
|
114
|
+
if (resBody['status'] == 'fail')
|
|
115
|
+
raise Error, resBody['message']
|
|
116
|
+
end
|
|
117
|
+
return resBody
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def get_printable_params params
|
|
121
|
+
paramsToPrint = params.clone
|
|
122
|
+
paramsToPrint['api_key'] = paramsToPrint['api_key'].gsub(/[123456789]/, '*')
|
|
123
|
+
paramsToPrint['apk_file'] = paramsToPrint['apk_file'].path()
|
|
124
|
+
JSON.pretty_generate(paramsToPrint)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def get_params
|
|
128
|
+
params = {'api_key' => "#{option(:api_key)}"}
|
|
129
|
+
add_file_param params, 'apk_file', option(:app_file)
|
|
130
|
+
add_file_param params, 'symbols_file', options[:symbols_file]
|
|
131
|
+
add_param params, 'video-quality', options[:video_quality]
|
|
132
|
+
add_param params, 'screenshot-interval', options[:screenshot_interval]
|
|
133
|
+
add_param params, 'max-duration', options[:max_duration]
|
|
134
|
+
add_param params, 'testers-groups', options[:testers_groups]
|
|
135
|
+
add_param params, 'advanced-options', options[:advanced_options]
|
|
136
|
+
add_param params, 'metrics', options[:metrics]
|
|
137
|
+
add_boolean_param params, 'data-only-wifi', options[:data_only_wifi]
|
|
138
|
+
add_boolean_param params, 'record-on-background', options[:record_on_background]
|
|
139
|
+
add_boolean_param params, 'video', options[:video]
|
|
140
|
+
add_boolean_param params, 'notify', options[:notify]
|
|
141
|
+
add_boolean_param params, 'icon-watermark', options[:icon_watermark]
|
|
142
|
+
|
|
143
|
+
travisCommitRange = context.env.fetch('TRAVIS_COMMIT_RANGE',nil)
|
|
144
|
+
if !travisCommitRange.nil?
|
|
145
|
+
changelog = %x[git log --pretty=oneline --abbrev-commit #{travisCommitRange}]
|
|
146
|
+
add_param params, 'changelog', changelog
|
|
147
|
+
end
|
|
148
|
+
params
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def add_file_param params, fileName, filePath
|
|
152
|
+
if (!filePath.nil? && !filePath.empty?)
|
|
153
|
+
params[fileName] = UploadIO.new(File.new(filePath), "", filePath.split("/").last)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def add_param params, paramName, param
|
|
158
|
+
if (!param.nil? && !param.empty?)
|
|
159
|
+
params[paramName] = param
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def add_boolean_param params, paramName, param
|
|
164
|
+
if (!param.nil? && !param.empty?)
|
|
165
|
+
params[paramName] = (param == true) ? "on" : "off"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def zip_path
|
|
170
|
+
@zip_path ||= %x[which zip].split("\n").first
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def zipalign_path
|
|
174
|
+
android_home_path = context.env.fetch('ANDROID_HOME', '/usr')
|
|
175
|
+
@zipalign_path ||= %x[find -L #{android_home_path} -name zipalign 2>/dev/null].split("\n").first
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def jarsigner_path
|
|
179
|
+
java_home_path = context.env.fetch('JAVA_HOME', '/usr')
|
|
180
|
+
@jarsigner_path ||= %x[find -L #{java_home_path} -name jarsigner 2>/dev/null].split("\n").first
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dpl/provider/testfairy'
|
|
3
|
+
|
|
4
|
+
describe DPL::Provider::TestFairy do
|
|
5
|
+
|
|
6
|
+
before (:all) do
|
|
7
|
+
|
|
8
|
+
%x[mkdir /tmp/android/]
|
|
9
|
+
%x[echo 'cp $3 $4' > /tmp/android/zipalign]
|
|
10
|
+
%x[chmod +x /tmp/android/zipalign]
|
|
11
|
+
|
|
12
|
+
@kyestore = '/tmp/debug.keystore'
|
|
13
|
+
%x[curl -Lso #{@kyestore} http://www.testfairy.com/support-files/travis/dpl/debug.keystore]
|
|
14
|
+
|
|
15
|
+
@local_android_app = '/tmp/android.apk'
|
|
16
|
+
%x[curl -Lso #{@local_android_app} http://www.testfairy.com/support-files/travis/dpl/android.apk]
|
|
17
|
+
|
|
18
|
+
@local_ios_app = '/tmp/ios.ipa'
|
|
19
|
+
%x[curl -Lso #{@local_ios_app} http://www.testfairy.com/support-files/travis/dpl/Empty.ipa]
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
let :context do
|
|
24
|
+
DummyContext.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
subject :provider do
|
|
28
|
+
# the account is travis-test@testfairy.com
|
|
29
|
+
described_class.new(context, :api_key => '4b85a2c03ba6026f4e22640a0432638180e1d1ea', :storepass => "android", :alias => "androiddebugkey", :keystore_file => @kyestore, :video => "true", :video_quality => 'low')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#check_auth" do
|
|
33
|
+
example "check_auth without app_file" do
|
|
34
|
+
lambda {provider.check_auth}.should raise_error
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
example "check_auth with app_file" do
|
|
38
|
+
provider.options.update(:app_file => @local_android_app)
|
|
39
|
+
provider.check_auth
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#needs_key?" do
|
|
44
|
+
example do
|
|
45
|
+
expect(provider.needs_key?).to eq(false)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#push_app" do
|
|
50
|
+
before do
|
|
51
|
+
context.stub(:env) { {'ANDROID_HOME' => '/tmp/android', 'JAVA_HOME' => '/usr/bin'} }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
example "push_app without app_file" do
|
|
55
|
+
lambda {provider.push_app}.should raise_error
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
example "push_app with app_file" do
|
|
59
|
+
provider.options.update(:app_file => @local_android_app)
|
|
60
|
+
provider.push_app
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
example "push_app with wrong alias" do
|
|
64
|
+
provider.options.update(:app_file => @local_android_app)
|
|
65
|
+
provider.options.update(:alias => 'test')
|
|
66
|
+
lambda {provider.push_app}.should raise_error
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
example "push_app with wrong storepass" do
|
|
70
|
+
provider.options.update(:app_file => @local_android_app)
|
|
71
|
+
provider.options.update(:storepass => 'test')
|
|
72
|
+
lambda {provider.push_app}.should raise_error
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
example "push_app with iOS app_file" do
|
|
76
|
+
provider.options.update(:app_file => @local_ios_app)
|
|
77
|
+
provider.push_app
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dpl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.12.travis.
|
|
4
|
+
version: 1.7.12.travis.748.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-04-
|
|
11
|
+
date: 2015-04-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|
|
@@ -136,6 +136,7 @@ files:
|
|
|
136
136
|
- lib/dpl/provider/releases.rb
|
|
137
137
|
- lib/dpl/provider/rubygems.rb
|
|
138
138
|
- lib/dpl/provider/s3.rb
|
|
139
|
+
- lib/dpl/provider/testfairy.rb
|
|
139
140
|
- lib/dpl/version.rb
|
|
140
141
|
- notes/dotcloud.md
|
|
141
142
|
- notes/engine_yard.md
|
|
@@ -172,6 +173,7 @@ files:
|
|
|
172
173
|
- spec/provider/releases_spec.rb
|
|
173
174
|
- spec/provider/rubygems_spec.rb
|
|
174
175
|
- spec/provider/s3_spec.rb
|
|
176
|
+
- spec/provider/testfairy_spec.rb
|
|
175
177
|
- spec/provider_spec.rb
|
|
176
178
|
- spec/spec_helper.rb
|
|
177
179
|
homepage: https://github.com/travis-ci/dpl
|