build_status_server 0.8 → 0.9

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/Gemfile CHANGED
@@ -6,10 +6,11 @@ gem "json"
6
6
 
7
7
  group :test do
8
8
  gem "rspec"
9
+ gem "ci_reporter"
10
+ gem "ruby-debug"
9
11
  end
10
12
 
11
13
  group :development do
12
- gem "ruby-debug"
13
14
  gem "sinatra"
14
15
  end
15
16
 
data/Gemfile.lock CHANGED
@@ -1,12 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- build_status_server (0.7)
4
+ build_status_server (0.8)
5
5
  json
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
+ builder (3.0.0)
11
+ ci_reporter (1.7.0)
12
+ builder (>= 2.1.2)
10
13
  columnize (0.3.6)
11
14
  diff-lcs (1.1.3)
12
15
  json (1.6.5)
@@ -41,6 +44,7 @@ PLATFORMS
41
44
 
42
45
  DEPENDENCIES
43
46
  build_status_server!
47
+ ci_reporter
44
48
  json
45
49
  rake
46
50
  rspec
@@ -19,7 +19,7 @@ Notification Plugin)) and an Arduino powered Traffic Light controller
19
19
  EOS
20
20
  s.description = "A build notifier server for Jenkins CI that controls an XFD over HTTP"
21
21
 
