crep 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 6ec9983a55f99437b47855a38a35de0748a1fb8023dca8ef5f3f973b9be87919
4
- data.tar.gz: e3830e5d8609c2aa9d1808d4d82218d7a44172b207f3fde619462c1cd38adddd
2
+ SHA1:
3
+ metadata.gz: 92ca99da70b9b006895c218f962edea42d463d35
4
+ data.tar.gz: 282e8f310eaabe35d01e2c46cc9b93f0f132ad34
5
5
  SHA512:
6
- metadata.gz: b3b1687053ac8aae4f85872331f9e16e632769765d6ca598556dd2adc76d048e68cafbe4fa0c2c0a205f0307d702c9196e73221ce9b5e3e214df24af39f3e7b0
7
- data.tar.gz: 1d0ea2b9eee605d398f8e600a2bbd31698f8e44ade452862cdccfb856f96013ef8dde8454de33ee23d8d330fdb710ca0ecd79945bec282bcbdbb9fa7b7a1995c
6
+ metadata.gz: 72c1e5f118d38112e5ad84b1a48b261948074cad36119be45b0a298445b7cba475d10720bf66395b9304e3e15031b21e12f6850df0e85d41d5f12ca8f227195b
7
+ data.tar.gz: 7a7e2a8cc83a8313750e97f9567a24f6c70d9cf9550e9c34e8bf2d4d235a857473a49b2db720fa5a6820a06170551d99eac966830670ede19df023248dc826c3
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: circleci/ruby:2.4.1
6
+ steps:
7
+ - checkout
8
+ - run:
9
+ name: Install dependencies
10
+ command: bundle install
11
+
12
+ - run:
13
+ name: Run the tests
14
+ command: bundle exec rspec
15
+
16
+ - run:
17
+ name: Run Danger
18
+ command: bundle exec danger
19
+ when: always
20
+ notify:
21
+ webhooks:
22
+ - url: https://alethea3000.herokuapp.com/post/circle
@@ -0,0 +1,6 @@
1
+ <!--
2
+ Please let us know what version of Crep you are using, so we can better pinpoint and/or solve your issue.
3
+ Please also provide the command you ran and what you expected to happen (or in case of an unexpected crash, the crash log).
4
+
5
+ Also please make sure your title and description describe your problem as clearly as possible. Questions end with a question mark.
6
+ -->
@@ -0,0 +1,10 @@
1
+ <!--
2
+ First of all, thank you for contributing to Crep! 🎉
3
+
4
+ If your pull request fixes an issue, please reference the issue.
5
+ For example, when your pull request fixes issue 10, add the following line:
6
+
7
+ Fixes #10
8
+
9
+ This will make sure that when the pull request is merged, the issue will automatically be closed.
10
+ -->
data/.gitignore CHANGED
@@ -2,7 +2,6 @@
2
2
  *.rbc
3
3
  /.bundle/
4
4
  /.yardoc
5
- /Gemfile.lock
6
5
  /.config
7
6
  /_yardoc/
8
7
  /coverage/
@@ -58,3 +57,6 @@ build-iPhoneSimulator/
58
57
  .rvmrc
59
58
 
60
59
  .DS_Store
60
+
61
+ # vim swp files
62
+ *.swp
@@ -0,0 +1 @@
1
+ 2.3.0
@@ -2,20 +2,31 @@
2
2
 
3
3
  ## Added
4
4
 
5
- -
6
-
7
5
  ## Removed
8
6
 
9
- -
7
+ ## Fixed
8
+
9
+ ## Miscellaneous
10
+
11
+ # v1.0.0
12
+
13
+ ## Added
14
+
15
+ - Added an `apps` command that shows a list of available apps.
16
+ - Added a warning when multiple versions of an app are found.
17
+ - Added colorful output to the message stating if there was no version found.
18
+ - Added deep link support to HockeyApp reporting.
19
+ - Added the possibility to use ERB templates to generate a report layout.
20
+ - Added the ability to supply a custom template for the crash report via a command line argument, `--template`.
21
+
22
+ ## Removed
10
23
 
11
24
  ## Fixed
12
25
 
