octopusci 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ class AddStatusJob < ActiveRecord::Migration
2
+ def self.up
3
+ add_column(:jobs, :status, :string)
4
+ add_column(:jobs, :stage, :string)
5
+ add_column(:jobs, :output_file_path, :string)
6
+ remove_column(:jobs, :output)
7
+ remove_column(:jobs, :successful)
8
+ remove_column(:jobs, :running)
9
+ end
10
+
11
+ def self.down
12
+ add_column(:jobs, :running, :boolean)
13
+ add_column(:jobs, :successful, :boolean)
14
+ add_column(:jobs, :output, :text)
15
+ remove_column(:jobs, :output_file_path)
16
+ remove_column(:jobs, :stage)
17
+ remove_column(:jobs, :status)
18
+ end
19
+ end
@@ -56,5 +56,9 @@ module Octopusci
56
56
  def self.encode(str)
57
57
  ::MultiJson.encode(str)
58
58
  end
59
+
60
+ def self.workspace_path(stage)
61
+ return Octopusci::CONFIG['general']['workspace_base_path'] + "/#{stage}"
62
+ end
59
63
  end
60
64
  end
data/lib/octopusci/job.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  module Octopusci
2
2
  class Job
3
- def self.run(github_payload, stage, job_id, job_conf)
3
+ def self.run(job_record)
4
4
  raise PureVirtualMethod, "The self.commit_run method needs to be defined on your Octopusci::Job."
5
5
  end
6
-
6
+
7
7
  def self.perform(project_name, branch_name, job_id, job_conf)
8
8
  ActiveRecord::Base.verify_active_connections!
9
9
 
@@ -23,19 +23,33 @@ module Octopusci
23
23
  job = ::Job.where("jobs.repo_name = ? && jobs.ref = ?", github_payload['repository']['name'], github_payload['ref']).order('jobs.created_at DESC').first
24
24
  if job
25
25
  job.started_at = Time.new
26
- job.running = true
27
- job.save
28
- end
29
-
30
- # Run the commit run and report about status and output
31
- # Bundler.with_clean_env {
32
- self.run(github_payload, stage, job_id, job_conf)
33
- # }
34
-
35
- if job
36
- job.ended_at = Time.new
37
- job.running = false
26
+ job.stage = stage
27
+ job.status = 'running'
38
28
  job.save
29
+
30
+ begin
31
+ rv = self.run(job)
32
+ if ::Job::STATUS.keys.include?(rv)
33
+ job.status = 0
34
+ else
35
+ if rv == 0
36
+ job.status = 'successful'
37
+ else
38
+ job.status = 'failed'
39
+ end
40
+ end
41
+ rescue => e
42
+ File.open(job.abs_output_file_path, 'a') { |f|
43
+ f << "\n\nException: #{e.message}\n"
44
+ f << "-"*30
45
+ f << "\n"
46
+ f << e.backtrace.join("\n")
47
+ }
48
+ job.status = 'error'
49
+ ensure
50
+ job.ended_at = Time.new
51
+ job.save
52
+ end
39
53
  end
40
54
  ensure
41
55
  if Octopusci::CONFIG.has_key?('stages')
@@ -10,7 +10,6 @@ module Octopusci
10
10
  def job_complete(recipient, cmd_output, cmd_status, github_payload, job_id)
11
11
  @job = ::Job.find(job_id)
12
12
  @job.output = cmd_output
13
- @job.running = false
14
13
  if cmd_status == 0
15
14
  @job.successful = true
16
15
  else
@@ -6,7 +6,7 @@ module Octopusci
6
6
  resque_opts = { "class" => job_klass, "args" => [proj_name, branch_name] }
7
7
  gh_pl_key = github_payload_key(proj_name, branch_name)
8
8
 
9
- if lismember('commit', resque_opts)
9
+ if lismember('octopusci:commit', resque_opts)
10
10
  Resque.redis.set(gh_pl_key, Resque::encode(github_payload))
11
11
  # Get the most recent job for this project and update it with the data
12
12
  job = ::Job.where("jobs.repo_name = ? && jobs.ref = ?", proj_name, '/refs/heads/' + branch_name).order('jobs.created_at DESC').first
