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 ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ relevant*.gem
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
@@ -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