octopusci 0.2.0 → 0.2.2

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/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