@@ -15,11 +15,11 @@ module Octopusci
15
15
  end
16
16
  else
17
17
  # Create a new job for this project with the appropriate data
18
- job = ::Job.create(Octopusci::Helpers.gh_payload_to_job_attrs(github_payload).merge({ :running => false }))
18
+ job = ::Job.create(Octopusci::Helpers.gh_payload_to_job_attrs(github_payload).merge(:status => 'pending'))
19
19
  resque_opts["args"] << job.id
20
20
  resque_opts["args"] << job_conf
21
21
  Resque.redis.set(gh_pl_key, Resque::encode(github_payload))
22
- Resque.push('commit', resque_opts)
22
+ Resque.push('octopusci:commit', resque_opts)
23
23
  end
24
24
  end
25
25
 
@@ -1,9 +1,115 @@
1
1
  require 'active_record'
2
2
 
3
3
  class Job < ActiveRecord::Base
4
+ STATUS = {
5
+ 'pending' => 'Pending...',
6
+ 'running' => 'Running...',
7
+ 'successful' => 'Successful',
8
+ 'failed' => 'Failed',
9
+ 'error' => 'Error'
10
+ }
11
+
4
12
  serialize :payload
5
13
 
14
+ after_create :set_output_file_path
15
+
6
16
  def branch_name
