hockeyapp 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +45 -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 +118 -0
- data/lib/hockeyapp/models/crash.rb +44 -0
- data/lib/hockeyapp/models/crash_group.rb +36 -0
- data/lib/hockeyapp/models/version.rb +91 -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 +96 -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 +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NzMwMzc2ODYwMGRiMTQzYmIzNzBjOTUzYmI0ODk1NGMyNGE2ZmQ2Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Yzk3ZmQ1MDg1MDI1YmI5YmU3MThiMzExMDJkOWQ1ZTA2ODk1MDI1OQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGQ2NWMyMTI5MzU2NDViMDM2ZDk0ODgyYzY0YzY5YzFhYzlhMmYwN2E3M2Uw
|
10
|
+
YjdhNjE4NjgyY2YyODE1YWE5MmI1ZGI5NDRmNTdiYzQ5MmZlZjAwODQ3NWZi
|
11
|
+
NjU5NTY3MWVkMTM1YzM0MDRiMmEzMmExNmFiZjMwOGVhYmM5ZWU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZGI5YzZlMTc0ZDZiODQyMGJkYmFiMDdiZjc0ZjEzZGI3ZWVkMTIyMGNhNTk3
|
14
|
+
NjA2MjNhMWNhOTNiNDFjODFlYmJhNjczN2M0ODE1YTg3MjFiMTIyMmU1NjMw
|
15
|
+
NTA3NjFmMTExNDA5Y2JmOWVlMTRmNGRhYTA1MTUwZmI0OWQ1MGI=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# HockeyApp gem
|
2
|
+
|
3
|
+
This gem enables you to easily access the JSON Rest API of http://www.hockeyapp.net.
|
4
|
+
|
5
|
+
More info available on this API here : http://support.hockeyapp.net/kb/api
|
6
|
+
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
### Configure your connection
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
HockeyApp::Config.configure do |config|
|
14
|
+
config.token = "ABCDEF"
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
### Make a client
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
client = HockeyApp.build_client
|
22
|
+
```
|
23
|
+
|
24
|
+
### Use the client
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
apps = client.get_apps
|
28
|
+
versions = apps.first.versions
|
29
|
+
crashes = apps.first.crashes
|
30
|
+
```
|
31
|
+
|
32
|
+
## Documentation
|
33
|
+
|
34
|
+
### Uploading a new version
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
@client ||= HockeyApp.build_client
|
38
|
+
|
39
|
+
app = HockeyApp::App.new(@client)
|
40
|
+
app.public_identifier = "aklsdjklajsd"
|
41
|
+
version = HockeyApp::Version.new(app, @client)
|
42
|
+
version.ipa = File.new('./app.ipa', 'r')
|
43
|
+
version.dsym = File.new('./dsym.dSYM.zip', 'r')
|
44
|
+
version = @client.post_new_version version
|
45
|
+
```
|
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,118 @@
|
|
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 = ""
|
95
|
+
version = Version.new(self, @client)
|
96
|
+
version.ipa = file
|
97
|
+
version.notes = release_notes
|
98
|
+
client.post_new_version version
|
99
|
+
@versions = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def remove
|
103
|
+
client.remove_app self
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
attr_reader :client
|
111
|
+
|
112
|
+
def url_strategy
|
113
|
+
return HockeyApp::IOSAppUrls.new(self) if platform == IOS
|
114
|
+
return HockeyApp::AndroidAppUrls.new(self) if platform == ANDROID
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
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,91 @@
|
|
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 => false,
|
20
|
+
1 => true
|
21
|
+
}
|
22
|
+
|
23
|
+
STATUS_TO_SYM = {
|
24
|
+
1 => :deny,
|
25
|
+
2 => :allow
|
26
|
+
}
|
27
|
+
|
28
|
+
attr_accessor *ATTRIBUTES
|
29
|
+
attr_accessor *POST_PAYLOAD
|
30
|
+
attr_reader :app
|
31
|
+
|
32
|
+
validates :notes_type, :inclusion => { :in =>NOTES_TYPES_TO_SYM.keys }
|
33
|
+
validates :notify, :inclusion => { :in => NOTIFY_TO_BOOL.keys }
|
34
|
+
validates :status, :inclusion => { :in => STATUS_TO_SYM.keys }
|
35
|
+
|
36
|
+
|
37
|
+
def self.from_hash(h, app, client)
|
38
|
+
res = self.new app, client
|
39
|
+
ATTRIBUTES.each do |attribute|
|
40
|
+
res.send("#{attribute.to_s}=", h[attribute.to_s]) unless (h[attribute.to_s].nil?)
|
41
|
+
end
|
42
|
+
res
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize app, client
|
46
|
+
@app = app
|
47
|
+
@client = client
|
48
|
+
default_values!
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def to_key
|
53
|
+
[@id] if persisted?
|
54
|
+
end
|
55
|
+
|
56
|
+
def crashes
|
57
|
+
@crashes ||= @app.crashes.select{|crash| "#{crash.app_version_id}" == @id.to_s}
|
58
|
+
end
|
59
|
+
|
60
|
+
def crash_reasons
|
61
|
+
@crash_groups ||= @app.crash_reasons.select{|crash_reason| "#{crash_reason.app_version_id}" == @id.to_s}
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def direct_download_url
|
66
|
+
url_strategy.direct_download_url
|
67
|
+
end
|
68
|
+
|
69
|
+
def install_url
|
70
|
+
url_strategy.install_url
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
attr_reader :client
|
76
|
+
|
77
|
+
def default_values!
|
78
|
+
@dsym=nil
|
79
|
+
@notes="New version"
|
80
|
+
@notes_type=Version::NOTES_TYPES_TO_SYM.invert[:textile]
|
81
|
+
@notify=Version::NOTIFY_TO_BOOL.invert[false]
|
82
|
+
@status=Version::STATUS_TO_SYM.invert[:allow]
|
83
|
+
end
|
84
|
+
|
85
|
+
def url_strategy
|
86
|
+
return HockeyApp::IOSVersionUrls.new(self) if app.platform == HockeyApp::App::IOS
|
87
|
+
return HockeyApp::AndroidVersionUrls.new(self) if app.platform == HockeyApp::App::ANDROID
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|