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 +2 -1
- data/Gemfile.lock +5 -1
- data/build_status_server.gemspec +1 -1
- data/config/config-example.yml +1 -0
- data/lib/build_status_server.html +118 -0
- data/lib/build_status_server/config.html +157 -0
- data/lib/build_status_server/config.rb +4 -0
- data/lib/build_status_server/server.html +202 -0
- data/lib/build_status_server/server.rb +52 -53
- data/lib/build_status_server/version.html +32 -0
- data/lib/build_status_server/version.rb +1 -1
- data/spec/lib/build_status_server/config_spec.rb +7 -7
- data/spec/lib/build_status_server/server_spec.rb +288 -11
- metadata +8 -7
- data/lib/build_status_server.rb~ +0 -10
- data/lib/build_status_server/server.rb~ +0 -162
- data/lib/build_status_server/version.rb~ +0 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
build_status_server (0.
|
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
|
data/build_status_server.gemspec
CHANGED
@@ -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
|
22
|
+
s.files = Dir["{lib/**/*,spec/**/*.rb,spec/support/*}"] + %w(
|
23
23
|
Gemfile
|
24
24
|
Gemfile.lock
|
25
25
|
LICENSE
|
data/config/config-example.yml
CHANGED
@@ -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 …
|
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">¶</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' 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'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">"rubygems"</span>
|
105
|
+
<span class="nb">require</span> <span class="s2">"json"</span>
|
106
|
+
<span class="nb">require</span> <span class="s2">"socket"</span>
|
107
|
+
<span class="nb">require</span> <span class="s2">"timeout"</span>
|
108
|
+
<span class="nb">require</span> <span class="s2">"yaml"</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">'build_status_server/config'</span>
|
112
|
+
<span class="nb">autoload</span> <span class="ss">:Server</span><span class="p">,</span> <span class="s1">'build_status_server/server'</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 …
|
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">¶</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">¶</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">&</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">"."</span><span class="p">,</span> <span class="n">store</span><span class="o">[</span><span class="s2">"filename"</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">¶</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">"verbose"</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">¶</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">"Supplied config file (</span><span class="si">#{</span><span class="n">config_file</span><span class="si">}</span><span class="s2">) doesn't seem to exist"</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"><<-</span><span class="no">EOT</span>
|
117
|
+
<span class="sh">Looks like there isn't an available configuration file for this program.</span>
|
118
|
+
<span class="sh">We're very diligently going to use some sensible defaults, but you'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("\n ")}</span>
|
122
|
+
|
123
|
+
<span class="sh"> Here is a sample of the contents for that file (and the settings we'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">"This is an invalid configuration file!"</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">"</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"</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>
|
@@ -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 …
|
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">¶</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">"address"</span><span class="o">]</span><span class="p">,</span> <span class="n">udp_server</span><span class="o">[</span><span class="s2">"port"</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"><<-</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["address"]}:#{udp_server["port"]}</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">"Listening on UDP </span><span class="si">#{</span><span class="n">udp_server</span><span class="o">[</span><span class="s2">"address"</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">"port"</span><span class="o">]</span><span class="si">}</span><span class="s2">"</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">"Good bye."</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">"{}"</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">"name"</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">"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">"regex"</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">"policy"</span><span class="o">]</span><span class="si">}</span><span class="s2">)"</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">"build"</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">"Pinged with an invalid payload"</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">"build"</span><span class="o">][</span><span class="s2">"phase"</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">"build"</span><span class="o">][</span><span class="s2">"status"</span><span class="o">]</span>
|
113
|
+
|
114
|
+
<span class="k">if</span> <span class="n">phase</span> <span class="o">==</span> <span class="s2">"FINISHED"</span>
|
115
|
+
<span class="no">STDOUT</span><span class="o">.</span><span class="n">puts</span> <span class="s2">"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">]"</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">"SUCCESS"</span><span class="p">,</span> <span class="s2">"FAILURE"</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">"w"</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">"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">]"</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">&&</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">"regex"</span><span class="o">]</span> <span class="o">&&</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">"policy"</span><span class="o">]</span> <span class="o">==</span> <span class="s2">"include"</span> <span class="o">&&</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">"regex"</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">"policy"</span><span class="o">]</span> <span class="o">!=</span> <span class="s2">"include"</span> <span class="o">&&</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">"regex"</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">&&=</span> <span class="p">(</span><span class="n">val</span> <span class="o">==</span> <span class="s2">"pass"</span> <span class="o">||</span> <span class="n">val</span> <span class="o">==</span> <span class="s2">"SUCCESS"</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">"pass"</span><span class="o">]</span> <span class="p">:</span> <span class="n">tcp_client</span><span class="o">[</span><span class="s2">"fail"</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">"host"</span><span class="o">]</span><span class="p">,</span> <span class="n">tcp_client</span><span class="o">[</span><span class="s2">"port"</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">"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">"</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">=></span> <span class="n">ex</span>
|
166
|
+
<span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">"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">"</span>
|
167
|
+
<span class="k">retry</span> <span class="k">unless</span> <span class="n">attempts</span> <span class="o">></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">=></span> <span class="n">ex</span>
|
169
|
+
<span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">"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">"</span>
|
170
|
+
<span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">"Will wait for 2 seconds and try again..."</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">></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"> "name":"test",</span>
|
183
|
+
<span class="cp"> "url":"job/test/",</span>
|
184
|
+
<span class="cp"> "build":{</span>
|
185
|
+
<span class="cp"> "full_url":"http://cronus.local:3001/job/test/20/",</span>
|
186
|
+
<span class="cp"> "number":20,</span>
|
187
|
+
<span class="cp"> "phase":"FINISHED",</span>
|
188
|
+
<span class="cp"> "status":"SUCCESS",</span>
|
189
|
+
<span class="cp"> "url":"job/test/20/"</span>
|
190
|
+
<span class="cp"> }</span>
|
191
|
+
<span class="cp">}</span>
|
192
|
+
|
193
|
+
<span class="cp">We're getting this error once in a while:</span>
|
194
|
+
<span class="cp">/usr/local/lib/ruby/1.8/timeout.rb:64:in `notify': execution expired (Timeout::Error)</span>
|
195
|
+
<span class="cp"> from /home/jcmuller/build_notifier/lib/server.rb:102:in `notify'</span>
|
196
|
+
<span class="cp"> from /home/jcmuller/build_notifier/lib/server.rb:33:in `listen'</span>
|
197
|
+
<span class="cp"> from bin/server:5</span></pre></div>
|
198
|
+
</td>
|
199
|
+
</tr>
|
200
|
+
</table>
|
201
|
+
</div>
|
202
|
+
</body>
|