relevant-hudson 0.0.1
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.
- data/.gitignore +2 -0
- data/README.md +1 -0
- data/Rakefile +30 -0
- data/lib/relevant/hudson.rb +159 -0
- data/spec/relevant/hudson_spec.rb +110 -0
- data/spec/spec_helper.rb +15 -0
- metadata +115 -0
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Hudson widget for Relevant
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require File.dirname(__FILE__) + "/lib/relevant/hudson.rb"
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gemspec|
|
9
|
+
gemspec.version = Relevant::Hudson::Version
|
10
|
+
gemspec.name = "relevant-hudson"
|
11
|
+
gemspec.summary = "Hudson widget for Relevant"
|
12
|
+
gemspec.description = "Check the time"
|
13
|
+
gemspec.email = "opensource@thinkrelevance.com"
|
14
|
+
gemspec.homepage = "http://github.com/relevance/relevant-hudson"
|
15
|
+
gemspec.authors = ["Jared Pace", "Rob Sanheim"]
|
16
|
+
gemspec.add_dependency "relevant-widget", "~> 0.0.6"
|
17
|
+
gemspec.add_dependency "feedzirra"
|
18
|
+
gemspec.add_development_dependency "rspec", "~> 2.0.0.beta.22"
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rspec/core/rake_task'
|
27
|
+
RSpec::Core::RakeTask.new(:spec)
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
task :full_release => [:check_dependencies, :spec, :release]
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require "relevant/widget"
|
2
|
+
require "feedzirra"
|
3
|
+
|
4
|
+
module Relevant
|
5
|
+
class Hudson
|
6
|
+
Version = "0.0.1"
|
7
|
+
include Relevant::Widget
|
8
|
+
|
9
|
+
available_options :title => :string,
|
10
|
+
:rss_feed => :string,
|
11
|
+
:ignore_projects => :string,
|
12
|
+
:http_auth_username => :string,
|
13
|
+
:http_auth_password => :password
|
14
|
+
|
15
|
+
refresh_every 1.minute
|
16
|
+
|
17
|
+
template_format :haml
|
18
|
+
template %q[
|
19
|
+
%h2 Hudson - #{@options[:title]}
|
20
|
+
%ul.hudson-builds
|
21
|
+
- builds.each do |build|
|
22
|
+
%li.build{:class => build.label}
|
23
|
+
%span.indicator
|
24
|
+
%h3= build.project.titleize
|
25
|
+
%em Build ##{build.number} - #{build.status}
|
26
|
+
:css
|
27
|
+
ul.hudson-builds li.failing { padding-left: 37%; height: 3em; margin-bottom: 0.5em; }
|
28
|
+
ul.hudson-builds li.failing .indicator {
|
29
|
+
display: block;
|
30
|
+
width: 50%;
|
31
|
+
height: 3em;
|
32
|
+
float: left;
|
33
|
+
margin-left: -58%;
|
34
|
+
background-color: #fc2015;
|
35
|
+
border-radius: 5px;
|
36
|
+
-moz-border-radius: 5px;
|
37
|
+
-webkit-border-radius: 5px;
|
38
|
+
}
|
39
|
+
ul.hudson-builds li.failing h3 { margin-bottom: 0}
|
40
|
+
ul.hudson-builds li.failing em { color: #BBB; font-size: 0.8em; }
|
41
|
+
|
42
|
+
ul.hudson-builds li.building { padding-left: 37%; height: 1.5em; margin-bottom: 0.5em; }
|
43
|
+
ul.hudson-builds li.building .indicator {
|
44
|
+
display: block;
|
45
|
+
width: 50%;
|
46
|
+
height: 1.5em;
|
47
|
+
float: left;
|
48
|
+
margin-left: -58%;
|
49
|
+
background-color: #fcce15;
|
50
|
+
border-radius: 5px;
|
51
|
+
-moz-border-radius: 5px;
|
52
|
+
-webkit-border-radius: 5px;
|
53
|
+
}
|
54
|
+
ul.hudson-builds li.building h3 { margin-bottom: 0}
|
55
|
+
ul.hudson-builds li.building em { display:none; }
|
56
|
+
|
57
|
+
ul.hudson-builds li.passing {
|
58
|
+
float: left;
|
59
|
+
margin-right: 1.5em;
|
60
|
+
padding: 5px 0 5px 18px;
|
61
|
+
}
|
62
|
+
ul.hudson-builds li.passing .indicator {
|
63
|
+
display: block;
|
64
|
+
width: 14px;
|
65
|
+
height: 14px;
|
66
|
+
float: left;
|
67
|
+
margin-left: -18px;
|
68
|
+
background-color: #4ad026;
|
69
|
+
border-radius: 7px;
|
70
|
+
-moz-border-radius: 7px;
|
71
|
+
-webkit-border-radius: 7px;
|
72
|
+
}
|
73
|
+
ul.hudson-builds li.passing h3 { font-size: 1.1em; margin: 0;}
|
74
|
+
ul.hudson-builds li.passing em { display: none }
|
75
|
+
ul.hudson-builds li .indicator {
|
76
|
+
box-shadow: 1px 1px 3px #222;
|
77
|
+
-moz-box-shadow: 1px 1px 3px #222;
|
78
|
+
-webkit-box-shadow: 1px 1px 3px #222;
|
79
|
+
}
|
80
|
+
:javascript
|
81
|
+
function animateHudsonBuilds() {
|
82
|
+
$('ul.hudson-builds li.building .indicator').animate({opacity:0.05},2000,function(){
|
83
|
+
$('ul.hudson-builds li.building .indicator').animate({opacity:1},2000,animateHudsonBuilds);
|
84
|
+
});
|
85
|
+
}
|
86
|
+
animateHudsonBuilds();
|
87
|
+
]
|
88
|
+
|
89
|
+
def builds
|
90
|
+
return [] unless feed.respond_to?(:entries) # Error fetching feed
|
91
|
+
|
92
|
+
builds = feed.entries.map{|rss_entry| Build.new(rss_entry)}
|
93
|
+
builds.reject! {|build| build.project.match Regexp.new(@options[:ignore_projects], true)} if @options[:ignore_projects].present?
|
94
|
+
builds.sort
|
95
|
+
end
|
96
|
+
|
97
|
+
def feed
|
98
|
+
return unless @options[:rss_feed].present?
|
99
|
+
|
100
|
+
feed_options = {:timeout => 10}
|
101
|
+
feed_options[:http_authentication] = [@options[:http_auth_username], @options[:http_auth_password]] if @options[:http_auth_username].present?
|
102
|
+
|
103
|
+
@feed ||= Feedzirra::Feed.fetch_and_parse(@options[:rss_feed], feed_options)
|
104
|
+
end
|
105
|
+
|
106
|
+
class Build
|
107
|
+
TitleRegexp = /^(.*) #(\d+) \((.*)\)$/
|
108
|
+
|
109
|
+
attr_reader :rss_entry
|
110
|
+
|
111
|
+
def initialize(rss_entry)
|
112
|
+
@rss_entry = rss_entry
|
113
|
+
end
|
114
|
+
|
115
|
+
def passing?
|
116
|
+
status.match(/(stable|back to normal)/i)
|
117
|
+
end
|
118
|
+
|
119
|
+
def failing?
|
120
|
+
status.match(/broken/)
|
121
|
+
end
|
122
|
+
|
123
|
+
def building?
|
124
|
+
status.match(/^\?$/)
|
125
|
+
end
|
126
|
+
|
127
|
+
def project
|
128
|
+
rss_entry.title.match(TitleRegexp)[1]
|
129
|
+
end
|
130
|
+
|
131
|
+
def number
|
132
|
+
rss_entry.title.match(TitleRegexp)[2]
|
133
|
+
end
|
134
|
+
|
135
|
+
def status
|
136
|
+
rss_entry.title.match(TitleRegexp)[3]
|
137
|
+
end
|
138
|
+
|
139
|
+
def label
|
140
|
+
if passing?
|
141
|
+
'passing'
|
142
|
+
elsif failing?
|
143
|
+
'failing'
|
144
|
+
elsif building?
|
145
|
+
'building'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def <=>(other_build)
|
150
|
+
order = ['failing','building','passing']
|
151
|
+
result = order.index(self.label) <=> order.index(other_build.label)
|
152
|
+
result = self.project <=> other_build.project if result.zero?
|
153
|
+
result
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
Relevant.register Relevant::Hudson
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Relevant::Hudson do
|
4
|
+
|
5
|
+
describe "#feed" do
|
6
|
+
it 'fetches and parses the RSS feed' do
|
7
|
+
hudson = Relevant::Hudson.setup(:rss_feed => 'http://hudson.example.com/rssLatest')
|
8
|
+
|
9
|
+
Feedzirra::Feed.expects(:fetch_and_parse).with('http://hudson.example.com/rssLatest', {:timeout => 10}).returns(:feed)
|
10
|
+
hudson.feed.should == :feed
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'will pass basic auth credentials if provided' do
|
14
|
+
hudson = Relevant::Hudson.setup(
|
15
|
+
:rss_feed => 'http://hudson.example.com/rssLatest',
|
16
|
+
:http_auth_username => 'admin',
|
17
|
+
:http_auth_password => 'letmein'
|
18
|
+
)
|
19
|
+
|
20
|
+
Feedzirra::Feed.expects(:fetch_and_parse).with(
|
21
|
+
'http://hudson.example.com/rssLatest', {
|
22
|
+
:timeout => 10,
|
23
|
+
:http_authentication => ['admin','letmein']
|
24
|
+
})
|
25
|
+
hudson.feed
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#builds' do
|
30
|
+
before do
|
31
|
+
@passing_entry = stub('entry', :title => 'Bar Project #15 (stable)')
|
32
|
+
@failing_entry = stub('entry', :title => 'Foo Project #99 (broken since build #85)')
|
33
|
+
@hudson = Relevant::Hudson.setup
|
34
|
+
@hudson.stubs(:feed).returns(stub('feed', :title => 'RSS Feed', :entries => [@passing_entry, @failing_entry]))
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'translates rss entries into builds' do
|
38
|
+
@hudson.builds.all?{|build| build.is_a? Relevant::Hudson::Build}.should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'sorts the builds to have failing ones first' do
|
42
|
+
@hudson.builds.first.should be_failing
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'ignores projects by matching against its name' do
|
46
|
+
hudson = Relevant::Hudson.setup :ignore_projects => '^foo'
|
47
|
+
hudson.stubs(:feed).returns(stub('feed', :title => 'RSS Feed', :entries => [@passing_entry, @failing_entry]))
|
48
|
+
|
49
|
+
hudson.builds.map(&:project).should_not include('Foo Project')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Relevant::Hudson::Build do
|
54
|
+
it 'knows the project of the build' do
|
55
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (broken since build #85)')
|
56
|
+
build.project.should == 'Foo Project'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'knows the number of the build' do
|
60
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (broken since build #85)')
|
61
|
+
build.number.should == '99'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'knows the status of the build' do
|
65
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (broken since build #85)')
|
66
|
+
build.status.should == 'broken since build #85'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'is passing if the build is stable' do
|
70
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (stable)')
|
71
|
+
build.should be_passing
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'is passing if the build is back to normal' do
|
75
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (back to normal)')
|
76
|
+
build.should be_passing
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'is failing if the build is broken' do
|
80
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (broken since build #85)')
|
81
|
+
build.should_not be_passing
|
82
|
+
build.should be_failing
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'is building if the status is unknown' do
|
86
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (?)')
|
87
|
+
build.should_not be_passing
|
88
|
+
build.should_not be_failing
|
89
|
+
build.should be_building
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'label' do
|
93
|
+
it "is 'passing' if the build is passing?" do
|
94
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (stable)')
|
95
|
+
build.label.should == 'passing'
|
96
|
+
end
|
97
|
+
|
98
|
+
it "is 'building' if the build is building?" do
|
99
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (?)')
|
100
|
+
build.label.should == 'building'
|
101
|
+
end
|
102
|
+
|
103
|
+
it "is 'failing' if the build is failing?" do
|
104
|
+
build = Relevant::Hudson::Build.new stub('entry', :title => 'Foo Project #99 (broken)')
|
105
|
+
build.label.should == 'failing'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift "../lib"
|
4
|
+
require "relevant/hudson"
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.color_enabled = true
|
8
|
+
config.mock_with :mocha
|
9
|
+
|
10
|
+
config.formatter = :progress
|
11
|
+
config.color_enabled = true
|
12
|
+
config.filter_run :focused => true
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.alias_example_to :fit, :focused => true
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: relevant-hudson
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jared Pace
|
13
|
+
- Rob Sanheim
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-09-24 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: relevant-widget
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- 6
|
33
|
+
version: 0.0.6
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: feedzirra
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 2
|
59
|
+
- 0
|
60
|
+
- 0
|
61
|
+
- beta
|
62
|
+
- 22
|
63
|
+
version: 2.0.0.beta.22
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
description: Check the time
|
67
|
+
email: opensource@thinkrelevance.com
|
68
|
+
executables: []
|
69
|
+
|
70
|
+
extensions: []
|
71
|
+
|
72
|
+
extra_rdoc_files:
|
73
|
+
- README.md
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- lib/relevant/hudson.rb
|
79
|
+
- spec/relevant/hudson_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
has_rdoc: true
|
82
|
+
homepage: http://github.com/relevance/relevant-hudson
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --charset=UTF-8
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.3.7
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Hudson widget for Relevant
|
113
|
+
test_files:
|
114
|
+
- spec/relevant/hudson_spec.rb
|
115
|
+
- spec/spec_helper.rb
|