7
17
  self.ref.gsub(/refs\/heads\//, '')
8
18
  end
19
+
20
+ def display_status
21
+ return STATUS[self.status]
22
+ end
23
+
24
+ def output
25
+ if File.exists?(self.abs_output_file_path)
26
+ return File.open(self.abs_output_file_path, 'r').read()
27
+ else
28
+ return ""
29
+ end
30
+ end
31
+
32
+ def workspace_path
33
+ return "#{Octopusci::CONFIG['general']['workspace_base_path']}/#{self.stage}"
34
+ end
35
+
36
+ # Relative path of the output file to the workspace base path.
37
+ def rel_output_file_path
38
+ "/jobs/#{self.id}/output.txt"
39
+ end
40
+
41
+ def abs_output_file_path
42
+ return "#{Octopusci::CONFIG['general']['workspace_base_path']}#{self.rel_output_file_path}"
43
+ end
44
+
45
+ def repository_path
46
+ return "#{self.workspace_path}/#{self.repo_name}"
47
+ end
48
+
49
+ def abs_output_path
50
+ return "#{Octopusci::CONFIG['general']['workspace_base_path']}/jobs/#{self.id}"
51
+ end
52
+
53
+ def code_cloned?
54
+ return File.directory?(self.repository_path)
55
+ end
56
+
57
+ def clone_code(job_conf)
58
+ if self.code_cloned?
59
+ return 0
60
+ 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
63
+ end
64
+ end
65
+
66
+ def checkout_branch(job_conf)
67
+ if !self.code_cloned?
68
+ self.clone_code(job_conf)
69
+ end
70
+
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
73
+ end
74
+
75
+ # Runs a command and logs it standard output to the job's associated
76
+ # output file. It also returns the exit status of the command that was
77
+ # run as the integer exit status of the commands on the command line.
78
+ def run_command(cmd_str, silently=false)
79
+ # Make sure that the directory structure is in place for the job output.
80
+ if !File.directory?(self.abs_output_path)
81
+ FileUtils.mkdir_p(self.abs_output_path)
82
+ end
83
+
84
+ # Run the command and output the output to the job file
85
+ if !silently
86
+ 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
+ end
92
+
93
+ f = IO.popen(cmd_str)
94
+ while(cur_line = f.gets) do
95
+ if !silently
96
+ out_f << cur_line
97
+ out_f.flush
98
+ end
99
+ end
100
+
101
+ if !silently
102
+ out_f.close
103
+ end
104
+ f.close
105
+
106
+ return $?.exitstatus.to_i
107
+ end
108
+
109
+ private
110
+
111
+ def set_output_file_path
112
+ self.output_file_path = self.rel_output_file_path()
113
+ self.save!
114
+ end
9
115
  end
@@ -1,97 +1,32 @@
1
- <% @jobs.each do |j| %>
2
- <div class="job">
3
- <div class="job_header">
4
- <div class="job_title">
5
- <%
6
- if j.running
7
- status_class = 'running'
8
- else
9
- if j.successful.nil?
10
- status_class = 'pending'
11
- elsif j.successful == true
12
- status_class = 'success'
13
- else
14
- status_class = 'failure'
15
- end
16
- end
17
- %>
18
- <span class="status <%= status_class %>"></span>
19
- <div style="float: left;">
20
- <a href="<%= j.payload['repository']['url'] %>"><%= j.repo_name %></a> / <a href="/<%= j.repo_name %>/<%= j.payload['ref'].gsub('refs/heads/', '') %>"><%= j.branch_name %></a>
21
- </div>
22
- <div style="clear: both;"></div>
1
+ <script type="text/javascript" charset="utf-8">
2
+ $(document).ready(function() {
3
+ $('#jobs').delegate("a.show_hide_job_output", 'click', function() {
4
+ $('.job_output').not(this).hide();
5
+ var job_cont = $(this).closest('.job_summary').next('.job_content')
6
+ var job_out = job_cont.find('.job_output').first();
7
+ job_out.toggle();
8
+ return false;
9
+ });
10
+
11
+ var t = setInterval(function() {
12
+ $('.job .status.pending,.job .status.running').each(function () {
13
+ var job_div = $(this).closest('.job');
14
+
15
+ job_div.find('.job_summary').first().load(job_div.attr('data-summary-url'));
16
+ job_div.find('.job_output > pre > code').first().load(job_div.attr('data-output-url'));
17
+ });
18
+ }, 5000);
19
+ });
20
+ </script>
21
+ <div id="jobs">
22
+ <% @jobs.each do |j| %>
23
+ <div id="job_<%= j.id%>" class="job status_<%= j.status %>" data-status-url="/jobs/<%= j.id %>/status" data-output-url="/jobs/<%= j.id %>/output" data-summary-url="/jobs/<%= j.id %>/ajax_summary">
24
+ <div class="job_summary">
25
+ <%= erb :job_summary, :locals => { :j => j } %>
23
26
  </div>
24
- <div class="created_on">
25
- <%= j.created_at.strftime('%A, %B %d, %Y AT %I:%M%p') %>
27
+ <div class="job_content">
28
+ <div class="job_output hidden"><pre><code><%= j.output %></code></pre></div>
26
29
  </div>
27
- <div style="clear: both;"></div>
28
30
  </div>
29
- <div class="job_content">
30
- <table>
31
- <tr>
32
- <td style="text-align: right;">Job:</td>
33
- <td style="width: 200px;"><%= j.id %></td>
34
- <td style="text-align: right;">Before Commit:</td>
35
- <td>
36
- <% if !j.payload['created'] %>
37
- <%= j.payload['before'] %>
38
- <% else %>
39
- No before commit, remote branch was created with this push.
40
- <% end %>
41
- </td>
42
- </tr>
43
- <tr>
44
- <td style="text-align: right;">Finished:</td>
45
- <td>
46
- <% if j.ended_at %>
47
- <%= j.ended_at.ago_in_words %>
48
- <% else %>
49
- -
50
- <% end %>
51
- </td>
52
- <td style="text-align: right;">After Commit:</td>
53
- <td>
54
- <%= j.payload['after'] %>
55
- </td>
56
- </tr>
57
- <tr>
58
- <td style="text-align: right;">Duration:</td>
59
- <td>
60
- <% if j.ended_at && j.started_at %>
61
- <%= ((j.ended_at - j.started_at)/60).to_i %> minutes
62
- <% else %>
63
- -
64
- <% end %>
65
- </td>
66
- <td style="text-align: right;">Compare:</td>
67
- <td><a href="<%= j.compare %>"><%= j.compare %></a></td>
68
- </tr>
69
- <tr>
70
- <td style="text-align: right;">Output:</td>
71
- <td>
72
- <% if j.running %>
73
- Running...
74
- <% elsif !j.running && j.successful.nil? %>
75
- Pending...
76
- <% else %>
77
- <a class="show_hide_job_output" href="#">show</a>
78
- <% end %>
79
- </td>
80
- <td style="text-align: right;">Pusher:</td>
81
- <td>
82
- <% if j.payload['pusher']['email'] %>
83
- <a href="mailto:<%= j.payload['pusher']['name'] %>"><%= j.payload['pusher']['name'] %></a>
84
- <% else %>
85
- <%= j.payload['pusher']['name'] %>
86
- <% end %>
87
- </td>
88
- </tr>
89
- </table>
90
- <div class="job_output">
91
- <pre>
92
- <code><%= j.output %></code>
93
- </pre>
94
- </div>
95
- </div>
96
- </div>
97
- <% end %>
31
+ <% end %>
32
+ </div>
@@ -0,0 +1,73 @@
1
+ <div class="job_header">
2
+ <div class="job_title">
3
+ <span class="status <%= j.status %>"></span>
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>
6
+ </div>
7
+ <div style="clear: both;"></div>
8
+ </div>
9
+ <div class="created_on">
10
+ <%= j.created_at.strftime('%A, %B %d, %Y AT %I:%M%p') %>
11
+ </div>
12
+ <div style="clear: both;"></div>
13
+ </div>
14
+ <div class="job_content">
15
+ <table>
16
+ <tr>
17
+ <td style="text-align: right;">Job:</td>
18
+ <td style="width: 200px;"><%= j.id %></td>
19
+ <td style="text-align: right;">Before Commit:</td>
20
+ <td>
21
+ <% if !j.payload['created'] %>
22
+ <%= j.payload['before'] %>
23
+ <% else %>
24
+ No before commit, remote branch was created with this push.
25
+ <% end %>
26
+ </td>
27
+ </tr>
28
+ <tr>
29
+ <td style="text-align: right;">Finished:</td>
30
+ <td>
31
+ <% if j.ended_at %>
32
+ <%= j.ended_at.ago_in_words %>
33
+ <% else %>
34
+ -
35
+ <% end %>
36
+ </td>
37
+ <td style="text-align: right;">After Commit:</td>
38
+ <td>
39
+ <%= j.payload['after'] %>
40
+ </td>
41
+ </tr>
42
+ <tr>
43
+ <td style="text-align: right;">Duration:</td>
44
+ <td>
45
+ <% if j.ended_at && j.started_at %>
46
+ <%= ((j.ended_at - j.started_at)/60).to_i %> minutes
47
+ <% else %>
48
+ -
49
+ <% end %>
50
+ </td>
51
+ <td style="text-align: right;">Compare:</td>
52
+ <td><a href="<%= j.compare %>"><%= j.compare %></a></td>
53
+ </tr>
54
+ <tr>
55
+ <td style="text-align: right;">Stage:</td>
56
+ <td><%= j.stage %></td>
57
+ <td style="text-align: right;">Pusher:</td>
58
+ <td>
59
+ <% if j.payload['pusher']['email'] %>
60
+ <a href="mailto:<%= j.payload['pusher']['name'] %>"><%= j.payload['pusher']['name'] %></a>
61
+ <% else %>
62
+ <%= j.payload['pusher']['name'] %>
63
+ <% end %>
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td style="text-align: right;">Output:</td>
68
+ <td>
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
+ </td>
71
+ </tr>
72
+ </table>
73
+ </div>
@@ -94,13 +94,10 @@
94
94
  line-height: 1.2em;
95
95
  display: none;
96
96
  }