22
- s.files = Dir["{lib/**/*,spec/**/*}"] + %w(
22
+ s.files = Dir["{lib/**/*,spec/**/*.rb,spec/support/*}"] + %w(
23
23
  Gemfile
24
24
  Gemfile.lock
25
25
  LICENSE
@@ -6,6 +6,7 @@
6
6
  port: 4567
7
7
  pass: /green
8
8
  fail: /red
9
+ attempts: 5
9
10
  store:
10
11
  filename: /tmp/build_result.yml
11
12
  mask:
@@ -0,0 +1,118 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>build_status_server.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="build_status_server.html">build_status_server.rb</a>
16
+ <a class="source" href="build_status_server/config.html">config.rb</a>
17
+ <a class="source" href="build_status_server/server.html">server.rb</a>
18
+ <a class="source" href="build_status_server/version.html">version.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>build_status_server.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-Installation'>
31
+ <td class=docs>
32
+ <div class="pilwrap">
33
+ <a class="pilcrow" href="#section-Installation">&#182;</a>
34
+ </div>
35
+ <p><strong>Build Notifier</strong></p>
36
+
37
+ <p>This utility is part of an XFD (eXtreeme Feedback Device) solution designed and
38
+ built for my employer <a href="http://challengepost.com">ChallengePost</a>. It works in
39
+ conjunction with our <a href="http://jenkins-ci.org">Jenkins</a> Continuous Integration
40
+ server (and its
41
+ <a href="https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin">Notification Plugin</a>)
42
+ and an <a href="http://arduino.cc">Arduino</a> powered
43
+ <a href="https://github.com/jcmuller/TrafficLightController">Traffic Light controller</a>
44
+ with a
45
+ pseudo-<a href="http://en.wikipedia.org/wiki/Representational_state_transfer">REST</a>ful
46
+ API.</p>
47
+
48
+ <p>To run, you need to create a <code>config.yml</code> file. The first time you run the
49
+ application without any arguments, you will get a sample.</p>
50
+
51
+ <h1>Installation</h1>
52
+
53
+ <p>$ gem install build<em>status</em>server</p>
54
+
55
+ <h1>Execution</h1>
56
+
57
+ <p>See the options you can pass in by:</p>
58
+
59
+ <p>$ build<em>status</em>server -h</p>
60
+
61
+ <h1>Configuration file</h1>
62
+
63
+ <h2>UDP Server</h2>
64
+
65
+ <p>This section defines what interface and port should the UDP server listen at.
66
+ The Jenkins&#39; Notification Plugin should be set to this parameters as well.</p>
67
+
68
+ <h2>TCP Client</h2>
69
+
70
+ <p>This section is where we tell the server how to communicate with the web
71
+ enabled XFD. In the example case, there is a web server running somewhere
72
+ listening on port 4567 that responds to <code>/green</code> and <code>/red</code>.</p>
73
+
74
+ <p>On our installation, this represents the Traffic Light&#39;s Arduino web server.</p>
75
+
76
+ <h2>Store</h2>
77
+
78
+ <p>Where the persistent state will be stored.</p>
79
+
80
+ <h2>Mask (optional)</h2>
81
+
82
+ <p>You can decide to either include or ignore certain builds whose names match a
83
+ given <a href="http://en.wikipedia.org/wiki/Regular_expression">Regular Expression</a>.</p>
84
+
85
+ <h2>Verbose</h2>
86
+
87
+ <p>Whether to display informative output messages.</p>
88
+
89
+ <h1>Development</h1>
90
+
91
+ <p><code>bin/build_status_server_traffic_light_mock</code> is provided for development
92
+ purposes only.</p>
93
+
94
+ <h1>Finished product</h1>
95
+
96
+ <p><img src="http://i.imgur.com/aK5rs.jpg" alt="my image"></p>
97
+
98
+ <h1>Wiring the traffic light</h1>
99
+
100
+ <p><img src="http://i.imgur.com/gUpWe.jpg" alt="my image"></p>
101
+
102
+ </td>
103
+ <td class=code>
104
+ <div class='highlight'><pre><span class="nb">require</span> <span class="s2">&quot;rubygems&quot;</span>
105
+ <span class="nb">require</span> <span class="s2">&quot;json&quot;</span>
106
+ <span class="nb">require</span> <span class="s2">&quot;socket&quot;</span>
107
+ <span class="nb">require</span> <span class="s2">&quot;timeout&quot;</span>
108
+ <span class="nb">require</span> <span class="s2">&quot;yaml&quot;</span>
109
+
110
+ <span class="k">module</span> <span class="nn">BuildStatusServer</span>
111
+ <span class="nb">autoload</span> <span class="ss">:Config</span><span class="p">,</span> <span class="s1">&#39;build_status_server/config&#39;</span>
112
+ <span class="nb">autoload</span> <span class="ss">:Server</span><span class="p">,</span> <span class="s1">&#39;build_status_server/server&#39;</span>
113
+ <span class="k">end</span></pre></div>
114
+ </td>
115
+ </tr>
116
+ </table>
117
+ </div>
118
+ </body>
@@ -0,0 +1,157 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>config.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="../build_status_server.html">build_status_server.rb</a>
16
+ <a class="source" href="config.html">config.rb</a>
17
+ <a class="source" href="server.html">server.rb</a>
18
+ <a class="source" href="version.html">version.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>config.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-1'>
31
+ <td class=docs>
32
+ <div class="pilwrap">
33
+ <a class="pilcrow" href="#section-1">&#182;</a>
34
+ </div>
35
+
36
+ </td>
37
+ <td class=code>
38
+ <div class='highlight'><pre><span class="k">module</span> <span class="nn">BuildStatusServer</span>
39
+ <span class="k">class</span> <span class="nc">Config</span>
40
+ <span class="kp">attr_reader</span> <span class="ss">:config</span>
41
+
42
+ <span class="k">def</span> <span class="nf">initialize</span>
43
+ <span class="vi">@config</span> <span class="o">=</span> <span class="p">{}</span>
44
+ <span class="k">end</span></pre></div>
45
+ </td>
46
+ </tr>
47
+ <tr id='section-2'>
48
+ <td class=docs>
49
+ <div class="pilwrap">
50
+ <a class="pilcrow" href="#section-2">&#182;</a>
51
+ </div>
52
+ <p>This is responsible of loading the config object</p>
53
+ </td>
54
+ <td class=code>
55
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
56
+ <span class="n">config</span> <span class="o">=</span> <span class="n">load_config_file</span><span class="p">(</span><span class="n">options</span><span class="o">[</span><span class="ss">:config</span><span class="o">]</span><span class="p">)</span>
57
+ <span class="n">import_config</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span>
58
+ <span class="k">end</span>
59
+
60
+ <span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="n">meth</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
61
+ <span class="k">return</span> <span class="n">config</span><span class="o">[</span><span class="n">meth</span><span class="o">.</span><span class="n">to_s</span><span class="o">]</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">has_key?</span><span class="p">(</span><span class="n">meth</span><span class="o">.</span><span class="n">to_s</span><span class="p">)</span>
62
+ <span class="k">super</span>
63
+ <span class="k">end</span>
64
+
65
+ <span class="k">def</span> <span class="nf">store_file</span>
66
+ <span class="k">return</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">,</span> <span class="n">store</span><span class="o">[</span><span class="s2">&quot;filename&quot;</span><span class="o">]</span><span class="p">)</span> <span class="k">if</span> <span class="n">store</span>
67
+ <span class="kp">nil</span>
68
+ <span class="k">end</span>
69
+
70
+ <span class="kp">private</span></pre></div>
71
+ </td>
72
+ </tr>
73
+ <tr id='section-3'>
74
+ <td class=docs>
75
+ <div class="pilwrap">
76
+ <a class="pilcrow" href="#section-3">&#182;</a>
77
+ </div>
78
+ <p>This will load the passed in config object into the config attribute</p>
79
+ </td>
80
+ <td class=code>
81
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">import_config</span><span class="p">(</span><span class="n">config</span> <span class="o">=</span> <span class="p">{},</span> <span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
82
+ <span class="n">config</span><span class="o">[</span><span class="s2">&quot;verbose&quot;</span><span class="o">]</span> <span class="o">=</span> <span class="n">options</span><span class="o">[</span><span class="ss">:verbose</span><span class="o">]</span> <span class="k">unless</span> <span class="n">options</span><span class="o">[</span><span class="ss">:verbose</span><span class="o">].</span><span class="n">nil?</span>
83
+ <span class="vi">@config</span> <span class="o">=</span> <span class="n">config</span>
84
+ <span class="k">end</span></pre></div>
85
+ </td>
86
+ </tr>
87
+ <tr id='section-4'>
88
+ <td class=docs>
89
+ <div class="pilwrap">
90
+ <a class="pilcrow" href="#section-4">&#182;</a>
91
+ </div>
92
+ <p>This is responsible to return a hash with the contents of a YAML file</p>
93
+
94
+ </td>
95
+ <td class=code>
96
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">load_config_file</span><span class="p">(</span><span class="n">config_file</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
97
+ <span class="n">curated_file</span> <span class="o">=</span> <span class="kp">nil</span>
98
+
99
+ <span class="k">if</span> <span class="n">config_file</span>
100
+ <span class="n">f</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">config_file</span><span class="p">)</span>
101
+ <span class="k">if</span> <span class="no">File</span><span class="o">.</span><span class="n">exists?</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
102
+ <span class="n">curated_file</span> <span class="o">=</span> <span class="n">f</span>
103
+ <span class="k">else</span>
104
+ <span class="k">raise</span> <span class="s2">&quot;Supplied config file (</span><span class="si">#{</span><span class="n">config_file</span><span class="si">}</span><span class="s2">) doesn&#39;t seem to exist&quot;</span>
105
+ <span class="k">end</span>
106
+ <span class="k">else</span>
107
+ <span class="n">locations_to_try</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">possible_conf_file</span><span class="o">|</span>
108
+ <span class="n">f</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">possible_conf_file</span><span class="p">)</span>
109
+ <span class="k">if</span> <span class="no">File</span><span class="o">.</span><span class="n">exists?</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
110
+ <span class="n">curated_file</span> <span class="o">=</span> <span class="n">f</span>
111
+ <span class="k">break</span>
112
+ <span class="k">end</span>
113
+ <span class="k">end</span>
114
+
115
+ <span class="k">if</span> <span class="n">curated_file</span><span class="o">.</span><span class="n">nil?</span>
116
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="o">&lt;&lt;-</span><span class="no">EOT</span>
117
+ <span class="sh">Looks like there isn&#39;t an available configuration file for this program.</span>
118
+ <span class="sh">We&#39;re very diligently going to use some sensible defaults, but you&#39;re</span>
119
+ <span class="sh">strongly recommended to create one in any of the following locations:</span>
120
+
121
+ <span class="sh"> #{locations_to_try.join(&quot;\n &quot;)}</span>
122
+
123
+ <span class="sh"> Here is a sample of the contents for that file (and the settings we&#39;re going</span>
124
+ <span class="sh"> to use):</span>
125
+
126
+ <span class="sh">#{get_example_config}</span>
127
+ <span class="no"> EOT</span>
128
+
129
+ <span class="k">return</span> <span class="no">YAML</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">get_example_config</span><span class="p">)</span>
130
+ <span class="k">end</span>
131
+ <span class="k">end</span>
132
+
133
+ <span class="no">YAML</span><span class="o">.</span><span class="n">load_file</span><span class="p">(</span><span class="n">curated_file</span><span class="p">)</span><span class="o">.</span><span class="n">tap</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
134
+ <span class="k">raise</span> <span class="s2">&quot;This is an invalid configuration file!&quot;</span> <span class="k">unless</span> <span class="n">config</span><span class="o">.</span><span class="n">class</span> <span class="o">==</span> <span class="no">Hash</span>
135
+ <span class="k">end</span>
136
+ <span class="k">end</span>
137
+
138
+ <span class="k">def</span> <span class="nf">locations_to_try</span>
139
+ <span class="sx">%w(</span>
140
+ <span class="sx"> ~/.config/build_status_server/config.yml</span>
141
+ <span class="sx"> ./config/config.yml</span>
142
+ <span class="sx"> /etc/build_status_server/config.yml</span>
143
+ <span class="sx"> /usr/local/etc/build_status_server/config.yml</span>
144
+ <span class="sx"> )</span>
145
+ <span class="k">end</span>
146
+
147
+ <span class="k">def</span> <span class="nf">get_example_config</span>
148
+ <span class="n">filename</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="no">File</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="bp">__FILE__</span><span class="p">))</span><span class="si">}</span><span class="s2">/../../config/config-example.yml&quot;</span>
149
+ <span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span><span class="o">.</span><span class="n">read</span>
150
+ <span class="k">end</span>
151
+ <span class="k">end</span>
152
+ <span class="k">end</span></pre></div>
153
+ </td>
154
+ </tr>
155
+ </table>
156
+ </div>
157
+ </body>
@@ -17,6 +17,10 @@ module BuildStatusServer
17
17
  super
