mattmatt-cijoe 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ class CIJoe
2
+ Version = "0.1.2"
3
+ end
@@ -0,0 +1,64 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link href="<%= cijoe_root %>/screen.css" media="screen" rel="stylesheet" type="text/css" />
5
+ <title><%= h(joe.project) %>: CI Joe</title>
6
+ </head>
7
+ <body>
8
+ <div class="site">
9
+ <div class="title">
10
+ <a href="<%= cijoe_root %>/">CI Joe</a>
11
+ <span class="extra">because knowing is half the battle</span>
12
+ </div>
13
+
14
+ <div id="home">
15
+ <h1><a href="<%= joe.url %>"><%= joe.project %></a></h1>
16
+ <ul class="posts">
17
+ <% if joe.current_build %>
18
+ <li>
19
+ <span class="date"><%= pretty_time(joe.current_build.started_at) if joe.current_build %></span> &raquo;
20
+ <% if joe.current_build.sha %>
21
+ Building <a href="<%= joe.url %>/commits/<%= joe.current_build.sha %>"><%= joe.current_build.short_sha %></a> <small>(pid: <%= joe.pid %>)</small>
22
+ <% else %>
23
+ Build starting...
24
+ <% end %>
25
+ </li>
26
+ <% else %>
27
+ <li><form method="POST"><input type="submit" value="Build"/></form></li>
28
+ <% end %>
29
+
30
+ <% if joe.last_build %>
31
+ <li><span class="date"><%= pretty_time(joe.last_build.finished_at) %></span> &raquo; Built <a href="<%= joe.url %>/commits/<%= joe.last_build.sha %>"><%= joe.last_build.short_sha %></a> <span class="<%= joe.last_build.status %>">(<%= joe.last_build.status %>)</span></li>
32
+ <% if joe.last_build.failed? %>
33
+ <li><pre class="terminal"><code><%=ansi_color_codes h(joe.last_build.output) %></code></pre></li>
34
+ <% end %>
35
+ <% end %>
36
+ </ul>
37
+ </div>
38
+
39
+ <div class="footer">
40
+ <div class="contact">
41
+ <p>
42
+ <a href="http://github.com/defunkt/cijoe/tree/master#readme">Documentation</a><br/>
43
+ <a href="http://github.com/defunkt/cijoe">Source</a><br/>
44
+ <a href="http://github.com/defunkt/cijoe/issues">Issues</a><br/>
45
+ <a href="http://twitter.com/defunkt">Twitter</a>
46
+ </p>
47
+ </div>
48
+ <div class="contact">
49
+ <p>
50
+ Designed by <a href="http://tom.preston-werner.com/">Tom Preston-Werner</a><br/>
51
+ Influenced by <a href="http://integrityapp.com/">Integrity</a><br/>
52
+ Built with <a href="http://sinatrarb.com/">Sinatra</a><br/>
53
+ Keep it simple, Sam.
54
+ </p>
55
+ </div>
56
+ <div class="rss">
57
+ <a href="http://github.com/defunkt/cijoe">
58
+ <img src="<%= cijoe_root %>/octocat.png" alt="Octocat!" />
59
+ </a>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </body>
64
+ </html>
@@ -0,0 +1,286 @@
1
+ # this was taken from
2
+ # http://github.com/lsegal/mmmail/
3
+
4
+ require 'net/smtp'
5
+
6
+ module MmMail
7
+ # General exception class when something goes wrong in MmMail
8
+ class TransportError < Exception; end
9
+
10
+ # Handles the transportation of a {Message} to its destination.
11
+ # Basic support for SMTP (through +Net::SMTP+) or +sendmail+.
12
+ #
13
+ # You can either pass a new {Transport::Config} object during transport or use
14
+ # the system wide {Transport::DefaultConfig} object.
15
+ #
16
+ # @example [To set transport to use sendmail]
17
+ # MmMail::Transport::DefaultConfig.method = :sendmail
18
+ # # Note you might need to point to sendmail if it's not in your PATH:
19
+ # MmMail::Transport::DefaultConfig.sendmail_binary = '/path/to/sendmail'
20
+ #
21
+ # @example [To connect to your ISP SMTP server on 587]
22
+ # MmMail::Transport::DefaultConfig.host = 'smtp.myisp.com'
23
+ # MmMail::Transport::DefaultConfig.port = 587
24
+ #
25
+ # @see Transport::Config
26
+ # @see Transport::mail
27
+ class Transport
28
+ # Configuration class for a {Transport}
29
+ class Config
30
+ # Set/get the SMTP host/port information
31
+ attr_accessor :host, :port
32
+
33
+ # Set/get the authentication type (nil for none, :plain, :login or :cram_md5)
34
+ attr_accessor :auth_type
35
+
36
+ # Set/get the AUTH user/password when using SMTP transport.
37
+ attr_accessor :auth_user, :auth_pass
38
+
39
+ # Set/get the email method. Allowed values are +:smtp+ or +:sendmail+.
40
+ attr_accessor :method
41
+
42
+ # Set/get the location of the sendmail binary on the system
43
+ attr_accessor :sendmail_binary
44
+
45
+ # Creates a new Config object set to send via SMTP on
46
+ # localhost:25 with no authentication.
47
+ def initialize
48
+ @method = :smtp # :sendmail
49
+ @host = 'localhost'
50
+ @port = 25
51
+ @auth_type = nil # :plain, :login, :cram_md5
52
+ @auth_user = nil
53
+ @auth_pass = nil
54
+ @sendmail_binary = 'sendmail'
55
+ end
56
+ end
57
+
58
+ # The default system wide configuration used when no custom config
59
+ # object is provided to a Transport object. If you want to make global
60
+ # configuration changes, change the settings here.
61
+ DefaultConfig = Config.new
62
+
63
+ # Creates a new {Transport} object and sends an email.
64
+ #
65
+ # @see #mail
66
+ def self.mail(message, config = nil)
67
+ new(config).mail(message)
68
+ end
69
+
70
+ # Sets a {Config} object to use when sending mail
71
+ attr_accessor :config
72
+
73
+ # Creates a new Transport object to send emails with. To change
74
+ # settings to sendmail or use SMTP auth, set these in the {Config}
75
+ # object.
76
+ #
77
+ # @param [Config] a configuration to use
78
+ # @raise [ArgumentError] if config is not a {Config} object.
79
+ def initialize(config = nil)
80
+ if config && !config.is_a?(Config)
81
+ raise ArgumentError, "expected #{self.class}::Config"
82
+ end
83
+
84
+ @config = config || DefaultConfig
85
+ end
86
+
87
+ # Sends a {Message} object out as an email using the configuration
88
+ # set during initialization.
89
+ #
90
+ # @param [Message] message an email to send
91
+ # @raise [ArgumentError] if message is not a {Message} object
92
+ # @raise [TransportError] if message is not {Message#valid? valid}.
93
+ def mail(message)
94
+ unless Message === message
95
+ raise ArgumentError, "expected MmMail::Message, got #{message.class}"
96
+ end
97
+
98
+ raise TransportError, "invalid message" unless message.valid?
99
+
100
+ send("mail_#{config.method}", message)
101
+ end
102
+
103
+ # Sends a mail through Net::SMTP using the {#config} if
104
+ # any SMTP or hostname information is set.
105
+ #
106
+ # @param [#to_s] message the message to send
107
+ def mail_smtp(message)
108
+ Net::SMTP.start(config.host, config.port, 'localhost.localdomain',
109
+ config.auth_user, config.auth_pass, config.auth_type) do |smtp|
110
+ smtp.send_message(message.to_s, message.from, message.recipients_list)
111
+ end
112
+ end
113
+
114
+ # Sends a mail through sendmail using the {Config#sendmail_binary} as the
115
+ # location of the file.
116
+ #
117
+ # @param [#to_s] message the message to send
118
+ # @raise [TransportError] if a problem during execution occured
119
+ def mail_sendmail(message)
120
+ bin, err = config.sendmail_binary, ''
121
+ result = IO.popen("#{bin} -t 2>&1", "w+") do |io|
122
+ io.write(message.to_s)
123
+ io.close_write
124
+ err = io.read.chomp
125
+ end
126
+
127
+ raise TransportError, err if $? != 0
128
+ end
129
+ end
130
+
131
+ # A Message object representing an Email to be passed to a {Transport}.
132
+ class Message
133
+ # Creates a new message with associated fields.
134
+ #
135
+ # @example
136
+ # MmMail::Message.new(:to => 'test@example.com', :body => 'hi')
137
+ #
138
+ # @param [Hash] opts the options to create a message with.
139
+ # @option opts [String] :from ('nobody@localhost') The email's From field
140
+ # @option opts [String] :subject ('') The email's Subject field
141
+ # @option opts [String] :body ('') The email's body (not a header)
142
+ # @option opts [String] :to (nil) The email's To field. List multiple recipients as
143
+ # 'a@b.c, b@c.d', not an array.
144
+ def initialize(opts = {})
145
+ defaults = {
146
+ :from => 'nobody@localhost',
147
+ :subject => '',
148
+ :body => ''
149
+ }
150
+ @headers = defaults.merge(opts)
151
+ end
152
+
153
+ # Allow access of fields by header name or symbolic representation
154
+ #
155
+ # @example
156
+ # m[:x_message_id] = '1234'
157
+ # m['X-Message-Id'] == '1234' # => true
158
+ #
159
+ # @param [String, Symbol] k the header or symbolic header value to lookup.
160
+ # @return [String] the value associated with the field
161
+ def [](k) @headers[translate_header_to_sym(k)] end
162
+
163
+ # Allow access of fields by header name or symbolic representation
164
+ #
165
+ # @example
166
+ # m[:x_message_id] = '1234'
167
+ # m['X-Message-Id'] == '1234' # => true
168
+ #
169
+ def []=(k, v) @headers[translate_header_to_sym(k)] = v end
170
+
171
+ # Override this method to allow any call to obj.meth or obj.meth= to
172
+ # set a header field on this object.
173
+ #
174
+ # @example [To set the field 'X-Message-Id']
175
+ # m.x_message_id = '1234'
176
+ # m.x_message_id == '1234' # => true
177
+ #
178
+ def method_missing(sym, *args)
179
+ if sym.to_s =~ /=$/
180
+ self[sym.to_s[0..-2].to_sym] = args.first
181
+ elsif @headers.has_key?(sym)
182
+ self[sym]
183
+ else
184
+ super
185
+ end
186
+ end
187
+
188
+ # Override this method to verify if a field has been set.
189
+ #
190
+ # @return [Boolean] whether the field was set (or if a regular method
191
+ # is callable.)
192
+ def respond_to?(sym)
193
+ return true if super
194
+ @headers.has_key?(sym)
195
+ end
196
+
197
+ # Returns the message in its full form as expected by an SMTP server.
198
+ #
199
+ # @return [String] the email with headers followed by a body
200
+ def to_s
201
+ [headers, body].join("\n")
202
+ end
203
+
204
+ # Returns all the recipients in the To field.
205
+ #
206
+ # @example
207
+ # m.to = 'a@b.c, b@c.d'
208
+ # m.recipients_list # => ['a@b.c', 'b@c.d']
209
+ #
210
+ # @return [Array<String>] the emails in the To field of the message.
211
+ def recipients_list
212
+ to.split(/\s*,\s*/)
213
+ end
214
+
215
+ # Checks if the message is valid. Validity is based on
216
+ # having the From, To and Subject fields set. From and To
217
+ # must not be empty.
218
+ #
219
+ # @return [Boolean] whether or not the message is a valid e-mail
220
+ def valid?
221
+ [:from, :to].each do |field|
222
+ return false if !self[field] || self[field].empty?
223
+ end
224
+
225
+ self[:subject] ? true : false
226
+ end
227
+
228
+ private
229
+
230
+ # Returns the headers as the RFC822 string.
231
+ #
232
+ # @return [String] the headers in RFC822 format
233
+ def headers
234
+ @headers.reject {|k, v| k == :body }.map do |k, v|
235
+ translate_header_name(k) + ': ' + v + "\n"
236
+ end.join
237
+ end
238
+
239
+ # Translates a header from its symbolic representation to its
240
+ # RFC822 header name or the other way around. If you give in
241
+ # a header name (String) you will get a Symbol, and a Symbol
242
+ # if you give a String.
243
+ #
244
+ # @example
245
+ # msg.translate_header_name(:x_message_id) # => 'X-Message-Id'
246
+ # msg.translate_header_name('Content-Type') # => :content_type
247
+ #
248
+ # @param [String,Symbol] key the header name to translate
249
+ # @return [Symbol,String] the symbolic or header representation of
250
+ # the symbol or header name.
251
+ # @raise [ArgumentError] if key is neither a String or Symbol
252
+ def translate_header_name(key)
253
+ case key
254
+ when String
255
+ key.downcase.tr('-', '_').to_sym
256
+ when Symbol
257
+ key.to_s.capitalize.gsub(/_(.)/) {|m| '-' + m[1].upcase }
258
+ else
259
+ raise ArgumentError, "invalid key type #{key.class}"
260
+ end
261
+ end
262
+
263
+ # Translates a header one-way to the symbolic representation.
264
+ #
265
+ # @param [String, Symbol] key any header or symbolic key
266
+ # @return [Symbol] the symbolic representation of the header name
267
+ # @see #translate_header_name
268
+ def translate_header_to_sym(key)
269
+ return key if Symbol === key
270
+ translate_header_name(key)
271
+ end
272
+ end
273
+
274
+ # Quickly send out an email.
275
+ #
276
+ # @example
277
+ # MmMail.mail(:to => 'me@gmail.com', :body => 'hi!')
278
+ #
279
+ # @param [Hash] opts the hash used to construct the message
280
+ # @param [Transport::Config, nil] config the configuration object to use
281
+ # during transport
282
+ # @see Transport#mail
283
+ def self.mail(opts = {}, config = nil)
284
+ Transport.mail(Message.new(opts), config)
285
+ end
286
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/../lib/cijoe'
2
+ require 'ostruct'
3
+
4
+ describe CIJoe::Email do
5
+
6
+ describe "activate" do
7
+ it "should include Email into the Build class if the config is valid" do
8
+ CIJoe::Config.stub!(:email => stub(:to => 'build@housetrip.com', :user => 'joe', :pass => 'passwd', :host => 'mail.example.com'))
9
+
10
+ CIJoe::Email.activate
11
+ CIJoe::Build.ancestors.should include(CIJoe::Email)
12
+ end
13
+
14
+ it "should not include Email into the Build class if the config is not valid" do
15
+ CIJoe::Email.activate
16
+ CIJoe::Build.ancestors.should_not include(CIJoe::Email)
17
+ end
18
+ end
19
+
20
+
21
+ describe "notify" do
22
+ class TestBuild
23
+ include CIJoe::Email
24
+
25
+ def initialize(worked)
26
+ @worked = worked
27
+ end
28
+
29
+ def worked?
30
+ @worked
31
+ end
32
+
33
+ def failed?
34
+ !@worked
35
+ end
36
+
37
+ def commit
38
+ OpenStruct.new(:url => "github.com/commit/bha75as")
39
+ end
40
+ end
41
+
42
+ CIJoe::Config.class_eval do
43
+ def self.email
44
+ OpenStruct.new(
45
+ :to => 'build@housetrip.com'
46
+ )
47
+ end
48
+ end
49
+
50
+ it "should send an email if the build failed" do
51
+ MmMail.should_receive(:send).with(:to => 'build@housetrip.com', :from => 'build@housetrip.com', :subject => 'Build failed', :body => 'The commit github.com/commit/bha75as caused the build to fail.')
52
+ TestBuild.new(false).notify
53
+ end
54
+
55
+ it "should send no email if the build succeeded" do
56
+ MmMail.should_not_receive(:send)
57
+ TestBuild.new(true).notify
58
+ end
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mattmatt-cijoe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wanstrath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-22 00:00:00 +01:00
13
+ default_executable: cijoe
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: choice
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: sinatra
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: open4
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: CI Joe is a simple Continuous Integration server.
46
+ email: chris@ozmm.org
47
+ executables:
48
+ - cijoe
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - LICENSE
53
+ - README.markdown
54
+ files:
55
+ - .gitignore
56
+ - LICENSE
57
+ - README.markdown
58
+ - Rakefile
59
+ - VERSION
60
+ - bin/cijoe
61
+ - deps.rip
62
+ - examples/cijoe.ru
63
+ - examples/cijoed
64
+ - lib/cijoe.rb
65
+ - lib/cijoe/build.rb
66
+ - lib/cijoe/commit.rb
67
+ - lib/cijoe/config.rb
68
+ - lib/cijoe/email.rb
69
+ - lib/cijoe/public/octocat.png
70
+ - lib/cijoe/public/screen.css
71
+ - lib/cijoe/server.rb
72
+ - lib/cijoe/version.rb
73
+ - lib/cijoe/views/template.erb
74
+ - lib/mmmail.rb
75
+ - spec/email_spec.rb
76
+ has_rdoc: true
77
+ homepage: http://github.com/defunkt/cijoe
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options:
82
+ - --charset=UTF-8
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: "0"
96
+ version:
97
+ requirements: []
98
+
99
+ rubyforge_project:
100
+ rubygems_version: 1.3.5
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: CI Joe is a simple Continuous Integration server.
104
+ test_files:
105
+ - spec/email_spec.rb