hockeyapp-aszmyd 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +53 -0
- data/README.md +37 -0
- data/Rakefile +1 -0
- data/hockeyapp.gemspec +33 -0
- data/lib/hockeyapp.rb +25 -0
- data/lib/hockeyapp/config.rb +18 -0
- data/lib/hockeyapp/models/active_model_compliance.rb +10 -0
- data/lib/hockeyapp/models/app.rb +121 -0
- data/lib/hockeyapp/models/crash.rb +44 -0
- data/lib/hockeyapp/models/crash_group.rb +36 -0
- data/lib/hockeyapp/models/version.rb +92 -0
- data/lib/hockeyapp/services/android_urls.rb +30 -0
- data/lib/hockeyapp/services/ios_urls.rb +35 -0
- data/lib/hockeyapp/ws/client.rb +72 -0
- data/lib/hockeyapp/ws/ws.rb +98 -0
- data/spec/config_spec.rb +35 -0
- data/spec/hockey_app_spec.rb +13 -0
- data/spec/models/app_spec.rb +143 -0
- data/spec/models/crash_group_spec.rb +53 -0
- data/spec/models/crash_spec.rb +77 -0
- data/spec/models/version_spec.rb +85 -0
- data/spec/support/active_model_lint.rb +19 -0
- data/spec/support/fake_ws.rb +54 -0
- data/spec/support/responses/app.json +83 -0
- data/spec/support/responses/app_versions.json +34 -0
- data/spec/support/responses/apps.json +22 -0
- data/spec/support/responses/crash_groups.json +43 -0
- data/spec/support/responses/crashes.json +45 -0
- data/spec/support/responses/new_app.json +12 -0
- data/spec/support/responses/new_version.json +13 -0
- data/spec/support/rspec_helper.rb +18 -0
- data/spec/ws/client_spec.rb +153 -0
- data/spec/ws/ws_spec.rb +32 -0
- metadata +198 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hockeyapp (0.0.15)
|
5
|
+
activemodel
|
6
|
+
awesome_print
|
7
|
+
httmultiparty
|
8
|
+
multi_json
|
9
|
+
rake
|
10
|
+
rspec
|
11
|
+
simplecov
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: http://rubygems.org/
|
15
|
+
specs:
|
16
|
+
activemodel (3.2.3)
|
17
|
+
activesupport (= 3.2.3)
|
18
|
+
builder (~> 3.0.0)
|
19
|
+
activesupport (3.2.3)
|
20
|
+
i18n (~> 0.6)
|
21
|
+
multi_json (~> 1.0)
|
22
|
+
awesome_print (1.0.2)
|
23
|
+
builder (3.0.0)
|
24
|
+
diff-lcs (1.1.3)
|
25
|
+
httmultiparty (0.3.7)
|
26
|
+
httparty (>= 0.7.3)
|
27
|
+
multipart-post
|
28
|
+
httparty (0.8.3)
|
29
|
+
multi_json (~> 1.0)
|
30
|
+
multi_xml
|
31
|
+
i18n (0.6.0)
|
32
|
+
multi_json (1.3.4)
|
33
|
+
multi_xml (0.5.1)
|
34
|
+
multipart-post (1.1.5)
|
35
|
+
rake (0.9.2.2)
|
36
|
+
rspec (2.9.0)
|
37
|
+
rspec-core (~> 2.9.0)
|
38
|
+
rspec-expectations (~> 2.9.0)
|
39
|
+
rspec-mocks (~> 2.9.0)
|
40
|
+
rspec-core (2.9.0)
|
41
|
+
rspec-expectations (2.9.1)
|
42
|
+
diff-lcs (~> 1.1.3)
|
43
|
+
rspec-mocks (2.9.0)
|
44
|
+
simplecov (0.6.4)
|
45
|
+
multi_json (~> 1.0)
|
46
|
+
simplecov-html (~> 0.5.3)
|
47
|
+
simplecov-html (0.5.3)
|
48
|
+
|
49
|
+
PLATFORMS
|
50
|
+
ruby
|
51
|
+
|
52
|
+
DEPENDENCIES
|
53
|
+
hockeyapp!
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
HockeyApp gem
|
2
|
+
=============
|
3
|
+
|
4
|
+
This gem enables you to easily access the JSON Rest API of http://www.hockeyapp.net.
|
5
|
+
|
6
|
+
More info available on this API here : http://support.hockeyapp.net/kb/api
|
7
|
+
|
8
|
+
|
9
|
+
HOW-TO
|
10
|
+
======
|
11
|
+
|
12
|
+
1° Configure your connection :
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
HockeyApp::Config.configure do |config|
|
16
|
+
config.token = "ABCDEF"
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
2° Make a client
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
client = HockeyApp.build_client
|
24
|
+
```
|
25
|
+
|
26
|
+
3° Use the client
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
apps = client.get_apps
|
30
|
+
versions = apps.first.versions
|
31
|
+
crashes = apps.first.crashes
|
32
|
+
....
|
33
|
+
```
|
34
|
+
|
35
|
+
4° Read the specs for more use cases
|
36
|
+
|
37
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/hockeyapp.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "hockeyapp"
|
6
|
+
s.version = "0.0.15"
|
7
|
+
s.authors = ["Philippe Van Eerdenbrugghe", "Paul Renson"]
|
8
|
+
s.email = ["philippe.vaneerdenbrugghe@tapptic.com", "paul.renson.ext@tapptic.com"]
|
9
|
+
s.homepage = ""
|
10
|
+
s.summary = %q{Wrapper for the hockeyapp REST API}
|
11
|
+
s.description = %q{This simple wrapper enables you to acces the hockeyapp REST API through simple ruby calls. You are rquired to configure a valid token before doing anyhting else}
|
12
|
+
|
13
|
+
s.rubyforge_project = "hockeyapp"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
s.add_runtime_dependency "rspec"
|
24
|
+
s.add_runtime_dependency "simplecov"
|
25
|
+
s.add_runtime_dependency "awesome_print"
|
26
|
+
s.add_runtime_dependency "rake"
|
27
|
+
s.add_runtime_dependency "multi_json"
|
28
|
+
|
29
|
+
|
30
|
+
s.add_runtime_dependency "httmultiparty"""
|
31
|
+
s.add_runtime_dependency "activemodel"
|
32
|
+
|
33
|
+
end
|
data/lib/hockeyapp.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_model'
|
3
|
+
require 'hockeyapp/models/active_model_compliance'
|
4
|
+
require "hockeyapp/models/app"
|
5
|
+
require 'hockeyapp/models/crash'
|
6
|
+
require 'hockeyapp/models/version'
|
7
|
+
require 'hockeyapp/models/crash_group'
|
8
|
+
require 'hockeyapp/ws/ws'
|
9
|
+
require 'hockeyapp/ws/client'
|
10
|
+
require 'hockeyapp/config'
|
11
|
+
require 'hockeyapp/services/android_urls'
|
12
|
+
require 'hockeyapp/services/ios_urls'
|
13
|
+
|
14
|
+
module HockeyApp
|
15
|
+
extend self
|
16
|
+
|
17
|
+
def build_client options = {}
|
18
|
+
ws = WS.new options
|
19
|
+
Client.new ws
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module HockeyApp
|
2
|
+
module Config
|
3
|
+
extend self
|
4
|
+
|
5
|
+
ATTRIBUTES = [:token, :base_uri]
|
6
|
+
|
7
|
+
attr_accessor *ATTRIBUTES
|
8
|
+
|
9
|
+
def configure
|
10
|
+
yield self
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
Hash[ATTRIBUTES.map{|a|[a, self.send("#{a.to_s}")]}]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module HockeyApp
|
2
|
+
class App
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include ActiveModelCompliance
|
7
|
+
|
8
|
+
ANDROID = 'Android'
|
9
|
+
IOS = 'iOS'
|
10
|
+
|
11
|
+
ATTRIBUTES = [:title, :minimum_os_version, :status, :company, :owner, :bundle_identifier, :device_family, :platform,
|
12
|
+
:public_identifier, :role, :release_type]
|
13
|
+
|
14
|
+
POST_PAYLOAD = [:status,:notes_type, :notify]
|
15
|
+
|
16
|
+
NOTES_TYPES_TO_SYM = {
|
17
|
+
0 => :textile,
|
18
|
+
1 => :markdown
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
NOTIFY_TO_BOOL = {
|
23
|
+
0 => false,
|
24
|
+
1 => true
|
25
|
+
}
|
26
|
+
|
27
|
+
STATUS_TO_SYM = {
|
28
|
+
1 => :deny,
|
29
|
+
2 => :allow
|
30
|
+
}
|
31
|
+
|
32
|
+
attr_accessor *ATTRIBUTES
|
33
|
+
attr_accessor *POST_PAYLOAD
|
34
|
+
|
35
|
+
|
36
|
+
validates :notes_type, :inclusion => { :in =>NOTES_TYPES_TO_SYM.keys }
|
37
|
+
validates :notify, :inclusion => { :in => NOTIFY_TO_BOOL.keys }
|
38
|
+
validates :status, :inclusion => { :in => STATUS_TO_SYM.keys }
|
39
|
+
|
40
|
+
|
41
|
+
def self.from_hash(h, client)
|
42
|
+
res = self.new client
|
43
|
+
ATTRIBUTES.each do |attribute|
|
44
|
+
res.send("#{attribute.to_s}=", h[attribute.to_s]) unless (h[attribute.to_s].nil?)
|
45
|
+
end
|
46
|
+
res
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize client
|
50
|
+
@client = client
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_key
|
54
|
+
[public_identifier] if persisted?
|
55
|
+
end
|
56
|
+
|
57
|
+
def platform= platform
|
58
|
+
@platform = platform
|
59
|
+
end
|
60
|
+
|
61
|
+
def crashes
|
62
|
+
@crashes ||= client.get_crashes(self)
|
63
|
+
end
|
64
|
+
|
65
|
+
def crash_reasons
|
66
|
+
@crash_reasons ||= client.get_crash_groups(self)
|
67
|
+
end
|
68
|
+
|
69
|
+
def versions
|
70
|
+
@versions ||= client.get_versions(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
def last_version
|
74
|
+
sorted_version = versions.sort_by { |v| v.version.to_i}
|
75
|
+
sorted_version.last
|
76
|
+
end
|
77
|
+
|
78
|
+
def icon
|
79
|
+
"https://rink.hockeyapp.net/api/2/apps/#{public_identifier}?format=png"
|
80
|
+
end
|
81
|
+
|
82
|
+
def download_url
|
83
|
+
last_version.download_url
|
84
|
+
end
|
85
|
+
|
86
|
+
def direct_download_url
|
87
|
+
url_strategy.direct_download_url
|
88
|
+
end
|
89
|
+
|
90
|
+
def install_url
|
91
|
+
url_strategy.install_url
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_version file, release_notes = "", notify = :none, status = :allow , tags = ""
|
95
|
+
version = Version.new(self, @client)
|
96
|
+
version.ipa = file
|
97
|
+
version.notes = release_notes
|
98
|
+
version.notify = notify
|
99
|
+
version.status = status
|
100
|
+
version.tags = tags
|
101
|
+
client.post_new_version version
|
102
|
+
@versions = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def remove
|
106
|
+
client.remove_app self
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
attr_reader :client
|
114
|
+
|
115
|
+
def url_strategy
|
116
|
+
return HockeyApp::IOSAppUrls.new(self) if platform == IOS
|
117
|
+
return HockeyApp::AndroidAppUrls.new(self) if platform == ANDROID
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module HockeyApp
|
2
|
+
class Crash
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include ActiveModelCompliance
|
7
|
+
|
8
|
+
ATTRIBUTES = [:crash_reason_id, :id, :jail_break, :created_at, :updated_at, :contact_string, :app_id, :bundle_version,
|
9
|
+
:app_version_id, :user_string, :has_description, :bundle_short_version, :has_log, :model, :oem, :os_version]
|
10
|
+
|
11
|
+
attr_accessor *ATTRIBUTES
|
12
|
+
attr_reader :app
|
13
|
+
|
14
|
+
|
15
|
+
def self.from_hash(h, app, client)
|
16
|
+
res = self.new app, client
|
17
|
+
ATTRIBUTES.each do |attribute|
|
18
|
+
res.send("#{attribute.to_s}=", h[attribute.to_s]) unless (h[attribute.to_s].nil?)
|
19
|
+
end
|
20
|
+
res
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize app, client
|
24
|
+
@app = app
|
25
|
+
@client = client
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def log
|
30
|
+
@log ||= client.get_crash_log(self) if has_log
|
31
|
+
end
|
32
|
+
|
33
|
+
def description
|
34
|
+
@description ||= client.get_crash_description(self) if has_description
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_accessor :client
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module HockeyApp
|
2
|
+
class CrashGroup
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include ActiveModelCompliance
|
7
|
+
|
8
|
+
ATTRIBUTES = [:file, :reason, :status, :id, :crash_class, :bundle_version, :last_crash_at, :app_version_id,
|
9
|
+
:line, :updated_at, :method, :bundle_short_version, :number_of_crashes, :fixed, :created_at, :app_id]
|
10
|
+
|
11
|
+
|
12
|
+
attr_accessor *ATTRIBUTES
|
13
|
+
attr_reader :application
|
14
|
+
|
15
|
+
|
16
|
+
def self.from_hash(h, app, client)
|
17
|
+
res = self.new app, client
|
18
|
+
ATTRIBUTES.each do |attribute|
|
19
|
+
res.send("#{attribute.to_s}=", h[attribute.to_s]) unless (h[attribute.to_s].nil?)
|
20
|
+
end
|
21
|
+
res.send("crash_class=", h['class']) unless h['class'].nil? # we should not override the #class method
|
22
|
+
res
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize application, client
|
26
|
+
@application = application
|
27
|
+
@client = client
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :client
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module HockeyApp
|
2
|
+
class Version
|
3
|
+
extend ActiveModel::Naming
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include ActiveModelCompliance
|
7
|
+
|
8
|
+
ATTRIBUTES = [:id, :notes, :shortversion, :version, :mandatory, :timestamp, :appsize, :title, :download_url]
|
9
|
+
|
10
|
+
POST_PAYLOAD = [:status, :ipa, :dsym, :notes_type, :notify, :tags]
|
11
|
+
|
12
|
+
NOTES_TYPES_TO_SYM = {
|
13
|
+
0 => :textile,
|
14
|
+
1 => :markdown
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
NOTIFY_TO_BOOL = {
|
19
|
+
0 => :none,
|
20
|
+
1 => :all_allowed,
|
21
|
+
2 => :all
|
22
|
+
}
|
23
|
+
|
24
|
+
STATUS_TO_SYM = {
|
25
|
+
1 => :deny,
|
26
|
+
2 => :allow
|
27
|
+
}
|
28
|
+
|
29
|
+
attr_accessor *ATTRIBUTES
|
30
|
+
attr_accessor *POST_PAYLOAD
|
31
|
+
attr_reader :app
|
32
|
+
|
33
|
+
validates :notes_type, :inclusion => { :in =>NOTES_TYPES_TO_SYM.keys }
|
34
|
+
validates :notify, :inclusion => { :in => NOTIFY_TO_BOOL.keys }
|
35
|
+
validates :status, :inclusion => { :in => STATUS_TO_SYM.keys }
|
36
|
+
|
37
|
+
|
38
|
+
def self.from_hash(h, app, client)
|
39
|
+
res = self.new app, client
|
40
|
+
ATTRIBUTES.each do |attribute|
|
41
|
+
res.send("#{attribute.to_s}=", h[attribute.to_s]) unless (h[attribute.to_s].nil?)
|
42
|
+
end
|
43
|
+
res
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize app, client
|
47
|
+
@app = app
|
48
|
+
@client = client
|
49
|
+
default_values!
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def to_key
|
54
|
+
[@id] if persisted?
|
55
|
+
end
|
56
|
+
|
57
|
+
def crashes
|
58
|
+
@crashes ||= @app.crashes.select{|crash| "#{crash.app_version_id}" == @id.to_s}
|
59
|
+
end
|
60
|
+
|
61
|
+
def crash_reasons
|
62
|
+
@crash_groups ||= @app.crash_reasons.select{|crash_reason| "#{crash_reason.app_version_id}" == @id.to_s}
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def direct_download_url
|
67
|
+
url_strategy.direct_download_url
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_url
|
71
|
+
url_strategy.install_url
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_reader :client
|
77
|
+
|
78
|
+
def default_values!
|
79
|
+
@dsym=nil
|
80
|
+
@notes="New version"
|
81
|
+
@notes_type=Version::NOTES_TYPES_TO_SYM.invert[:textile]
|
82
|
+
@notify=Version::NOTIFY_TO_BOOL.invert[:none]
|
83
|
+
@status=Version::STATUS_TO_SYM.invert[:allow]
|
84
|
+
end
|
85
|
+
|
86
|
+
def url_strategy
|
87
|
+
return HockeyApp::IOSVersionUrls.new(self) if app.platform == HockeyApp::App::IOS
|
88
|
+
return HockeyApp::AndroidVersionUrls.new(self) if app.platform == HockeyApp::App::ANDROID
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|