97
-
97
+
98
98
  .status {
99
99
  overflow: visible;
100
- /* position: absolute;
101
- top: -5px;
102
- left: 0;
103
- */ background: url("../images/status2.png");
100
+ background: url("../images/status2.png");
104
101
  float: left;
105
102
  width: 26px;
106
103
  height: 26px;
@@ -108,11 +105,11 @@
108
105
  margin: 0 0 0 0;
109
106
  }
110
107
 
111
- .success {
108
+ .successful {
112
109
  background-position: 0px 0px;
113
110
  }
114
111
 
115
- .failure {
112
+ .failed {
116
113
  background-position: 0px -26px;
117
114
  }
118
115
 
@@ -123,30 +120,11 @@
123
120
  .pending {
124
121
  background-position: 0px -74px;
125
122
  }
123
+
124
+ .error {
125
+ background-position: 0px -132px;
126
+ }
126
127
  </style>
127
- <script type="text/javascript" charset="utf-8">
128
- $(document).ready(function () {
129
- // setInterval(function() {
130
- // window.location.reload();
131
- // }, 10000 );
132
-
133
- $("a.show_hide_job_output").click(function() {
134
- // $("a.show_hide_job_output ~ div.job_output").hide();
135
- // $("a.show_hide_job_output").text('show');
136
- $('a.show_hide_job_output').not(this).html('show');
137
- $('.job_output').not(this).hide();
138
-
139
- if ($(this).html() == 'show') {
140
- $(this).html('hide');
141
- $(this).closest('.job_content').find('.job_output').show();
142
- } else {
143
- $(this).html('show');
144
- $(this).closest('.job_content').find('.job_output').hide();
145
- }
146
- return false;
147
- });
148
- });
149
- </script>
150
128
  </head>
151
129
  <body>
152
130
  <div id="header">
@@ -163,8 +141,8 @@
163
141
  <div style="font-size: 14px; line-height: 1.2em; margin-left: 20px;">
164
142
  <span class="status pending"></span><div style="float: left; margin-top: 6px;">Pending...</div>
165
143
  <span class="status running"></span><div style="float: left; margin-top: 6px;">Running...</div>
166
- <span class="status success"></span><div style="float: left; margin-top: 6px;">Successful</div>
167
- <span class="status failure"></span><div style="float: left; margin-top: 6px;">Failed</div>
144
+ <span class="status successful"></span><div style="float: left; margin-top: 6px;">Successful</div>
145
+ <span class="status failed"></span><div style="float: left; margin-top: 6px;">Failed</div>
168
146
  <div style="clear: both;"></div>
169
147
  </div>
170
148
  <%= yield %>
@@ -42,6 +42,26 @@ module Octopusci
42
42
  erb :index
43
43
  end
44
44
 
45
+ get '/jobs/:job_id/output' do
46
+ protected!
47
+ @job = ::Job.find(params[:job_id])
48
+ content_type('text/plain')
49
+ return @job.output
50
+ end
51
+
52
+ get '/jobs/:job_id/status' do
53
+ protected!
54
+ @job = ::Job.find(params[:job_id])
55
+ content_type('text/plain')
56
+ return @job.status
57
+ end
58
+
59
+ get '/jobs/:job_id/ajax_summary' do
60
+ protected!
61
+ @job = ::Job.find(params[:job_id])
62
+ erb :job_summary, :layout => false, :locals => { :j => @job }
63
+ end
64
+
45
65
  post '/github-build' do
46
66
  if params['payload'].nil?
47
67
  raise "No payload paramater found, it is a required parameter."
@@ -54,7 +74,7 @@ module Octopusci
54
74
  return 404
55
75
  end
56
76
 
57
- if github_payload["ref"] =~ /refs\/heads\//
77
+ if (github_payload["ref"] =~ /refs\/heads\//) && (github_payload["deleted"] != true)
58
78
  branch_name = github_payload["ref"].gsub(/refs\/heads\//, '')
59
79
 
60
80
  # Queue the job appropriately
@@ -1,3 +1,3 @@
1
1
  module Octopusci
2
- Version = VERSION = '0.1.0'
2
+ Version = VERSION = '0.2.0'
3
3
  end
@@ -29,7 +29,7 @@ module Octopusci
29
29
 
30
30
  Octopusci::CONFIG['stages'].size.times do
31
31
  cur_pid = Process.fork do
32
- queues = ['commit']
32
+ queues = ['octopusci:commit']
33
33
  worker = Resque::Worker.new(*queues)
34
34
  worker.log "Starting worker #{worker}"
35
35
  worker.work(5)
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.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-09-26 00:00:00.000000000Z
13
+ date: 2011-09-28 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
17
- requirement: &70340169062820 !ruby/object:Gem::Requirement
17
+ requirement: &70291783224220 !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: *70340169062820
25
+ version_requirements: *70291783224220
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &70340169062200 !ruby/object:Gem::Requirement
28
+ requirement: &70291783210520 !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: *70340169062200
36
+ version_requirements: *70291783210520
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: resque
39
- requirement: &70340169061580 !ruby/object:Gem::Requirement
39
+ requirement: &70291783209560 !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: *70340169061580
47
+ version_requirements: *70291783209560
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: actionmailer
50
- requirement: &70340169060900 !ruby/object:Gem::Requirement
50
+ requirement: &70291783207940 !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: *70340169060900
58
+ version_requirements: *70291783207940
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: activerecord
61
- requirement: &70340169060180 !ruby/object:Gem::Requirement
61
+ requirement: &70291783206840 !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: *70340169060180
69
+ version_requirements: *70291783206840
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: mysql
72
- requirement: &70340169059700 !ruby/object:Gem::Requirement
72
+ requirement: &70291783205440 !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: *70340169059700
80
+ version_requirements: *70291783205440
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: multi_json
83
- requirement: &70340169058940 !ruby/object:Gem::Requirement
83
+ requirement: &70291783203200 !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: *70340169058940
91
+ version_requirements: *70291783203200
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: time-ago-in-words
94
- requirement: &70340169058300 !ruby/object:Gem::Requirement
94
+ requirement: &70291783181960 !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: *70340169058300
102
+ version_requirements: *70291783181960
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rake
105
- requirement: &70340169057260 !ruby/object:Gem::Requirement
105
+ requirement: &70291783179780 !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: *70340169057260
113
+ version_requirements: *70291783179780
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: rspec
116
- requirement: &70340169053960 !ruby/object:Gem::Requirement
116
+ requirement: &70291783145000 !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: *70340169053960
124
+ version_requirements: *70291783145000
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rack-test
127
- requirement: &70340169053040 !ruby/object:Gem::Requirement
127
+ requirement: &70291783142300 !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: *70340169053040
135
+ version_requirements: *70291783142300
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: guard
138
- requirement: &70340169052080 !ruby/object:Gem::Requirement
138
+ requirement: &70291783104620 !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: *70340169052080
146
+ version_requirements: *70291783104620
147
147
  - !ruby/object:Gem::Dependency
148
148
  name: rb-fsevent
149
- requirement: &70340169049420 !ruby/object:Gem::Requirement
149
+ requirement: &70291783079720 !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: *70340169049420
157
+ version_requirements: *70291783079720
158
158
  - !ruby/object:Gem::Dependency
159
159
  name: growl
160
- requirement: &70340169047220 !ruby/object:Gem::Requirement
160
+ requirement: &70291783069020 !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: *70340169047220
168
+ version_requirements: *70291783069020
169
169
  - !ruby/object:Gem::Dependency
170
170
  name: guard-rspec
171
- requirement: &70340169046240 !ruby/object:Gem::Requirement
171
+ requirement: &70291783049440 !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: *70340169046240
179
+ version_requirements: *70291783049440
180
180
  description: A multi-branch Continous Integration server that integrates with GitHub
181
181
  email:
182
182
  - cyphactor@gmail.com
@@ -200,12 +200,14 @@ files:
200
200
  - lib/octopusci/notifier.rb
201
201
  - lib/octopusci/queue.rb
202
202
  - lib/octopusci/schema.rb
203
+ - lib/octopusci/server/public/images/ajax-loader-1.gif
203
204
  - lib/octopusci/server/public/images/noise.gif
204
205
  - lib/octopusci/server/public/images/status.png
205
206
  - lib/octopusci/server/public/images/status2.png
206
207
  - lib/octopusci/server/public/javascripts/jquery-1.6.4.min.js
207
208
  - lib/octopusci/server/views/hello_world.erb
208
209
  - lib/octopusci/server/views/index.erb
210
+ - lib/octopusci/server/views/job_summary.erb
209
211
  - lib/octopusci/server/views/layout.erb
210
212
  - lib/octopusci/server.rb
211
213
  - lib/octopusci/stage_locker.rb
@@ -222,6 +224,7 @@ files:
222
224
  - spec/lib/octopusci_spec.rb
223
225
  - spec/spec_helper.rb
224
226
  - db/migrate/0001_init.rb
227
+ - db/migrate/0002_add_status_job.rb
225
228
  - extra/etc/init.d/octopusci
226
229
  homepage: https://github.com/cyphactor/octopusci
227
230
  licenses: []