octopusci 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/octopusci/job.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Octopusci
2
2
  class Job
3
- def self.run(job_record)
3
+ def self.run(job_rec)
4
4
  raise PureVirtualMethod, "The self.commit_run method needs to be defined on your Octopusci::Job."
5
5
  end
6
6
 
@@ -28,6 +28,9 @@ module Octopusci
28
28
  job.save
29
29
 
30
30
  begin
31
+ job.clone_code(job_conf)
32
+ job.checkout_branch(job_conf)
33
+
31
34
  rv = self.run(job)
32
35
  if ::Job::STATUS.keys.include?(rv)
33
36
  job.status = 0
@@ -49,6 +52,8 @@ module Octopusci
49
52
  ensure
50
53
  job.ended_at = Time.new
51
54
  job.save
55
+
56
+ Octopusci::Notifier.job_complete(job, job_conf, job.successful?)
52
57
  end
53
58
  end
54
59
  ensure
@@ -4,13 +4,8 @@
4
4
  <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
5
5
  </head>
6
6
  <body>
7
- <h1>Octopusci Build (<%= @status_str %>) - <%= @job.repo_name %> / <%= @job.ref.gsub(/refs\/heads\//, '') %></h1>
8
- <h2>Status: <%= @status_str %></h2>
9
- <h2>Command Output:</h2>
10
- <pre>
11
- <code>
12
- <%= @cmd_output %>
13
- </code>
14
- </pre>
7
+ <h1>Octopusci Build (<%= @status_str %>) - <%= @job.repo_name %> / <%= @job.branch_name %></h1>
8
+ <h2>Output:</h2>
9
+ <pre><code><%= @job.output %></code></pre>
15
10
  </body>
16
11
  </html>
@@ -1,9 +1,5 @@
1
1
  # Octopusci Build
2
2
 
3
- ## Command Status
4
-
5
- <%= @cmd_status %>
6
-
7
3
  ## Command Output
8
4
 
9
- <%= @cmd_output %>
5
+ <%= @cmd_output %>
@@ -7,30 +7,29 @@ ActionMailer::Base.view_paths = File.dirname(__FILE__) + '/../'
7
7
 
8
8
  module Octopusci
9
9
  class Notifier < ActionMailer::Base
10
- def job_complete(recipient, cmd_output, cmd_status, github_payload, job_id)
11
- @job = ::Job.find(job_id)
12
- @job.output = cmd_output
13
- if cmd_status == 0
14
- @job.successful = true
10
+ def job_complete(job_rec, job_conf, success=false)
11
+ @job = job_rec
12
+ if success
13
+ @status_str = 'success'
15
14
  else
16
- @job.successful = false
15
+ @status_str = 'failed'
17
16
  end
18
- @job.save
19
17
 
20
- if recipient
21
- @cmd_output = cmd_output
22
- @cmd_status = cmd_status
23
- @github_payload = github_payload
24
- if @cmd_status == 0
25
- @status_str = 'success'
18
+ recip_email = nil
19
+ if job_rec.branch_name == 'master'
20
+ recip_email = job_conf['default_email']
21
+ else
22
+ if job_rec.github_payload['pusher']['email']
23
+ recip_email = job_rec.github_payload['pusher']['email']
26
24
  else
27
- @status_str = 'failed'
28
- end
29
- mail(:to => recipient, :subject => "Octopusci Build (#{@status_str}) - #{@job.repo_name} / #{@job.ref.gsub(/refs\/heads\//, '')}") do |format|
30
- format.text
31
- format.html
25
+ recip_email = job_conf['default_email']
32
26
  end
33
27
  end
28
+
29
+ mail(:to => recip_email, :subject => "Octopusci Build (#{@status_str}) - #{@job.repo_name} / #{@job.branch_name}") do |format|
30
+ format.text
31
+ format.html
32
+ end
34
33
  end
35
34
  end
36
35
  end
@@ -21,6 +21,18 @@ class Job < ActiveRecord::Base
21
21
  return STATUS[self.status]
22
22
  end
23
23
 
24
+ def successful?
25
+ return self.status == 'successful'
26
+ end
27
+
28
+ def failed?
29
+ return self.status == 'failed'
30
+ end
31
+
32
+ def finished?
33
+ return ['successful', 'failed', 'error'].include?(self.status)
34
+ end
35
+
24
36
  def output
25
37
  if File.exists?(self.abs_output_file_path)
26
38
  return File.open(self.abs_output_file_path, 'r').read()
@@ -28,6 +40,14 @@ class Job < ActiveRecord::Base
28
40
  return ""
29
41
  end
30
42
  end
43
+
44
+ def silent_output
45
+ if File.exists?(self.abs_silent_output_file_path)
46
+ return File.open(self.abs_silent_output_file_path, 'r').read()
47
+ else
48
+ return ""
49
+ end
50
+ end
31
51
 
32
52
  def workspace_path
33
53
  return "#{Octopusci::CONFIG['general']['workspace_base_path']}/#{self.stage}"
@@ -42,6 +62,10 @@ class Job < ActiveRecord::Base
42
62
  return "#{Octopusci::CONFIG['general']['workspace_base_path']}#{self.rel_output_file_path}"
43
63
  end
44
64
 
65
+ def abs_silent_output_file_path
66
+ return "#{self.abs_output_path}/silent_output.txt"
67
+ end
68
+
45
69
  def repository_path
46
70
  return "#{self.workspace_path}/#{self.repo_name}"
47
71
  end
@@ -58,8 +82,10 @@ class Job < ActiveRecord::Base
58
82
  if self.code_cloned?
59
83
  return 0
60
84
  else
61
- exit_stat = self.run_command("cd #{self.workspace_path} 2>&1 && git clone #{job_conf['repo_uri']} #{self.repo_name} 2>&1", true)
62
- return exit_stat.exitstatus.to_i
85
+ if !Dir.exists?(self.workspace_path)
86
+ FileUtils.mkdir_p(self.workspace_path)
87
+ end
88
+ return self.run_command("cd #{self.workspace_path} 2>&1 && git clone #{job_conf['repo_uri']} #{self.repo_name} 2>&1", true)
63
89
  end
64
90
  end
65
91
 
@@ -68,8 +94,7 @@ class Job < ActiveRecord::Base
68
94
  self.clone_code(job_conf)
69
95
  end
70
96
 
71
- exit_stat = self.run_command("cd #{self.repository_path} 2>&1 && git fetch --all -p 2>&1 && git checkout #{self.branch_name} 2>&1 && git pull -f origin #{self.branch_name}:#{self.branch_name} 2>&1", true)
72
- return exit_stat.exitstatus.to_i
97
+ return self.run_command("cd #{self.repository_path} 2>&1 && git fetch --all -p 2>&1 && git checkout #{self.branch_name} 2>&1 && git pull -f origin #{self.branch_name}:#{self.branch_name} 2>&1", true)
73
98
  end
74
99
 
75
100
  # Runs a command and logs it standard output to the job's associated
@@ -81,26 +106,26 @@ class Job < ActiveRecord::Base
81
106
  FileUtils.mkdir_p(self.abs_output_path)
82
107
  end
83
108
 
109
+ out_f = nil
110
+
84
111
  # Run the command and output the output to the job file
85
- if !silently
112
+ if silently
113
+ out_f = File.open(self.abs_silent_output_file_path, 'a')
114
+ else
86
115
  out_f = File.open(self.abs_output_file_path, 'a')
87
- out_f << "\n\nRunning: #{cmd_str}\n"
88
- out_f << "-"*30
89
- out_f << "\n"
90
- out_f.flush
91
116
  end
117
+ out_f << "\n\nRunning: #{cmd_str}\n"
118
+ out_f << "-"*30
119
+ out_f << "\n"
120
+ out_f.flush
92
121
 
93
122
  f = IO.popen(cmd_str)
94
123
  while(cur_line = f.gets) do
95
- if !silently
96
- out_f << cur_line
97
- out_f.flush
98
- end
124
+ out_f << cur_line
125
+ out_f.flush
99
126
  end
100
127
 
101
- if !silently
102
- out_f.close
103
- end
128
+ out_f.close
104
129
  f.close
105
130
 
106
131
  return $?.exitstatus.to_i
@@ -25,7 +25,7 @@
25
25
  <%= erb :job_summary, :locals => { :j => j } %>
26
26
  </div>
27
27
  <div class="job_content">
28
- <div class="job_output hidden"><pre><code><%= j.output %></code></pre></div>
28
+ <div class="job_output"><pre><code><%= j.output %></code></pre></div>
29
29
  </div>
30
30
  </div>
31
31
  <% end %>
@@ -0,0 +1,26 @@
1
+ <script type="text/javascript" charset="utf-8">
2
+ $(document).ready(function() {
3
+ var t = setInterval(function() {
4
+ $('.job .status.pending,.job .status.running').each(function () {
5
+ var job_div = $(this).closest('.job');
6
+
7
+ job_div.find('.job_summary').first().load(job_div.attr('data-summary-url'));
8
+ job_div.find('.output > pre > code').first().load(job_div.attr('data-output-url'));
9
+ job_div.find('.silent_output > pre > code').first().load(job_div.attr('data-silent-output-url'));
10
+ });
11
+ }, 5000);
12
+ });
13
+ </script>
14
+ <div id="job_<%= @job.id%>" class="job status_<%= @job.status %>" data-status-url="/jobs/<%= @job.id %>/status" data-output-url="/jobs/<%= @job.id %>/output" data-silent-output-url="/jobs/<%= @job.id %>/silent_output" data-summary-url="/jobs/<%= @job.id %>/ajax_summary">
15
+ <div class="job_summary">
16
+ <%= erb :job_summary, :locals => { :j => @job } %>
17
+ </div>
18
+ <div class="job_content">
19
+ Output:
20
+ <div class="output job_output" style="display: block;"><pre><code><%= @job.output %></code></pre></div>
21
+ </div>
22
+ <div class="job_content">
23
+ Log:
24
+ <div class="silent_output job_output" style="display: block;"><pre><code><%= @job.silent_output %></code></pre></div>
25
+ </div>
26
+ </div>
@@ -2,7 +2,7 @@
2
2
  <div class="job_title">
3
3
  <span class="status <%= j.status %>"></span>
4
4
  <div style="float: left;">
5
- <a href="<%= j.payload['repository']['url'] %>"><%= j.repo_name %></a> / <a href="/<%= j.repo_name %>/<%= j.branch_name %>"><%= j.branch_name %></a>
5
+ <a href="<%= j.payload['repository']['url'] %>"><%= j.repo_name %></a> / <a href="/<%= j.repo_name %>/<%= j.branch_name %>/jobs"><%= j.branch_name %></a>
6
6
  </div>
7
7
  <div style="clear: both;"></div>
8
8
  </div>
@@ -15,7 +15,7 @@
15
15
  <table>
16
16
  <tr>
17
17
  <td style="text-align: right;">Job:</td>
18
- <td style="width: 200px;"><%= j.id %></td>
18
+ <td style="width: 200px;"><a href="/jobs/<%= j.id %>"><%= j.id %></a></td>
19
19
  <td style="text-align: right;">Before Commit:</td>
20
20
  <td>
21
21
  <% if !j.payload['created'] %>
@@ -68,6 +68,10 @@
68
68
  <td>
69
69
  <a class="show_hide_job_output" style="display: block; float: left;" href="#">toggle</a><div class="output_busy" style="float: left; margin-left: 5px; margin-top: 2px; <% if j.status == 'running' %>display: block;<% else %>display: none;<% end %>"><img src="/images/ajax-loader-1.gif" style="height: 12px;"/></div><div style="clear: both;"></div>
70
70
  </td>
71
+ <td style="text-align: right;">Log:</td>
72
+ <td>
73
+ <a target="_blank" href="/jobs/<%= j.id %>/silent_output">click here</a>
74
+ </td>
71
75
  </tr>
72
76
  </table>
73
77
  </div>
@@ -97,7 +97,7 @@
97
97
 
98
98
  .status {
99
99
  overflow: visible;
100
- background: url("../images/status2.png");
100
+ background: url("/images/status2.png");
101
101
  float: left;
102
102
  width: 26px;
103
103
  height: 26px;
@@ -122,7 +122,7 @@
122
122
  }
123
123
 
124
124
  .error {
125
- background-position: 0px -132px;
125
+ background-position: 0px -26px;
126
126
  }
127
127
  </style>
128
128
  </head>
@@ -35,13 +35,19 @@ module Octopusci
35
35
  erb :index
36
36
  end
37
37
 
38
- get '/:repo_name/:branch_name' do
38
+ get '/:repo_name/:branch_name/jobs' do
39
39
  protected!
40
40
  @page_logo = "#{params[:repo_name]} / #{params[:branch_name]}"
41
41
  @jobs = ::Job.where(:repo_name => params[:repo_name], :ref => "refs/heads/#{params[:branch_name]}").order('jobs.created_at DESC').limit(20)
42
42
  erb :index
43
43
  end
44
44
 
45
+ get '/jobs/:job_id' do
46
+ protected!
47
+ @job = ::Job.find(params[:job_id])
48
+ erb :job
49
+ end
50
+
45
51
  get '/jobs/:job_id/output' do
46
52
  protected!
47
53
  @job = ::Job.find(params[:job_id])
@@ -49,6 +55,13 @@ module Octopusci
49
55
  return @job.output
50
56
  end
51
57
 
58
+ get '/jobs/:job_id/silent_output' do
59
+ protected!
60
+ @job = ::Job.find(params[:job_id])
61
+ content_type('text/plain')
62
+ return @job.silent_output
63
+ end
64
+
52
65
  get '/jobs/:job_id/status' do
53
66
  protected!
54
67
  @job = ::Job.find(params[:job_id])
@@ -1,3 +1,3 @@
1
1
  module Octopusci
2
- Version = VERSION = '0.2.0'
2
+ Version = VERSION = '0.2.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octopusci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ date: 2011-09-28 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
17
- requirement: &70291783224220 !ruby/object:Gem::Requirement
17
+ requirement: &70178118072320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70291783224220
25
+ version_requirements: *70178118072320
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &70291783210520 !ruby/object:Gem::Requirement
28
+ requirement: &70178118066860 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70291783210520
36
+ version_requirements: *70178118066860
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: resque
39
- requirement: &70291783209560 !ruby/object:Gem::Requirement
39
+ requirement: &70178118064820 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70291783209560
47
+ version_requirements: *70178118064820
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: actionmailer
50
- requirement: &70291783207940 !ruby/object:Gem::Requirement
50
+ requirement: &70178118063100 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70291783207940
58
+ version_requirements: *70178118063100
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: activerecord
61
- requirement: &70291783206840 !ruby/object:Gem::Requirement
61
+ requirement: &70178118061380 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: '0'
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70291783206840
69
+ version_requirements: *70178118061380
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: mysql
72
- requirement: &70291783205440 !ruby/object:Gem::Requirement
72
+ requirement: &70178118050900 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '0'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *70291783205440
80
+ version_requirements: *70178118050900
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: multi_json
83
- requirement: &70291783203200 !ruby/object:Gem::Requirement
83
+ requirement: &70178118049440 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '0'
89
89
  type: :runtime
90
90
  prerelease: false
91
- version_requirements: *70291783203200
91
+ version_requirements: *70178118049440
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: time-ago-in-words
94
- requirement: &70291783181960 !ruby/object:Gem::Requirement
94
+ requirement: &70178118047860 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: '0'
100
100
  type: :runtime
101
101
  prerelease: false
102
- version_requirements: *70291783181960
102
+ version_requirements: *70178118047860
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rake
105
- requirement: &70291783179780 !ruby/object:Gem::Requirement
105
+ requirement: &70178118043500 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ! '>='
@@ -110,10 +110,10 @@ dependencies:
110
110
  version: '0'
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *70291783179780
113
+ version_requirements: *70178118043500
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: rspec
116
- requirement: &70291783145000 !ruby/object:Gem::Requirement
116
+ requirement: &70178118036140 !ruby/object:Gem::Requirement
117
117
  none: false
118
118
  requirements:
119
119
  - - ! '>='
@@ -121,10 +121,10 @@ dependencies:
121
121
  version: '0'
122
122
  type: :development
123
123
  prerelease: false
124
- version_requirements: *70291783145000
124
+ version_requirements: *70178118036140
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rack-test
127
- requirement: &70291783142300 !ruby/object:Gem::Requirement
127
+ requirement: &70178118027000 !ruby/object:Gem::Requirement
128
128
  none: false
129
129
  requirements:
130
130
  - - ! '>='
@@ -132,10 +132,10 @@ dependencies:
132
132
  version: '0'
133
133
  type: :development
134
134
  prerelease: false
135
- version_requirements: *70291783142300
135
+ version_requirements: *70178118027000
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: guard
138
- requirement: &70291783104620 !ruby/object:Gem::Requirement
138
+ requirement: &70178118023200 !ruby/object:Gem::Requirement
139
139
  none: false
140
140
  requirements:
141
141
  - - ! '>='
@@ -143,10 +143,10 @@ dependencies:
143
143
  version: '0'
144
144
  type: :development
145
145
  prerelease: false
146
- version_requirements: *70291783104620
146
+ version_requirements: *70178118023200
147
147
  - !ruby/object:Gem::Dependency
148
148
  name: rb-fsevent
149
- requirement: &70291783079720 !ruby/object:Gem::Requirement
149
+ requirement: &70178118007000 !ruby/object:Gem::Requirement
150
150
  none: false
151
151
  requirements:
152
152
  - - ! '>='
@@ -154,10 +154,10 @@ dependencies:
154
154
  version: '0'
155
155
  type: :development
156
156
  prerelease: false
157
- version_requirements: *70291783079720
157
+ version_requirements: *70178118007000
158
158
  - !ruby/object:Gem::Dependency
159
159
  name: growl
160
- requirement: &70291783069020 !ruby/object:Gem::Requirement
160
+ requirement: &70178118000460 !ruby/object:Gem::Requirement
161
161
  none: false
162
162
  requirements:
163
163
  - - ! '>='
@@ -165,10 +165,10 @@ dependencies:
165
165
  version: '0'
166
166
  type: :development
167
167
  prerelease: false
168
- version_requirements: *70291783069020
168
+ version_requirements: *70178118000460
169
169
  - !ruby/object:Gem::Dependency
170
170
  name: guard-rspec
171
- requirement: &70291783049440 !ruby/object:Gem::Requirement
171
+ requirement: &70178117997180 !ruby/object:Gem::Requirement
172
172
  none: false
173
173
  requirements:
174
174
  - - ! '>='
@@ -176,7 +176,7 @@ dependencies:
176
176
  version: '0'
177
177
  type: :development
178
178
  prerelease: false
179
- version_requirements: *70291783049440
179
+ version_requirements: *70178117997180
180
180
  description: A multi-branch Continous Integration server that integrates with GitHub
181
181
  email:
182
182
  - cyphactor@gmail.com
@@ -207,6 +207,7 @@ files:
207
207
  - lib/octopusci/server/public/javascripts/jquery-1.6.4.min.js
208
208
  - lib/octopusci/server/views/hello_world.erb
209
209
  - lib/octopusci/server/views/index.erb
210
+ - lib/octopusci/server/views/job.erb
210
211
  - lib/octopusci/server/views/job_summary.erb
211
212
  - lib/octopusci/server/views/layout.erb
212
213
  - lib/octopusci/server.rb