18
18
  end
19
19
 
20
+ def respond_to?(meth)
21
+ config.has_key?(meth.to_s) || super
22
+ end
23
+
20
24
  def store_file
21
25
  return File.expand_path(".", store["filename"]) if store
22
26
  nil
@@ -0,0 +1,202 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>server.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="../build_status_server.html">build_status_server.rb</a>
16
+ <a class="source" href="config.html">config.rb</a>
17
+ <a class="source" href="server.html">server.rb</a>
18
+ <a class="source" href="version.html">version.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>server.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-1'>
31
+ <td class=docs>
32
+ <div class="pilwrap">
33
+ <a class="pilcrow" href="#section-1">&#182;</a>
34
+ </div>
35
+ <p>TODO
36
+ move all configuration stuff to Config
37
+ and just call config[:blaj] instead of if blah</p>
38
+
39
+ </td>
40
+ <td class=code>
41
+ <div class='highlight'><pre><span class="k">module</span> <span class="nn">BuildStatusServer</span>
42
+ <span class="k">class</span> <span class="nc">Server</span>
43
+ <span class="kp">attr_reader</span> <span class="ss">:config</span><span class="p">,</span> <span class="ss">:store</span>
44
+
45
+ <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
46
+ <span class="vi">@config</span> <span class="o">=</span> <span class="no">Config</span><span class="o">.</span><span class="n">new</span>
47
+ <span class="n">config</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
48
+ <span class="k">end</span>
49
+
50
+ <span class="k">def</span> <span class="nf">listen</span>
51
+ <span class="n">sock</span> <span class="o">=</span> <span class="no">UDPSocket</span><span class="o">.</span><span class="n">new</span>
52
+ <span class="n">udp_server</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">udp_server</span>
53
+
54
+ <span class="k">begin</span>
55
+ <span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">udp_server</span><span class="o">[</span><span class="s2">&quot;address&quot;</span><span class="o">]</span><span class="p">,</span> <span class="n">udp_server</span><span class="o">[</span><span class="s2">&quot;port&quot;</span><span class="o">]</span><span class="p">)</span>
56
+ <span class="k">rescue</span> <span class="no">Errno</span><span class="o">::</span><span class="no">EADDRINUSE</span>
57
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="o">&lt;&lt;-</span><span class="no">EOT</span>
58
+ <span class="sh">There appears that another instance is running, or another process</span>
59
+ <span class="sh">is listening at the same port (#{udp_server[&quot;address&quot;]}:#{udp_server[&quot;port&quot;]}</span>
60
+
61
+ <span class="no"> EOT</span>
62
+ <span class="nb">exit</span>
63
+ <span class="k">end</span>
64
+
65
+ <span class="nb">puts</span> <span class="s2">&quot;Listening on UDP </span><span class="si">#{</span><span class="n">udp_server</span><span class="o">[</span><span class="s2">&quot;address&quot;</span><span class="o">]</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="n">udp_server</span><span class="o">[</span><span class="s2">&quot;port&quot;</span><span class="o">]</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">verbose</span>
66
+
67
+ <span class="k">begin</span>
68
+ <span class="k">while</span> <span class="kp">true</span>
69
+ <span class="n">data</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recvfrom</span><span class="p">(</span><span class="mi">2048</span><span class="p">)</span>
70
+
71
+ <span class="k">if</span> <span class="n">process_job</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
72
+ <span class="n">status</span> <span class="o">=</span> <span class="n">process_all_statuses</span>
73
+ <span class="n">notify</span><span class="p">(</span><span class="n">status</span><span class="p">)</span>
74
+ <span class="k">end</span>
75
+ <span class="k">end</span>
76
+ <span class="k">rescue</span> <span class="no">Interrupt</span>
77
+ <span class="nb">puts</span> <span class="s2">&quot;Good bye.&quot;</span>
78
+ <span class="n">sock</span><span class="o">.</span><span class="n">close</span>
79
+ <span class="nb">exit</span>
80
+ <span class="k">end</span>
81
+ <span class="k">end</span>
82
+
83
+ <span class="kp">private</span>
84
+
85
+ <span class="k">def</span> <span class="nf">load_store</span>
86
+ <span class="vi">@store</span> <span class="o">=</span> <span class="k">begin</span>
87
+ <span class="no">YAML</span><span class="o">.</span><span class="n">load_file</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">store_file</span><span class="p">)</span>
88
+ <span class="k">rescue</span>
89
+ <span class="p">{}</span>
90
+ <span class="k">end</span>
91
+ <span class="vi">@store</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">unless</span> <span class="n">store</span><span class="o">.</span><span class="n">class</span> <span class="o">==</span> <span class="no">Hash</span>
92
+ <span class="k">end</span>
93
+
94
+
95
+ <span class="k">def</span> <span class="nf">process_job</span><span class="p">(</span><span class="n">data</span> <span class="o">=</span> <span class="s2">&quot;{}&quot;</span><span class="p">)</span>
96
+ <span class="n">job</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
97
+
98
+ <span class="n">build_name</span> <span class="o">=</span> <span class="n">job</span><span class="o">[</span><span class="s2">&quot;name&quot;</span><span class="o">]</span>
99
+
100
+ <span class="k">unless</span> <span class="n">should_process_build</span><span class="p">(</span><span class="n">build_name</span><span class="p">)</span>
101
+ <span class="no">STDOUT</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Ignoring </span><span class="si">#{</span><span class="n">build_name</span><span class="si">}</span><span class="s2"> (</span><span class="si">#{</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;regex&quot;</span><span class="o">]</span><span class="si">}</span><span class="s2">--</span><span class="si">#{</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;policy&quot;</span><span class="o">]</span><span class="si">}</span><span class="s2">)&quot;</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">verbose</span>
102
+ <span class="k">return</span> <span class="kp">false</span>
103
+ <span class="k">end</span>
104
+
105
+ <span class="k">if</span> <span class="n">job</span><span class="o">.</span><span class="n">class</span> <span class="o">!=</span> <span class="no">Hash</span> <span class="ow">or</span>
106
+ <span class="n">job</span><span class="o">[</span><span class="s2">&quot;build&quot;</span><span class="o">].</span><span class="n">class</span> <span class="o">!=</span> <span class="no">Hash</span>
107
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Pinged with an invalid payload&quot;</span>
108
+ <span class="k">return</span> <span class="kp">false</span>
109
+ <span class="k">end</span>
110
+
111
+ <span class="n">phase</span> <span class="o">=</span> <span class="n">job</span><span class="o">[</span><span class="s2">&quot;build&quot;</span><span class="o">][</span><span class="s2">&quot;phase&quot;</span><span class="o">]</span>
112
+ <span class="n">status</span> <span class="o">=</span> <span class="n">job</span><span class="o">[</span><span class="s2">&quot;build&quot;</span><span class="o">][</span><span class="s2">&quot;status&quot;</span><span class="o">]</span>
113
+
114
+ <span class="k">if</span> <span class="n">phase</span> <span class="o">==</span> <span class="s2">&quot;FINISHED&quot;</span>
115
+ <span class="no">STDOUT</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Got </span><span class="si">#{</span><span class="n">status</span><span class="si">}</span><span class="s2"> for </span><span class="si">#{</span><span class="n">build_name</span><span class="si">}</span><span class="s2"> on </span><span class="si">#{</span><span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2"> [</span><span class="si">#{</span><span class="n">job</span><span class="o">.</span><span class="n">inspect</span><span class="si">}</span><span class="s2">]&quot;</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">verbose</span>
116
+ <span class="k">case</span> <span class="n">status</span>
117
+ <span class="k">when</span> <span class="s2">&quot;SUCCESS&quot;</span><span class="p">,</span> <span class="s2">&quot;FAILURE&quot;</span>
118
+ <span class="n">load_store</span>
119
+ <span class="n">store</span><span class="o">[</span><span class="n">build_name</span><span class="o">]</span> <span class="o">=</span> <span class="n">status</span>
120
+ <span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">store_file</span><span class="p">,</span> <span class="s2">&quot;w&quot;</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="no">YAML</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">store</span><span class="p">,</span> <span class="n">file</span><span class="p">)</span> <span class="p">}</span>
121
+ <span class="k">return</span> <span class="kp">true</span>
122
+ <span class="k">end</span>
123
+ <span class="k">else</span>
124
+ <span class="no">STDOUT</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Started for </span><span class="si">#{</span><span class="n">build_name</span><span class="si">}</span><span class="s2"> on </span><span class="si">#{</span><span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2"> [</span><span class="si">#{</span><span class="n">job</span><span class="o">.</span><span class="n">inspect</span><span class="si">}</span><span class="s2">]&quot;</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">verbose</span>
125
+ <span class="k">end</span>
126
+
127
+ <span class="k">return</span> <span class="kp">false</span>
128
+ <span class="k">end</span>
129
+
130
+ <span class="k">def</span> <span class="nf">should_process_build</span><span class="p">(</span><span class="n">build_name</span><span class="p">)</span>
131
+ <span class="c1"># If mask exists, then ...</span>
132
+ <span class="o">!</span> <span class="p">(</span>
133
+ <span class="o">!!</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span> <span class="o">&amp;&amp;</span>
134
+ <span class="o">!!</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;regex&quot;</span><span class="o">]</span> <span class="o">&amp;&amp;</span>
135
+ <span class="p">((</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;policy&quot;</span><span class="o">]</span> <span class="o">==</span> <span class="s2">&quot;include&quot;</span> <span class="o">&amp;&amp;</span> <span class="n">build_name</span> <span class="o">!~</span> <span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;regex&quot;</span><span class="o">]</span><span class="p">)</span> <span class="o">||</span>
136
+ <span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;policy&quot;</span><span class="o">]</span> <span class="o">!=</span> <span class="s2">&quot;include&quot;</span> <span class="o">&amp;&amp;</span> <span class="n">build_name</span> <span class="o">=~</span> <span class="n">config</span><span class="o">.</span><span class="n">mask</span><span class="o">[</span><span class="s2">&quot;regex&quot;</span><span class="o">]</span><span class="p">)</span>
137
+ <span class="p">))</span>
138
+ <span class="k">end</span>
139
+
140
+ <span class="k">def</span> <span class="nf">process_all_statuses</span>
141
+ <span class="n">pass</span> <span class="o">=</span> <span class="kp">true</span>
142
+
143
+ <span class="vi">@store</span><span class="o">.</span><span class="n">values</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">val</span><span class="o">|</span>
144
+ <span class="n">pass</span> <span class="o">&amp;&amp;=</span> <span class="p">(</span><span class="n">val</span> <span class="o">==</span> <span class="s2">&quot;pass&quot;</span> <span class="o">||</span> <span class="n">val</span> <span class="o">==</span> <span class="s2">&quot;SUCCESS&quot;</span><span class="p">)</span>
145
+ <span class="k">end</span>
146
+
147
+ <span class="n">pass</span>
148
+ <span class="k">end</span>
149
+
150
+ <span class="k">def</span> <span class="nf">notify</span><span class="p">(</span><span class="n">status</span><span class="p">)</span>
151
+ <span class="n">tcp_client</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">tcp_client</span>
152
+
153
+ <span class="n">attempts</span> <span class="o">=</span> <span class="mi">0</span>
154
+ <span class="n">light</span> <span class="o">=</span> <span class="n">status</span> <span class="p">?</span> <span class="n">tcp_client</span><span class="o">[</span><span class="s2">&quot;pass&quot;</span><span class="o">]</span> <span class="p">:</span> <span class="n">tcp_client</span><span class="o">[</span><span class="s2">&quot;fail&quot;</span><span class="o">]</span>
155
+
156
+ <span class="k">begin</span>
157
+ <span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="k">do</span>
158
+ <span class="n">attempts</span> <span class="o">+=</span> <span class="mi">1</span>
159
+ <span class="n">client</span> <span class="o">=</span> <span class="no">TCPSocket</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">tcp_client</span><span class="o">[</span><span class="s2">&quot;host&quot;</span><span class="o">]</span><span class="p">,</span> <span class="n">tcp_client</span><span class="o">[</span><span class="s2">&quot;port&quot;</span><span class="o">]</span><span class="p">)</span>
160
+ <span class="n">client</span><span class="o">.</span><span class="n">print</span> <span class="s2">&quot;GET </span><span class="si">#{</span><span class="n">light</span><span class="si">}</span><span class="s2"> HTTP/1.0</span><span class="se">\n\n</span><span class="s2">&quot;</span>
161
+ <span class="n">answer</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">gets</span><span class="p">(</span><span class="kp">nil</span><span class="p">)</span>
162
+ <span class="no">STDOUT</span><span class="o">.</span><span class="n">puts</span> <span class="n">answer</span> <span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">verbose</span>
163
+ <span class="n">client</span><span class="o">.</span><span class="n">close</span>
164
+ <span class="k">end</span>
165
+ <span class="k">rescue</span> <span class="no">Timeout</span><span class="o">::</span><span class="no">Error</span> <span class="o">=&gt;</span> <span class="n">ex</span>
166
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Error: </span><span class="si">#{</span><span class="n">ex</span><span class="si">}</span><span class="s2"> while trying to send </span><span class="si">#{</span><span class="n">light</span><span class="si">}</span><span class="s2">&quot;</span>
167
+ <span class="k">retry</span> <span class="k">unless</span> <span class="n">attempts</span> <span class="o">&gt;</span> <span class="mi">2</span>
168
+ <span class="k">rescue</span> <span class="no">Errno</span><span class="o">::</span><span class="no">ECONNREFUSED</span><span class="p">,</span> <span class="no">Errno</span><span class="o">::</span><span class="no">EHOSTUNREACH</span> <span class="o">=&gt;</span> <span class="n">ex</span>
169
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Error: </span><span class="si">#{</span><span class="n">ex</span><span class="si">}</span><span class="s2"> while trying to send </span><span class="si">#{</span><span class="n">light</span><span class="si">}</span><span class="s2">&quot;</span>
170
+ <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&quot;Will wait for 2 seconds and try again...&quot;</span>
171
+ <span class="nb">sleep</span> <span class="mi">2</span>
172
+ <span class="k">retry</span> <span class="k">unless</span> <span class="n">attempts</span> <span class="o">&gt;</span> <span class="mi">2</span>
173
+ <span class="k">end</span>
174
+ <span class="k">end</span>
175
+ <span class="k">end</span>
176
+ <span class="k">end</span>
177
+
178
+ <span class="cp">__END__</span>
179
+
180
+ <span class="cp">Example payload:</span>
181
+ <span class="cp">{</span>
182
+ <span class="cp"> &quot;name&quot;:&quot;test&quot;,</span>
183
+ <span class="cp"> &quot;url&quot;:&quot;job/test/&quot;,</span>
184
+ <span class="cp"> &quot;build&quot;:{</span>
185
+ <span class="cp"> &quot;full_url&quot;:&quot;http://cronus.local:3001/job/test/20/&quot;,</span>
186
+ <span class="cp"> &quot;number&quot;:20,</span>
187
+ <span class="cp"> &quot;phase&quot;:&quot;FINISHED&quot;,</span>
188
+ <span class="cp"> &quot;status&quot;:&quot;SUCCESS&quot;,</span>
189
+ <span class="cp"> &quot;url&quot;:&quot;job/test/20/&quot;</span>
190
+ <span class="cp"> }</span>
191
+ <span class="cp">}</span>
192
+
193
+ <span class="cp">We&#39;re getting this error once in a while:</span>
194
+ <span class="cp">/usr/local/lib/ruby/1.8/timeout.rb:64:in `notify&#39;: execution expired (Timeout::Error)</span>
195
+ <span class="cp"> from /home/jcmuller/build_notifier/lib/server.rb:102:in `notify&#39;</span>
196
+ <span class="cp"> from /home/jcmuller/build_notifier/lib/server.rb:33:in `listen&#39;</span>
197
+ <span class="cp"> from bin/server:5</span></pre></div>
198
+ </td>
199
+ </tr>
200
+ </table>
201
+ </div>
202
+ </body>