13
- -
26
+ - Fixed an invalid identifier producing a bogus error (#46)
14
27
 
15
28
  ## Miscellaneous
16
29
 
17
- -
18
-
19
- # 0.1.0
30
+ # v0.1.0
20
31
 
21
32
  - Initial release.
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run rubocop
4
+ rubocop.lint
5
+
6
+ not_declared_trivial = !github.pr_title.include?('trivial')
7
+
8
+ has_lib_changes = !git.modified_files.grep(/lib/).empty?
9
+ has_fixture_changes = !git.modified_files.grep(/fixtures/).empty?
10
+ no_readme_changes = !git.modified_files.include?('Readme.md')
11
+
12
+ no_changelog_entry = !git.modified_files.include?('Changelog.md')
13
+
14
+ warn('PR is classed as Work in Progress') if github.pr_title.include? 'WIP'
15
+ warn('Big PR') if git.lines_of_code > 500
16
+
17
+ if has_lib_changes && no_changelog_entry && not_declared_trivial
18
+ warn('Any changes to library code should be reflected in the Changelog. Please consider adding a note there.')
19
+ end
20
+
21
+ if has_fixture_changes && no_readme_changes
22
+ raise("Any changes in the fixtures should be reflected in the Readme's usage example.")
23
+ end
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Crep's dependencies in crep.gemspec
@@ -5,3 +7,6 @@ gemspec
5
7
 
6
8
  # contains Support for Statistics
7
9
  gem 'hockeyapp', git: 'https://github.com/q231950/hockeyapp.git'
10
+
11
+ gem 'danger'
12
+ gem 'danger-rubocop'
@@ -0,0 +1,157 @@
1
+ GIT
2
+ remote: https://github.com/q231950/hockeyapp.git
3
+ revision: 67bdabfdae885e59c977cf30765ac6346dd0ab57
4
+ specs:
5
+ hockeyapp (0.0.17)
6
+ activemodel
7
+ awesome_print
8
+ httmultiparty
9
+ multi_json
10
+ rake
11
+ rspec
12
+ simplecov
13
+
14
+ PATH
15
+ remote: .
16
+ specs:
17
+ crep (1.0.0)
18
+ claide (~> 1.0.0)
19
+ colorize
20
+ hockeyapp
21
+
22
+ GEM
23
+ remote: https://rubygems.org/
24
+ specs:
25
+ activemodel (5.1.4)
26
+ activesupport (= 5.1.4)
27
+ activesupport (5.1.4)
28
+ concurrent-ruby (~> 1.0, >= 1.0.2)
29
+ i18n (~> 0.7)
30
+ minitest (~> 5.1)
31
+ tzinfo (~> 1.1)
32
+ addressable (2.5.2)
33
+ public_suffix (>= 2.0.2, < 4.0)
34
+ ast (2.3.0)
35
+ awesome_print (1.8.0)
36
+ byebug (9.1.0)
37
+ claide (1.0.2)
38
+ claide-plugins (0.9.2)
39
+ cork
40
+ nap
41
+ open4 (~> 1.3)
42
+ coderay (1.1.2)
43
+ colored2 (3.1.2)
44
+ colorize (0.8.1)
45
+ concurrent-ruby (1.0.5)
46
+ cork (0.3.0)
47
+ colored2 (~> 3.1)
48
+ danger (5.5.6)
49
+ claide (~> 1.0)
50
+ claide-plugins (>= 0.9.2)
51
+ colored2 (~> 3.1)
52
+ cork (~> 0.1)
53
+ faraday (~> 0.9)
54
+ faraday-http-cache (~> 1.0)
55
+ git (~> 1)
56
+ kramdown (~> 1.5)
57
+ no_proxy_fix
58
+ octokit (~> 4.7)
59
+ terminal-table (~> 1)
60
+ danger-rubocop (0.6.0)
61
+ danger
62
+ rubocop
63
+ diff-lcs (1.3)
64
+ docile (1.1.5)
65
+ faraday (0.13.1)
66
+ multipart-post (>= 1.2, < 3)
67
+ faraday-http-cache (1.3.1)
68
+ faraday (~> 0.8)
69
+ git (1.3.0)
70
+ httmultiparty (0.3.16)
71
+ httparty (>= 0.7.3)
72
+ mimemagic
73
+ multipart-post
74
+ httparty (0.15.6)
75
+ multi_xml (>= 0.5.2)
76
+ i18n (0.9.3)
77
+ concurrent-ruby (~> 1.0)
78
+ json (2.1.0)
79
+ kramdown (1.16.2)
80
+ method_source (0.9.0)
81
+ mimemagic (0.3.2)
82
+ minitest (5.11.3)
83
+ multi_json (1.13.1)
84
+ multi_xml (0.6.0)
85
+ multipart-post (2.0.0)
86
+ nap (1.1.0)
87
+ no_proxy_fix (0.1.2)
88
+ octokit (4.8.0)
89
+ sawyer (~> 0.8.0, >= 0.5.3)
90
+ open4 (1.3.4)
91
+ parallel (1.12.0)
92
+ parser (2.4.0.2)
93
+ ast (~> 2.3)
94
+ powerpack (0.1.1)
95
+ pry (0.11.2)
96
+ coderay (~> 1.1.0)
97
+ method_source (~> 0.9.0)
98
+ pry-byebug (3.5.1)
99
+ byebug (~> 9.1)
100
+ pry (~> 0.10)
101
+ public_suffix (3.0.1)
102
+ rainbow (2.2.2)
103
+ rake
104
+ rake (10.5.0)
105
+ rspec (3.7.0)
106
+ rspec-core (~> 3.7.0)
107
+ rspec-expectations (~> 3.7.0)
108
+ rspec-mocks (~> 3.7.0)
109
+ rspec-core (3.7.0)
110
+ rspec-support (~> 3.7.0)
111
+ rspec-expectations (3.7.0)
112
+ diff-lcs (>= 1.2.0, < 2.0)
113
+ rspec-support (~> 3.7.0)
114
+ rspec-mocks (3.7.0)
115
+ diff-lcs (>= 1.2.0, < 2.0)
116
+ rspec-support (~> 3.7.0)
117
+ rspec-support (3.7.0)
118
+ rubocop (0.51.0)
119
+ parallel (~> 1.10)
120
+ parser (>= 2.3.3.1, < 3.0)
121
+ powerpack (~> 0.1)
122
+ rainbow (>= 2.2.2, < 3.0)
123
+ ruby-progressbar (~> 1.7)
124
+ unicode-display_width (~> 1.0, >= 1.0.1)
125
+ ruby-progressbar (1.9.0)
126
+ sawyer (0.8.1)
127
+ addressable (>= 2.3.5, < 2.6)
128
+ faraday (~> 0.8, < 1.0)
129
+ simplecov (0.15.1)
130
+ docile (~> 1.1.0)
131
+ json (>= 1.8, < 3)
132
+ simplecov-html (~> 0.10.0)
133
+ simplecov-html (0.10.2)
134
+ terminal-table (1.8.0)
135
+ unicode-display_width (~> 1.1, >= 1.1.1)
136
+ thread_safe (0.3.6)
137
+ tzinfo (1.2.4)
138
+ thread_safe (~> 0.1)
139
+ unicode-display_width (1.3.0)
140
+
141
+ PLATFORMS
142
+ ruby
143
+
144
+ DEPENDENCIES
145
+ bundler (~> 1.15)
146
+ crep!
147
+ danger
148
+ danger-rubocop
149
+ hockeyapp!
150
+ pry
151
+ pry-byebug
152
+ rake (~> 10.0)
153
+ rspec
154
+ rubocop (= 0.51.0)
155
+
156
+ BUNDLED WITH
157
+ 1.16.1
data/Rakefile CHANGED
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  task default: :spec
@@ -0,0 +1,78 @@
1
+ # Crep
2
+
3
+ [![CircleCI](https://circleci.com/gh/xing/crep.svg?style=svg)](https://circleci.com/gh/xing/crep)
4
+
5
+ *Crep - a Crash Reporter for creating appealing Crash Reports*
6
+
7
+ ![the crab logo](assets/logo_small.png)
8
+
9
+ We use Crep at [XING](https://www.xing.com) to create our Crash Newsletters for [iOS](https://www.xing.com/ios) and [Android](https://www.xing.com/android) within the _Mobile Releases Team_. It currently uses [HockeyApp](https://rink.hockeyapp.net) as a crash source, so if you are using Hockey, you should definitely give Crep a try.
10
+
11
+ In case you are creating Crash Reports and have a different crash source in mind - check out the contributing section!
12
+
13
+ ## Install
14
+
15
+ Please follow our guide in the [Installation Instructions](https://github.com/xing/crep/wiki/Install).
16
+
17
+ ## Usage
18
+
19
+ Provide a `CREP_HOCKEY_API_TOKEN`:
20
+
21
+ `export CREP_HOCKEY_API_TOKEN='abcde'`
22
+
23
+ Run Crep:
24
+
25
+ `bundle exec crep crashes --identifier='com.example.company' --version='1.23.0' --build='42' --only-unresolved`
26
+
27
+ The `--only-unresolved` flag filters out any crashes marked as resolved.
28
+
29
+ [ERB](http://www.stuartellis.name/articles/erb/) templates are used for the crash report layout.
30
+ You can either use the [supplied template](https://github.com/xing/crep/blob/master/templates/default_crash_report.txt.erb) in the templates folder
31
+ or specify your own via a command line argument.
32
+ Example: `bundle exec crep crashes --identifier .... --template=<path to your template>`
33
+
34
+ **This is what [Crep output](https://github.com/xing/crep/blob/master/spec/fixtures/report_output.txt) can look like:**
35
+
36
+ ```
37
+ Reporting for YourApp (0.17.1/1114) your.bundle.identifier
38
+ ------------- #1 --------------
39
+ Class: SomeWeirdClass
40
+ First appeared on 2017-07-14 and occurred 50 times in 0.17.1
41
+ Percentage: 12.5% of all 0.17.1 crashes
42
+ File/Line: line:123
43
+ Reason: Unknown
44
+ Link: https://my.crash.url
45
+ Deep Link: hockeyapp-coach://view-crash/app_id/reason_id/latest
46
+
47
+ ------------- #2 --------------
48
+ Class: SomeOtherClass
49
+ First appeared on 2017-07-14 and occurred 100 times in 0.17.1
50
+ Percentage: 25.0% of all 0.17.1 crashes
51
+ File/Line: line:123
52
+ Reason: Unknown
53
+ Link: https://my.crash.url
54
+ Deep Link: hockeyapp-coach://view-crash/app_id/reason_id/latest
55
+ ```
56
+
57
+ ## Test
58
+
59
+ Run `bundle exec rspec` in order to run the tests.
60
+
61
+ ## Contributing
62
+
63
+ 🎁 Bug reports and pull requests for new features are most welcome!
64
+
65
+ 👷🏼 In case you want to use a different crash source - feel free to add on, we are looking forward to your pull request, we'd love to help!
66
+
67
+ You can help by doing any of the following:
68
+
69
+ - Reviewing pull requests
70
+ - Bringing ideas for the new features
71
+ - Answering questions on issues
72
+ - Improving documentation
73
+
74
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant code](http://contributor-covenant.org/) of conduct.
75
+
76
+ ## License
77
+
78
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Vision.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Goals
2
2
 
3
- - Add newsletter templating to easily create a readable and actionable format for sharing crashes.
3
+ - Add templating support for reports to easily create a readable and actionable format for sharing crashes.
4
4
  - Add multiple crash sources, making it easier for anyone to plug and play.
5
5
  - Enable newsletters or results to be easily published on sites like GitHub.
6
6
  - Cultivate an inclusive open source community through respectful discussion.
@@ -8,7 +8,7 @@
8
8
  # Scope
9
9
 
10
10
  - We are focusing on crashes for a specific app version.
11
- - Having a crash newsletter in mind, we do not expect adding crash visualisations.
11
+ - We do not expect adding crash visualisations.
12
12
 
13
13
  ## Inspiration
14
14
 
Binary file
Binary file
Binary file
Binary file
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'crep'
data/bin/crep CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH.push File.expand_path('../lib', File.dirname(__FILE__))
4
5
 
@@ -1,4 +1,6 @@
1
1
 
2
+ # frozen_string_literal: true
3
+
2
4
  lib = File.expand_path('../lib', __FILE__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'crep/version'
@@ -9,11 +11,19 @@ Gem::Specification.new do |spec|
9
11
  spec.authors = ['Kim Dung-Pham', 'Bas Broek', 'Serghei Moret']
10
12
  spec.email = ['kim.dung-pham@xing.com', 'bas.broek@xing.com', 'serghei.moret@xing.com']
11
13
 
12
- spec.summary = 'Create Crash Newsletter with ease.'
13
- spec.description = 'Create Crash Newsletter with ease. Really.'
14
+ spec.summary = 'Create Crash Reports with ease.'
15
+ spec.description = 'Create Crash Reports with ease. Really.'
14
16
  spec.homepage = 'https://github.com/xing/crep'
15
17
  spec.license = 'MIT'
16
18
 
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
25
+ 'public gem pushes.'
26
+ end
17
27
 
18
28
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
29
  f.match(%r{^(test|spec|features)/})
@@ -23,13 +33,14 @@ Gem::Specification.new do |spec|
23
33
  spec.executables << 'crep'
24
34
  spec.require_paths = ['lib']
25
35
 
26
- spec.add_dependency 'hockeyapp'
27
36
  spec.add_dependency 'colorize'
37
+ spec.add_dependency 'hockeyapp'
28
38
 
29
39
  spec.add_runtime_dependency 'claide', '~> 1.0.0'
30
40
 
31
41
  spec.add_development_dependency 'bundler', '~> 1.15'
32
42
  spec.add_development_dependency 'pry'
43
+ spec.add_development_dependency 'pry-byebug'
33
44
  spec.add_development_dependency 'rake', '~> 10.0'
34
45
  spec.add_development_dependency 'rspec'
35
46
  spec.add_development_dependency 'rubocop', '0.51.0'
@@ -1,12 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'crep/version'
2
4
  require 'crep/command'
3
5
  require 'claide'
4
- require 'logger'
5
6
 
6
7
  module Crep
7
- XINGLogger = Logger.new(STDOUT)
8
- XINGLogger.level = Logger::DEBUG
9
-
10
8
  def self.run
11
9
  Command.run(ARGV)
12
10
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crep
4
+ class AppController
5
+ def initialize(app_source, identifier, version, build, versions_limit)
6
+ @identifier = identifier&.downcase
7
+ @version = version
8
+ @build = build
9
+ @versions_limit = versions_limit
10
+
11
+ @app_source = app_source
12
+ @app_source.configure
13
+ end
14
+
15
+ def apps
16
+ filtered_apps = @app_source.apps.select do |app|
17
+ @identifier ? app.bundle_identifier.downcase == @identifier : true
18
+ end
19
+ filtered_apps.each do |app|
20
+ report_app(app.public_identifier, app.title)
21
+ end
22
+ end
23
+
24
+ def report_app(identifier, title)
25
+ puts "\n\t\t" + title
26
+ app_versions_as_string_list(identifier).each do |version_string|
27
+ puts "\t\t#{version_string}"
28
+ end
29
+ end
30
+
31
+ def app_versions_as_string_list(app_identifier)
32
+ versions = @app_source.versions(app_identifier)
33
+
34
+ filtered_versions = versions.select do |v|
35
+ version_match = @version ? v.version == @version : true
36
+ build_match = @build ? v.build == @build : true
37
+ version_match && build_match
38
+ end
39
+
40
+ AppController.versions_as_string_list(filtered_versions, @versions_limit)
41
+ end
42
+
43
+ def self.versions_as_string_list(versions, limit)
44
+ versions.first(limit).map do |v|
45
+ "#{v.version} (#{v.build})"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'claide'
2
4
  require 'crep/version'
3
5
 
4
6
  module Crep
5
7
  class Command < CLAide::Command
6
8
  require 'crep/command/crashes'
9
+ require 'crep/command/apps'
7
10
 
8
11
  self.abstract_command = true
9
12
  self.command = 'crep'
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'crep/command'
4
+ require 'crep/app_controller'
5
+ require 'crep/model/app_source/hockeyapp_app_source'
6
+
7
+ module Crep
8
+ class Apps < Command
9
+ # options should accept app name and version filter
10
+ DEFAULT_VERSIONS_LIMIT = 5
11
+
12
+ def self.options
13
+ [
14
+ ['--identifier=<com.company.app>', 'Crep will show app information with this identifier.'],
15
+ ['--version=<7.10.0>', 'An optional filter for the version of an app.'],
16
+ ['--build=<24>', 'An optional filter for the build of an app.'],
17
+ ['--versions=5', "If set, Crep will limit the number of displayed versions per app. #{DEFAULT_VERSIONS_LIMIT} by default."]
18
+ ].concat(super)
19
+ end
20
+
21
+ self.summary = <<-DESC
22
+ Shows the apps with their versions.
23
+ DESC
24
+
25
+ self.description = <<-DESC
26
+ Display apps with their versions.
27
+ DESC
28
+
29
+ def initialize(argv)
30
+ super
31
+
32
+ @versions_limit = argv.option('versions') || DEFAULT_VERSIONS_LIMIT
33
+ CrepLogger.info("Versions will be limited to #{@versions_limit} per app")
34
+
35
+ @identifier = argv.option('identifier')
36
+ CrepLogger.info("Apps will be filtered by identifier: #{@identifier}") if @identifier
37
+
38
+ @version = argv.option('version')
39
+ CrepLogger.info("Version will be filtered: #{@version}") if @version
40
+
41
+ @build = argv.option('build')
42
+ CrepLogger.info("Build will be filtered: #{@build}") if @build
43
+ end
44
+
45
+ def run
46
+ CrepLogger.info('Reporting apps:')
47
+
48
+ app_source = HockeyAppAppSource.new
49
+ app_controller = AppController.new(app_source, @identifier, @version, @build, @versions_limit.to_i)
50
+ app_controller.apps
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'crep/command'
2
4
  require 'crep/crash_controller'
3
5
  require 'crep/model/crash_sources/hockeyapp_crash_source'
@@ -6,6 +8,7 @@ require 'hockeyapp'
6
8
  module Crep
7
9
  class Crashes < Command
8
10
  DEFAULT_TOP_COUNT = 5
11
+ DEFAULT_TEMPLATE = 'templates/default_crash_report.txt.erb'
9
12
 
10
13
  def self.options
11
14
  [
@@ -13,7 +16,8 @@ module Crep
13
16
  ['--identifier=<com.company.app>', 'Crep will show crashes for the app with this bundle identifier'],
14
17
  ['--version=<7.10.0>', 'The version of the App.'],
15
18
  ['--build=<24>', 'The Build number of the App.'],
16
- ['--only-unresolved', 'If set, resolved crashes will be filtered out.']
19
+ ['--only-unresolved', 'If set, resolved crashes will be filtered out.'],
20
+ ['--template=templates/defaul_crash_report.txt.erb', 'Set this to specify a erb template for the report format. If no value is specifed the default temapate will be used.']
17
21
  ].concat(super)
18
22
  end
19
23
 
@@ -22,21 +26,31 @@ module Crep
22
26
  DESC
23
27
 
24
28
  self.description = <<-DESC
25
- Besides the optional `top` parameter, Crep requires all other parameters.
29
+ Besides the optional `top`, `template` and `only-unresolved` parameters, Crep requires all other parameters.
26
30
  DESC
27
31
 
28
32
  def initialize(argv)
33
+ super
34
+
29
35
  @show_only_unresolved = argv.flag?('only-unresolved', false)
30
- @top = argv.option('top') || DEFAULT_TOP_COUNT
31
- @bundle_identifier = argv.option('identifier') || raise('Missing `identifier` parameter')
32
- @version = argv.option('version') || raise('Missing `version` parameter')
33
- @build = argv.option('build') || raise('Missing `build` parameter')
36
+ @top = argv.option('top', DEFAULT_TOP_COUNT)
37
+ @bundle_identifier = argv.option('identifier')
38
+ @version = argv.option('version')
39
+ @build = argv.option('build')
40
+ @template = argv.option('template', DEFAULT_TEMPLATE)
41
+ end
42
+
43
+ def validate!
34
44
  super
45
+
46
+ help! 'The identifier (--identifier) is a required parameter' unless @bundle_identifier
47
+ help! 'The version (--version) is a required parameter' unless @version
48
+ help! 'The build number (--build) is a required parameter' unless @build
35
49
  end
36
50
 
37
51
  def run
38
52
  crash_datasource = HockeyAppCrashSource.new
39
- crash_controller = CrashController.new(@bundle_identifier, @top, crash_datasource, @show_only_unresolved)
53
+ crash_controller = CrashController.new(@bundle_identifier, @top, crash_datasource, @show_only_unresolved, @template)
40
54
  crash_controller.top_crashes(@version, @build)
41
55
  end
42
56
  end
@@ -1,64 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'colorize'
4
+ require 'erb'
2
5
 
3
6
  module Crep
4
7
  class CrashController
5
- def initialize(bundle_identifier, top, crash_source, show_only_unresolved)
8
+ attr_reader :bundle_identifier, :crashes, :app_name, :version, :build, :total_crashes, :template_path
9
+
10
+ def initialize(bundle_identifier, top, crash_source, show_only_unresolved, template_path)
6
11
  @bundle_identifier = bundle_identifier
7
12
  @top = top
8
13
  @crash_source = crash_source
9
14
  @show_only_unresolved = show_only_unresolved
10
15
  @crash_source.configure(bundle_identifier)
16
+ @app_name = @crash_source.app.name
17
+ @template_path = template_path
11
18
  end
12
19
 
13
20
  # returns list of top crashes for the given build
14
21
  def top_crashes(version, build)
15
- crashes = @crash_source.crashes(@top, version, build, @show_only_unresolved)
16
- total_crashes = @crash_source.crash_count(version: version,
17
- build: build)
18
- report(crashes: crashes,
19
- total_crashes: total_crashes,
20
- app_name: @crash_source.app.name,
21
- identifier: @crash_source.app.bundle_identifier,
22
- version: version,
23
- build: build)
24
- end
25
-
26
- def report(crashes:, total_crashes:, app_name:, identifier:, version:, build:)
27
- puts("Reporting for #{app_name} (#{version}/#{build}) #{identifier}")
28
-
29
- crash_reports = crashes_report(crashes: crashes, total_crashes: total_crashes, version: version)
30
- empty_message = total_crashes == 0 ? "Look mom, no crashes... yet!" : "Look mom, no unresolved crashes... yet!"
31
- puts(empty_message.green) if crash_reports.empty?
32
-
33
- crash_reports.each_with_index do |crash_report, i|
34
- puts("\n------------- ##{(i + 1)} --------------")
35
- crash_report.each do |line|
36
- puts(line)
37
- end
38
- end
22
+ @version = version
23
+ @build = build
24
+ @crashes = @crash_source.crashes(@top, version, build, @show_only_unresolved)
25
+ @total_crashes = @crash_source.crash_count(version: @version, build: @build)
26
+ report
39
27
  end
40
28
 
41
- def crashes_report(crashes:, total_crashes:, version:)
42
- crashes.map do |crash|
43
- percentage = crash_percentage(crash: crash, total_crashes: total_crashes)
44
- crash_report(crash: crash, percentage: percentage, version: version)
45
- end
29
+ private def report
30
+ template = File.read template_path
31
+ renderer = ERB.new template
32
+ puts output = renderer.result(binding)
33
+ output
46
34
  end
47
35
 
48
- def crash_percentage(crash:, total_crashes:)
36
+ private def crash_percentage(crash:, total_crashes:)
49
37
  crash.occurrences.to_f / total_crashes.to_f * 100.0
50
38
  end
51
-
52
- def crash_report(crash:, percentage:, version:)
53
- raise 'Crash info does not fulfill the requirements' unless crash.is_a? Crep::Crash
54
- report = []
55
- report.push "Class: #{crash.crash_class}"
56
- report.push "First appeared on #{crash.registered_at} and occurred #{crash.occurrences} times in #{version}"
57
- report.push "Percentage: #{percentage.round(2)}% of all #{version} crashes"
58
- report.push "File/Line: #{crash.file_line}"
59
- report.push "Reason: #{crash.reason}" # crash.reason[0..80]
60
- report.push "Link: #{crash.url}"
61
- report
62
- end
63
39
  end
64
40
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Crep
6
+ CrepLogger = Logger.new(STDOUT)
7
+ CrepLogger.level = Logger::DEBUG
8
+ CrepLogger.datetime_format = '%Y-%m-%d %H:%M:%S'
9
+ CrepLogger.formatter = proc do |severity, datetime, _progname, msg|
10
+ case severity
11
+ when 'DEBUG'
12
+ "[DEBUG] #{datetime}: #{msg}\n".light_magenta
13
+ when 'ERROR'
14
+ "[ERROR] #{datetime}: #{msg}\n".red
15
+ when 'FATAL'
16
+ "[FATAL] #{datetime}: #{msg}\n".red
17
+ when 'INFO'
18
+ "[INFO] #{datetime}: #{msg}\n".green
19
+ when 'WARN'
20
+ "[WARNING] #{datetime}: #{msg}\n".yellow
21
+ else
22
+ "[LOG] #{datetime}: #{msg}\n"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crep
4
+ class AppSource
5
+ attr_reader :version
6
+
7
+ def configure
8
+ CrepLogger.info('Configuration of the CrashSource can happen in the `configure` method')
9
+ end
10
+
11
+ def apps
12
+ raise 'AppSource subclass has to implement the `apps` method.'
13
+ end
14
+
15
+ # versions returns the versions for the given app identifier
16
+ def versions(_app_identifier)
17
+ raise 'AppSource subclass has to implement the `versions` method.'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'crep/model/app_source/app_source'
4
+ require 'crep/model/crash_model/version'
5
+ require 'hockeyapp'
6
+
7
+ module Crep
8
+ class HockeyAppAppSource < AppSource
9
+ def configure
10
+ HockeyApp::Config.configure do |config|
11
+ raise 'Missing API token (CREP_HOCKEY_API_TOKEN)' unless ENV['CREP_HOCKEY_API_TOKEN']
12
+ config.token = ENV['CREP_HOCKEY_API_TOKEN']
13
+ end
14
+
15
+ @client = HockeyApp.build_client
16
+ end
17
+
18
+ def apps
19
+ @client.get_apps
20
+ end
21
+
22
+ def versions(app_identifier)
23
+ apps = @client.get_apps.select do |a|
24
+ a.public_identifier == app_identifier
25
+ end
26
+
27
+ raise("Unable to find app with identifier: #{app_identifier}") unless apps.count.positive?
28
+
29
+ app = apps.first
30
+ app.versions.map do |version|
31
+ Crep::Version.new(version.shortversion, version.version, app.public_identifier.downcase)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Crep
2
4
  # App represents an App
3
5
  class App
@@ -1,13 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Crep
2
4
  class Crash
3
- attr_reader :file_line, :occurrences, :reason, :crash_class, :registered_at, :url
5
+ attr_reader :file_line, :occurrences, :reason, :crash_class, :registered_at, :deep_link, :url
4
6
 
5
- def initialize(file_line:, occurrences:, reason:, crash_class:, registered_at:, url:)
7
+ def initialize(file_line:, occurrences:, reason:, crash_class:, registered_at:, deep_link:, url:)
6
8
  @file_line = file_line
7
9
  @occurrences = occurrences
8
10
  @reason = reason
9
11
  @crash_class = crash_class
10
12
  @registered_at = registered_at
13
+ @deep_link = deep_link
11
14
  @url = url
12
15
  end
13
16
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crep
4
+ class Version
5
+ attr_reader :version, :build, :app_identifier
6
+
7
+ def initialize(version, build, app_identifier)
8
+ @version = version
9
+ @build = build
10
+ @app_identifier = app_identifier
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Crep
2
4
  # This is an abstract class that defines the methods which subclasses must implement.
3
5
  class CrashSource
@@ -5,7 +7,7 @@ module Crep
5
7
 
6
8
  # Necessary configuration of the subclass can happen here
7
9
  def configure(_bundle_identifier)
8
- raise 'CrashSource subclass has to implement the `configure` method.'
10
+ CrepLogger.info('Configuration of the CrashSource can happen in the `configure` method')
9
11
  end
10
12
 
11
13
  def crash_count(_version, _build)
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'crep/model/crash_sources/crash_source'
2
4
  require 'crep/model/crash_model/app'
3
5
  require 'crep/model/crash_model/crash'
6
+ require 'crep/logger'
4
7
  require 'hockeyapp'
5
8
 
6
9
  module Crep
@@ -35,11 +38,13 @@ module Crep
35
38
  unresolved_reasons = show_only_unresolved ? unresolved_reasons(reasons) : reasons
36
39
  unresolved_reasons.map do |reason|
37
40
  url = url(app_id: reason.app.public_identifier, version_id: version.id, reason_id: reason.id)
41
+ deep_link = deep_link(app_id: reason.app.public_identifier, reason_id: reason.id)
38
42
  Crash.new(file_line: "#{reason.file}:#{reason.line}",
39
43
  occurrences: reason.number_of_crashes,
40
44
  reason: reason.reason,
41
45
  crash_class: reason.crash_class,
42
46
  registered_at: Date.parse(reason.created_at),
47
+ deep_link: deep_link,
43
48
  url: url)
44
49
  end
45
50
  end
@@ -48,12 +53,23 @@ module Crep
48
53
  "https://rink.hockeyapp.net/manage/apps/#{app_id}/app_versions/#{version_id}/crash_reasons/#{reason_id}"
49
54
  end
50
55
 
56
+ def deep_link(app_id:, reason_id:)
57
+ "hockeyapp-coach://view-crash/#{app_id}/#{reason_id}/latest"
58
+ end
59
+
51
60
  def version(version:, build:)
52
61
  filtered_versions = filtered_versions_by_version_and_build(@hockeyapp_app.versions, version, build)
53
62
 
54
- raise "No version was found for #{version})#{build})" unless filtered_versions.count > 0
63
+ if filtered_versions.count <= 0
64
+ CrepLogger.error("No version was found for #{version})#{build})")
65
+ raise
66
+ end
55
67
 
56
- filtered_versions.first
68
+ report_version = filtered_versions.first
69
+
70
+ CrepLogger.warn("Multiple results for #{version}/#{build} were found, using the first (with ID #{report_version.id}) one that was found") unless filtered_versions.count <= 1
71
+
72
+ report_version
57
73
  end
58
74
 
59
75
  def unresolved_reasons(reasons)
@@ -65,6 +81,10 @@ module Crep
65
81
  apps = all_apps.select do |app|
66
82
  app.bundle_identifier == bundle_identifier
67
83
  end
84
+ unless apps.first
85
+ CrepLogger.error("No app with the give bundle identifier (#{bundle_identifier}) was found.")
86
+ raise
87
+ end
68
88
  apps.first
69
89
  end
70
90
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Crep
2
- VERSION = '0.1.0'.freeze
4
+ VERSION = '1.0.0'
3
5
  end
@@ -0,0 +1,11 @@
1
+ Reporting for <%= app_name %> (<%= version %>/<%= build %>) <%= bundle_identifier %>
2
+ <% crashes.each_with_index do |crash, index| %>
3
+ ------------- #<%= index + 1 %> --------------
4
+ Class: <%= crash.crash_class %>
5
+ First appeared on <%= crash.registered_at %> and occurred <%= crash.occurrences %> times in <%= version %>
6
+ Percentage: <%= crash_percentage(crash: crash, total_crashes: total_crashes).round(2) %>% of all <%= version %> crashes
7
+ File/Line: <%= crash.file_line %>
8
+ Reason: <%= crash.reason %>
9
+ Link: <%= crash.url %>
10
+ Deep Link: <%= crash.deep_link %>
11
+ <% end %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kim Dung-Pham
@@ -10,10 +10,10 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-01-13 00:00:00.000000000 Z
13
+ date: 2018-04-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: hockeyapp
16
+ name: colorize
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
19
  - - ">="
@@ -27,7 +27,7 @@ dependencies:
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0'
29
29
  - !ruby/object:Gem::Dependency
30
- name: colorize
30
+ name: hockeyapp
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - ">="
@@ -82,6 +82,20 @@ dependencies:
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: pry-byebug
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
85
99
  - !ruby/object:Gem::Dependency
86
100
  name: rake
87
101
  requirement: !ruby/object:Gem::Requirement
@@ -124,7 +138,7 @@ dependencies:
124
138
  - - '='
125
139
  - !ruby/object:Gem::Version
126
140
  version: 0.51.0
127
- description: Create Crash Newsletter with ease. Really.
141
+ description: Create Crash Reports with ease. Really.
128
142
  email:
129
143
  - kim.dung-pham@xing.com
130
144
  - bas.broek@xing.com
@@ -134,32 +148,51 @@ executables:
134
148
  extensions: []
135
149
  extra_rdoc_files: []
136
150
  files:
151
+ - ".circleci/config.yml"
152
+ - ".github/ISSUE_TEMPLATE.md"
153
+ - ".github/PULL_REQUEST_TEMPLATE.md"
137
154
  - ".gitignore"
138
155
  - ".rspec"
139
156
  - ".rubocop.yml"
157
+ - ".ruby-version"
140
158
  - Changelog.md
159
+ - Dangerfile
141
160
  - Gemfile
161
+ - Gemfile.lock
142
162
  - LICENSE
143
- - README.md
144
163
  - Rakefile
164
+ - Readme.md
145
165
  - Vision.md
166
+ - assets/logo.png
167
+ - assets/logo_dark.png
168
+ - assets/logo_grapefruit.png
169
+ - assets/logo_small.png
170
+ - assets/logo_square.png
146
171
  - bin/console
147
172
  - bin/crep
148
173
  - bin/setup
149
174
  - crep.gemspec
150
175
  - lib/crep.rb
176
+ - lib/crep/app_controller.rb
151
177
  - lib/crep/command.rb
178
+ - lib/crep/command/apps.rb
152
179
  - lib/crep/command/crashes.rb
153
180
  - lib/crep/crash_controller.rb
181
+ - lib/crep/logger.rb
182
+ - lib/crep/model/app_source/app_source.rb
183
+ - lib/crep/model/app_source/hockeyapp_app_source.rb
154
184
  - lib/crep/model/crash_model/app.rb
155
185
  - lib/crep/model/crash_model/crash.rb
186
+ - lib/crep/model/crash_model/version.rb
156
187
  - lib/crep/model/crash_sources/crash_source.rb
157
188
  - lib/crep/model/crash_sources/hockeyapp_crash_source.rb
158
189
  - lib/crep/version.rb
190
+ - templates/default_crash_report.txt.erb
159
191
  homepage: https://github.com/xing/crep
160
192
  licenses:
161
193
  - MIT
162
- metadata: {}
194
+ metadata:
195
+ allowed_push_host: https://rubygems.org
163
196
  post_install_message:
164
197
  rdoc_options: []
165
198
  require_paths:
@@ -176,8 +209,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
209
  version: '0'
177
210
  requirements: []
178
211
  rubyforge_project:
179
- rubygems_version: 2.7.4
212
+ rubygems_version: 2.5.1
180
213
  signing_key:
181
214
  specification_version: 4
182
- summary: Create Crash Newsletter with ease.
215
+ summary: Create Crash Reports with ease.
183
216
  test_files: []
data/README.md DELETED
@@ -1,37 +0,0 @@
1
- # Crep
2
-
3
- *Crep - a Crash Reporter for creating appealing Crash Newsletters*
4
-
5
- We use Crep at [XING](https://www.xing.com) to create our Crash Newsletters for [iOS](https://www.xing.com/ios) and [Android](https://www.xing.com/android) within the _Mobile Releases Team_. It currently uses [HockeyApp](https://rink.hockeyapp.net) as a crash source, so if you are using Hockey, you should definitely give Crep a try.
6
-
7
- In case you are creating Crash Newsletters and have a different crash source in mind - check out the contributing section!
8
-
9
- ## Install
10
-
11
- Please follow our guide in the [Installation Instructions](https://github.com/xing/crep/wiki/Install).
12
-
13
- ## Usage
14
-
15
- Provide a `CREP_HOCKEY_API_TOKEN`:
16
-
17
- `export CREP_HOCKEY_API_TOKEN='abcde'`
18
-
19
- Run Crep:
20
-
21
- `bundle exec crep crashes --identifier='com.example.company' --version='1.23.0' --build='42' --only-unresolved`
22
-
23
- The `--only-unresolved` flag filters out any crashes marked as resolved.
24
-
25
- ## Test
26
-
27
- Run `bundle exec rspec` in order to run the tests.
28
-
29
- ## Contributing
30
-
31
- 🎁 Bug reports and pull requests for new features are most welcome!
32
-
33
- 👷🏼 In case you want to use a different crash source - feel free to add on, we are looking forward to your pull request, we'd love to help!
34
-
35
- ## License
36
-
37
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).