korinthenkacker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1c174ae40b2ddbc7d73ca1bce0d2e97e630362d
4
+ data.tar.gz: 7dda75b32aa473799d35ed4a901ab282ab2cc6d1
5
+ SHA512:
6
+ metadata.gz: 5e2d9147896eb71cd1f171529251c1392207f36cbc5a474d1553ae3c23a735c5bd0395f26e683e75ab0a3709e92ba230b27d463fb71b85787caaa18d64e27529
7
+ data.tar.gz: 8a0f648765d04537361468847211d5a439c84f7edcd2d010193dd1b89850f29e6de8db9c56d946f51c9f2fac12951aadd88772c520c9bdf634cbd5219322d26c
@@ -0,0 +1,23 @@
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
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .korinthenkacker.yml
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use default@korinthenkacker
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in korinthenkacker.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Vincent Garrigues
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # Korinthenkacker
2
+
3
+ Know your Jenkins
4
+
5
+ ## Setup
6
+
7
+ Add a `.korinthenkacker.yml` containing the jenkins url:
8
+
9
+ ```
10
+ jenkins:
11
+ url: http://mobile-jenkins.int.s-cloud.net:82/
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```
17
+ $> korinthenkacker jobs
18
+ api-mobile
19
+ [...]
20
+ soundcloud_rac_acceptance_tests_0
21
+ soundcloud_rac_acceptance_tests_1
22
+ soundcloud_rac_acceptance_tests_2
23
+ soundcloud_rac_acceptance_tests_3
24
+ soundcloud_rac_acceptance_tests_4
25
+ soundcloud_rac_master
26
+ soundcloud_rac_master_deploy_alpha
27
+ soundcloud_rac_master_deploy_beta
28
+ soundcloud_rac_release
29
+ ```
30
+
31
+ ```
32
+ $> korinthenkacker builds soundcloud_rac_acceptance_tests_0 -l 10
33
+ # success duration
34
+ 65 true 1327.1874
35
+ 64 false 1416.8722
36
+ 63 true 1409.2301
37
+ 62 true 754.0678
38
+ 61 true 1132.1196
39
+ 60 true 1177.228
40
+ 59 true 1157.0691
41
+ 58 false 1164.8196
42
+ 57 false 1175.3278
43
+ ```
44
+
45
+ ```
46
+ $> korinthenkacker failed_scenarios soundcloud_rac_acceptance_tests_0 -l 20
47
+ # duration failed scenario name
48
+ 64 28.805166 Empty view when no results returned
49
+ 58 28.217377 Unliking a track updates the count and like cells
50
+ 57 28.0328 Liking a track updates the count and like cells
51
+ 53 11.726423 Mini waveform stops animating on track error
52
+ 47 41.80393 When an unfollowing request fails, display followed state
53
+ 47 80.93447 When a follow request fails, display unfollowed state
54
+ ```
55
+
56
+ ```
57
+ $> korinthenkacker failed_scenarios soundcloud_rac_acceptance_tests_0 47
58
+ # duration failed scenario name
59
+ 47 41.80393 When an unfollowing request fails, display followed state
60
+ 47 80.93447 When a follow request fails, display unfollowed state
61
+ ```
62
+
63
+ ```
64
+ $> korinthenkacker report soundcloud_rac_acceptance_tests_{0,1,2,3,4} -l 5
65
+ soundcloud_rac_acceptance_tests_0
66
+ # duration failed scenario name
67
+ 64 28.805166 'Empty view when no results returned'
68
+ soundcloud_rac_acceptance_tests_1
69
+ # duration failed scenario name
70
+ 62 43.684013 'Logging out stops playback, removes player from tab bar'
71
+ soundcloud_rac_acceptance_tests_2
72
+ # duration failed scenario name
73
+ 55 44.15834 'User should be able to paginate their playlists'
74
+ soundcloud_rac_acceptance_tests_3
75
+ # duration failed scenario name
76
+ 64 0.013009 'Player shows timestamp with correct duration'
77
+ 64 0.02346 'Followed user shows follow button'
78
+ 64 40.086674 'User should be able to paginate their playlists'
79
+ 63 0.013006 'Player shows timestamp with correct duration'
80
+ 63 41.263924 'User should be able to paginate their playlists'
81
+ soundcloud_rac_acceptance_tests_4
82
+ ```
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'korinthenkacker/cli'
4
+
5
+ Korinthenkacker::CLI.start(ARGV)
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'korinthenkacker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'korinthenkacker'
8
+ spec.version = Korinthenkacker::VERSION
9
+ spec.authors = ['Vincent Garrigues']
10
+ spec.email = ['vincent@soundcloud.com']
11
+ spec.summary = %q{Seriously Jenkins?}
12
+ spec.description = %q{Find out what the fuck is going on with those tests}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'thor'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.6'
24
+ spec.add_development_dependency 'rake'
25
+ end
@@ -0,0 +1,2 @@
1
+ module Korinthenkacker
2
+ end
@@ -0,0 +1,39 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Korinthenkacker
5
+ class API
6
+ def initialize(base_url)
7
+ uri = URI(base_url)
8
+ @host = uri.host
9
+ @port = uri.port
10
+ end
11
+
12
+ def jobs
13
+ get('')
14
+ end
15
+
16
+ def job(jobname)
17
+ get("/job/#{jobname}")
18
+ end
19
+
20
+ def build(jobname, build)
21
+ get("/job/#{jobname}/#{build}")
22
+ end
23
+
24
+ def test_report(jobname, build)
25
+ get("/job/#{jobname}/#{build}/testReport")
26
+ end
27
+
28
+ private
29
+ def get(path)
30
+ uri = URI::HTTP.build({:host => @host, :port => @port, :path => path + '/api/json'})
31
+ response = Net::HTTP.get_response(uri)
32
+ if response.code == '200'
33
+ JSON.parse(response.body)
34
+ else
35
+ raise 'response code is ' + response.code + ' for ' + uri.to_s
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,85 @@
1
+ require 'thor'
2
+
3
+ require_relative 'api'
4
+ require_relative 'configuration'
5
+ require_relative 'test_report'
6
+ require_relative 'job_info'
7
+
8
+ module Korinthenkacker
9
+ class CLI < Thor
10
+ package_name 'korinthenkacker'
11
+
12
+ desc 'jobs', 'Show all jobs'
13
+ def jobs
14
+ puts api.jobs["jobs"].map{ |job| job['name'] }
15
+ end
16
+
17
+ desc 'builds JOBNAME', 'Display JOBNAME builds and their status'
18
+ method_option :limit, :aliases => '-l', :type => :numeric
19
+ def builds(jobname)
20
+ reports = test_reports(jobname, options.limit)
21
+ output = []
22
+ output << "#\tsuccess\tduration"
23
+ reports.each{ |report|
24
+ output << "#{report.build}\t#{report.success?}\t#{report.duration}"
25
+ }
26
+ puts output.join("\n")
27
+ end
28
+
29
+ desc 'failed_scenarios JOBNAME [BUILD]', 'Display JOBNAME failing scenarios'
30
+ method_option :limit, :aliases => '-l', :type => :numeric
31
+ def failed_scenarios(jobname, build=nil)
32
+ if build
33
+ test_report = TestReport.new(jobname, build, api.test_report(jobname, build))
34
+ print_failed_table_header unless test_report.failed_cases.empty?
35
+ test_report.failed_cases.each { |failed_case|
36
+ print_scenario_report(build, failed_case)
37
+ }
38
+ else
39
+ reports = test_reports(jobname, options.limit)
40
+ failed_build_reports = reports.select{ |report| !report.success? }
41
+ print_failed_table_header unless failed_build_reports.empty?
42
+ failed_build_reports.each{ |report|
43
+ report.failed_cases.each{ |failed_case|
44
+ print_scenario_report(report.build, failed_case)
45
+ }
46
+ }
47
+ end
48
+ end
49
+
50
+ desc 'report [JOBS...]', 'Display failing scenario for jobs'
51
+ method_option :limit, :aliases => '-l', :type => :numeric
52
+ def report(*jobs)
53
+ jobs.each{ |job|
54
+ puts job
55
+ failed_scenarios(job, nil)
56
+ }
57
+ end
58
+
59
+ private
60
+
61
+ def print_failed_table_header
62
+ printf("%s\t%-15s\t%s\n", '#', 'duration', 'failed scenario name')
63
+ end
64
+
65
+ def print_scenario_report(build, scenario)
66
+ printf("%s\t%-15s\t'%s'\n", build, scenario.duration, scenario.name)
67
+ end
68
+
69
+ def test_reports(jobname, limit=nil)
70
+ job_info = JobInfo.new(api.job(jobname))
71
+ builds = options.limit ? job_info.build_numbers.first(options.limit) : job_info.build_numbers
72
+ builds.map{ |build|
73
+ begin
74
+ TestReport.new(jobname, build, api.test_report(jobname, build))
75
+ rescue Exception => ex
76
+ nil
77
+ end
78
+ }.compact
79
+ end
80
+
81
+ def api
82
+ @api ||= API.new(Configuration.jenkins_url)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,16 @@
1
+ require 'yaml'
2
+
3
+ module Korinthenkacker
4
+ module Configuration
5
+ extend self
6
+
7
+ def jenkins_url
8
+ settings['jenkins']['url']
9
+ end
10
+
11
+ private
12
+ def settings
13
+ @settings ||= YAML.load_file('.korinthenkacker.yml')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Korinthenkacker
2
+ class JobInfo
3
+ attr_reader :name, :url
4
+
5
+ def initialize(json)
6
+ @name = json['name']
7
+ @url = json['url']
8
+ @json = json
9
+ end
10
+
11
+ def build_numbers
12
+ @json['builds'].map{ |build| build['number'] }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module Korinthenkacker
2
+ class TestCase
3
+ attr_reader :name, :duration, :failed_since, :status
4
+
5
+ def initialize(json)
6
+ @name = json['name']
7
+ @duration = json['duration']
8
+ @failed_since = json['duration']
9
+ @status = json['status']
10
+ end
11
+
12
+ def success?
13
+ !(status == 'REGRESSION' || status == 'FAILED')
14
+ end
15
+
16
+ private
17
+
18
+ def status_with_json(json)
19
+ json['status'] == 'REGRESSION' || json['status'] == 'FAILED'
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,46 @@
1
+ require_relative 'test_case'
2
+
3
+ module Korinthenkacker
4
+ class TestReport
5
+ attr_reader :jobname, :build
6
+
7
+ def initialize(jobname, build, json)
8
+ @jobname = jobname
9
+ @build = build
10
+ @json = json
11
+ end
12
+
13
+ def duration
14
+ @json['duration']
15
+ end
16
+
17
+ def fail_count
18
+ @json['failCount']
19
+ end
20
+
21
+ def pass_count
22
+ @json['passCount']
23
+ end
24
+
25
+ def skip_count
26
+ @json['skipCount']
27
+ end
28
+
29
+ def success?
30
+ fail_count == 0 && skip_count == 0
31
+ end
32
+
33
+ def failed_cases
34
+ all_cases.select { |test_case| !test_case.success? }
35
+ end
36
+
37
+ private
38
+
39
+ def all_cases
40
+ @json['suites']
41
+ .map { |suite| suite['cases'] }
42
+ .flatten
43
+ .map { |my_case| TestCase.new(my_case) }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module Korinthenkacker
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: korinthenkacker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Garrigues
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Find out what the fuck is going on with those tests
56
+ email:
57
+ - vincent@soundcloud.com
58
+ executables:
59
+ - korinthenkacker
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - .rvmrc
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/korinthenkacker
70
+ - korinthenkacker.gemspec
71
+ - lib/korinthenkacker.rb
72
+ - lib/korinthenkacker/api.rb
73
+ - lib/korinthenkacker/cli.rb
74
+ - lib/korinthenkacker/configuration.rb
75
+ - lib/korinthenkacker/job_info.rb
76
+ - lib/korinthenkacker/test_case.rb
77
+ - lib/korinthenkacker/test_report.rb
78
+ - lib/korinthenkacker/version.rb
79
+ homepage: ''
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.0.3
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Seriously Jenkins?
103
+ test_files: []