Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: tech-angels/moci
base: 64bee419e7
...
head fork: tech-angels/moci
compare: bef9de4662
  • 5 commits
  • 40 files changed
  • 0 commit comments
  • 1 contributor
Commits on Feb 18, 2012
@comboy comboy bump to rails 3.0.11, locking test 7fd0c26
@comboy comboy make it ugly!
we can choose some different nice template, something clean
36ffd6e
Commits on Feb 19, 2012
@comboy comboy some ProjectInstance#execute tests & fix for very stupid bug
also make commits on project info page links
10e8f9b
@comboy comboy use open4 making execution cleaner ea217b9
@comboy comboy add annotator bef9de4
Showing with 408 additions and 1,061 deletions.
  1. +14 −2 Gemfile
  2. +62 −42 Gemfile.lock
  3. +2 −0  README.md
  4. +2 −2 app/controllers/commits_controller.rb
  5. +6 −0 app/models/author.rb
  6. +13 −0 app/models/commit.rb
  7. +7 −0 app/models/notification.rb
  8. +9 −0 app/models/project.rb
  9. +36 −11 app/models/project_instance.rb
  10. +9 −0 app/models/project_instance_commit.rb
  11. +8 −0 app/models/test_suite.rb
  12. +14 −0 app/models/test_suite_run.rb
  13. +7 −0 app/models/test_unit.rb
  14. +7 −0 app/models/test_unit_run.rb
  15. +1 −0  app/views/commits/_commit.html.haml
  16. +0 −26 app/views/common/_aside.html.haml
  17. +11 −0 app/views/common/_sidebar.html.haml
  18. +5 −11 app/views/common/_top_menu.html.haml
  19. +0 −87 app/views/layouts/application.html.erb
  20. +0 −14 app/views/layouts/application.html.erb.back
  21. +17 −0 app/views/layouts/application.html.haml
  22. +0 −505 app/views/layouts/application_layout.html.erb
  23. +10 −3 app/views/projects/show.html.haml
  24. +1 −0  config/routes.rb
  25. +1 −0  db/schema.rb
  26. +2 −2 lib/moci/project_handler/base.rb
  27. +4 −0 lib/moci/test_runner/base.rb
  28. +3 −4 lib/moci/test_runner/rails_units.rb
  29. +29 −33 lib/moci/test_runner/spec.rb
  30. +0 −14 public/stylesheets/1col.css
  31. +0 −19 public/stylesheets/2col.css
  32. +0 −35 public/stylesheets/main-ie6.css
  33. +0 −132 public/stylesheets/main.css
  34. +70 −0 public/stylesheets/mystyle.css
  35. +0 −31 public/stylesheets/reset.css
  36. +0 −86 public/stylesheets/style.css
  37. +5 −0 test/factories/project.rb
  38. +10 −0 test/factories/project_instance.rb
  39. +3 −0  test/test_helper.rb
  40. +40 −2 test/unit/project_instance_test.rb
View
16 Gemfile
@@ -1,9 +1,15 @@
source 'http://rubygems.org'
+gem 'rails', '3.0.11'
-gem 'wirble'
+# models annotations
+gem 'annotator'
-gem 'rails', '3.0.3'
+# live web notifications in rails
+gem 'juggernaut'
+
+# test runner
+gem 'open4'
# DB
@@ -24,3 +30,9 @@ gem 'git'
gem 'httparty'
+# Test suite
+
+group :development, :test do
+ gem 'factory_girl_rails'
+ gem 'ZenTest'
+end
View
104 Gemfile.lock
@@ -1,89 +1,109 @@
GEM
remote: http://rubygems.org/
specs:
+ ZenTest (4.6.2)
abstract (1.0.0)
- actionmailer (3.0.3)
- actionpack (= 3.0.3)
- mail (~> 2.2.9)
- actionpack (3.0.3)
- activemodel (= 3.0.3)
- activesupport (= 3.0.3)
+ actionmailer (3.0.11)
+ actionpack (= 3.0.11)
+ mail (~> 2.2.19)
+ actionpack (3.0.11)
+ activemodel (= 3.0.11)
+ activesupport (= 3.0.11)
builder (~> 2.1.2)
erubis (~> 2.6.6)
- i18n (~> 0.4)
+ i18n (~> 0.5.0)
rack (~> 1.2.1)
- rack-mount (~> 0.6.13)
- rack-test (~> 0.5.6)
+ rack-mount (~> 0.6.14)
+ rack-test (~> 0.5.7)
tzinfo (~> 0.3.23)
- activemodel (3.0.3)
- activesupport (= 3.0.3)
+ activemodel (3.0.11)
+ activesupport (= 3.0.11)
builder (~> 2.1.2)
- i18n (~> 0.4)
- activerecord (3.0.3)
- activemodel (= 3.0.3)
- activesupport (= 3.0.3)
- arel (~> 2.0.2)
+ i18n (~> 0.5.0)
+ activerecord (3.0.11)
+ activemodel (= 3.0.11)
+ activesupport (= 3.0.11)
+ arel (~> 2.0.10)
tzinfo (~> 0.3.23)
- activeresource (3.0.3)
- activemodel (= 3.0.3)
- activesupport (= 3.0.3)
- activesupport (3.0.3)
- arel (2.0.7)
+ activeresource (3.0.11)
+ activemodel (= 3.0.11)
+ activesupport (= 3.0.11)
+ activesupport (3.0.11)
+ annotator (0.0.2)
+ rails (~> 3.0)
+ arel (2.0.10)
builder (2.1.2)
crack (0.1.8)
erubis (2.6.6)
abstract (>= 1.0.0)
+ factory_girl (2.6.0)
+ activesupport (>= 2.3.9)
+ factory_girl_rails (1.7.0)
+ factory_girl (~> 2.6.0)
+ railties (>= 3.0.0)
git (1.2.5)
gravtastic (3.1.0)
haml (3.0.25)
httparty (0.7.7)
crack (= 0.1.8)
i18n (0.5.0)
- mail (2.2.14)
+ json (1.6.5)
+ juggernaut (2.1.1)
+ redis
+ mail (2.2.19)
activesupport (>= 2.3.6)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
- mime-types (1.16)
+ mime-types (1.17.2)
+ open4 (1.3.0)
pg (0.10.1)
- polyglot (0.3.1)
- rack (1.2.1)
- rack-mount (0.6.13)
+ polyglot (0.3.3)
+ rack (1.2.5)
+ rack-mount (0.6.14)
rack (>= 1.0.0)
rack-test (0.5.7)
rack (>= 1.0)
- rails (3.0.3)
- actionmailer (= 3.0.3)
- actionpack (= 3.0.3)
- activerecord (= 3.0.3)
- activeresource (= 3.0.3)
- activesupport (= 3.0.3)
+ rails (3.0.11)
+ actionmailer (= 3.0.11)
+ actionpack (= 3.0.11)
+ activerecord (= 3.0.11)
+ activeresource (= 3.0.11)
+ activesupport (= 3.0.11)
bundler (~> 1.0)
- railties (= 3.0.3)
- railties (3.0.3)
- actionpack (= 3.0.3)
- activesupport (= 3.0.3)
+ railties (= 3.0.11)
+ railties (3.0.11)
+ actionpack (= 3.0.11)
+ activesupport (= 3.0.11)
rake (>= 0.8.7)
+ rdoc (~> 3.4)
thor (~> 0.14.4)
- rake (0.8.7)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ redis (2.2.2)
sqlite3-ruby (1.3.2)
thor (0.14.6)
- treetop (1.4.9)
+ treetop (1.4.10)
+ polyglot
polyglot (>= 0.3.1)
- tzinfo (0.3.24)
+ tzinfo (0.3.31)
will_paginate (2.3.15)
- wirble (0.1.3)
PLATFORMS
ruby
DEPENDENCIES
+ ZenTest
+ annotator
+ factory_girl_rails
git
gravtastic
haml
httparty
+ juggernaut
+ open4
pg
- rails (= 3.0.3)
+ rails (= 3.0.11)
sqlite3-ruby
will_paginate
- wirble
View
2  README.md
@@ -18,6 +18,7 @@
Currently focused on making it work with rails tests and git as VCS.
Planned features that made me start this project (to keep in my mind while developing):
+
* ability to tell on which commit given error appeared for the first time (and associated
with this be able to tell if commit was OK even if some tests are still failing if they
were failing already before)
@@ -27,6 +28,7 @@
files changes and so on)
Assumptions:
+
* even though it's gonna be ruby & git only for now, make it modular so that either test
runner or VCS can be added without rewrites
View
4 app/controllers/commits_controller.rb
@@ -1,12 +1,12 @@
class CommitsController < ApplicationController
- within_project
-
def index
+ must_be_in_project
@commits = @project.commits.order('committed_at DESC').paginate(:page => params[:page], :per_page => 10)
end
def show
@commit = Commit.find params[:id]
+ @project = @commit.project
end
end
View
6 app/models/author.rb
@@ -1,3 +1,9 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * email [string]:w
+# * name [string]
+# * updated_at [datetime] - last update time
class Author < ActiveRecord::Base
has_many :commits
View
13 app/models/commit.rb
@@ -1,3 +1,16 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * author_id [integer] - belongs_to Author
+# * committed_at [datetime] - when commit was created in repo
+# * created_at [datetime] - creation time (in our database)
+# * description [text] - description provided inside commit
+# * dev_structure [text] - keeps database structure FIXME: reorganize, make it some data_yaml or whatever
+# * number [string] - commit number as in VCS (e.g. sha hash in git)
+# * parent_id [integer] - belongs_to parent Commit
+# * preparation_log [text] - FIXME: remove me, it's present in ProjectInstanceCommit
+# * project_id [integer] - belongs_to Project
+# * skipped [boolean] - commit can be marked as skipped if we don't want moci to run it
+# * updated_at [datetime] - last update time
class Commit < ActiveRecord::Base
#TODO? maybe: commiter? multiple parents?
#
View
7 app/models/notification.rb
@@ -1,3 +1,10 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * name [string]
+# * notification_options [text] - serialized options specific to given handler
+# * notification_type [string] - class name of the handler (Moci::Notificator::..)
+# * updated_at [datetime] - last update time
class Notification < ActiveRecord::Base
has_and_belongs_to_many :projects
View
9 app/models/project.rb
@@ -1,3 +1,10 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * name [string]
+# * project_type [string, default=Base] - same as class name that will be used as project handler (Moci::ProjectHandler::..)
+# * updated_at [datetime] - last update time
+# * vcs_branch_name [string]
class Project < ActiveRecord::Base
validates_presence_of :name
@@ -5,6 +12,8 @@ class Project < ActiveRecord::Base
has_many :test_suites
has_many :project_instances
+ has_many :test_suite_runs, :through => :project_instances
+
alias instances project_instances
has_and_belongs_to_many :notifications
View
47 app/models/project_instance.rb
@@ -1,7 +1,17 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * locked_by [string] - string handle of whoever locked the instance #TODO: add locked_at and timeouts
+# * project_id [integer] - belongs_to Project
+# * state [string, default=new] - TODO: document me
+# * updated_at [datetime] - last update time
+# * working_directory [string] - directory of the project we run tests on
class ProjectInstance < ActiveRecord::Base
belongs_to :project
has_many :project_instance_commits
+ has_many :test_suite_runs
+
alias commits project_instance_commits
scope :free, :conditions => {:locked_by => nil}
@@ -13,22 +23,31 @@ def checkout(commit)
end
# Execute shell command within project instance directory
- # Output parameter can be used to pass a string where output will be appended.
+ #
+ # output parameter can be used to pass a string where output will be appended.
+ # if block is passed, output is not collected and block will receive 4 params same as for popen4:
+ # pid, stdin, stdout, stderr
# Returns true if exit code was 0
def execute(command, output='')
# redirection to file to avoid using ruby tricks to get both return status
# and output. If there's any better way please fix.
- temp_file = Tempfile.new('execute.log')
- command = "cd #{working_directory} && #{command} &> #{temp_file.path}"
+ command = "cd #{working_directory} && #{command}"
exit_status = nil
project_handler.execute_wrapper(command, output) do |command, output|
info " executing #{command}"
- exit_status = system(command)
+ output << "$ #{command}\n\n" # I don't like it, but it here, but it's very useful information to know why it failed
+ status = Open4.popen4(command) do |pid, stdin, stdout, stderr|
+ if block_given?
+ yield(pid, stdin, stdout, stderr)
+ else
+ # IMPROVE: separate them?
+ output << stdout.read
+ output << stderr.read
+ end
+ end
+ exit_status = status.exitstatus
end
- output << "$ #{command}\n\n"
- output << File.read(temp_file.path)
- temp_file.unlink
- exit_status
+ return exit_status == 0
end
def execute!(command, output='')
@@ -113,10 +132,16 @@ def try_to_acquire(handle)
info "trying to acquire by #{handle}"
# Since it's done within single query, database guarantees that lock won't
# be given twice
- success = self.class.update_all(
+ update_count = self.class.update_all(
{:locked_by => handle},
- {:locked_by => nil, :id => self.id}) == 1
- info "ACQUIRED by #{handle}" if success
+ {:locked_by => nil, :id => self.id})
+ success = (update_count == 1)
+
+ if success
+ self.reload # update locked_by field
+ info "ACQUIRED by #{handle}"
+ end
+
return success
end
View
9 app/models/project_instance_commit.rb
@@ -1,3 +1,12 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * commit_id [integer] - belongs_to Commit
+# * created_at [datetime] - creation time
+# * data_yaml [text] - serialized data associated with commit
+# * preparation_log [text] - commaound output of first time commit preparation (use data maybe?)
+# * project_instance_id [integer] - belongs_to ProjectInstance
+# * state [string, default=new] - current state, 'new' -> ( 'prepared' | 'preparation_failed' )
+# * updated_at [datetime] - last update time
class ProjectInstanceCommit < ActiveRecord::Base
belongs_to :commit
View
8 app/models/test_suite.rb
@@ -1,3 +1,11 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * name [string]
+# * project_id [integer] - belongs_to Project
+# * suite_options [text] - test suite specific options to be passed to test runner (e.g' which files to include/exclude)
+# * suite_type [string] - test suite type, name same as test runner class name (inside Moci::TestRunner)
+# * updated_at [datetime] - last update time
require 'moci/test_runner/spec' #FIXME this should not be necessary here
class TestSuite < ActiveRecord::Base
View
14 app/models/test_suite_run.rb
@@ -1,3 +1,17 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * assertions_count [integer] - number of assertions made
+# * commit_id [integer] - belongs_to Commit (TODO: shouldn't that be project_instance_commit?)
+# * created_at [datetime] - creation time
+# * errors_count [integer] - number of errors that occurred during test suite run
+# * failures_count [integer] - number of failures that occured during test suite run
+# * project_instance_id [integer] - belongs_to ProjectInstance
+# * run_log [text] - command output of test suite run
+# * run_time [float] - total test suite execution time
+# * state [string] - currently only 2 states: running -> finished
+# * test_suite_id [integer] - belongs_to TestSuite
+# * tests_count [integer] - number of tests in the test suite
+# * updated_at [datetime] - last update time
class TestSuiteRun < ActiveRecord::Base
belongs_to :commit
belongs_to :project_instance
View
7 app/models/test_unit.rb
@@ -1,3 +1,10 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * class_name [string] - name of group of tests
+# * created_at [datetime] - creation time
+# * name [text]
+# * test_suite_id [integer] - belongs_to TestSuite
+# * updated_at [datetime] - last update time
class TestUnit < ActiveRecord::Base
belongs_to :test_suite
end
View
7 app/models/test_unit_run.rb
@@ -1,3 +1,10 @@
+# Attributes:
+# * id [integer, primary, not null] - primary key
+# * created_at [datetime] - creation time
+# * result [string] - '.' - OK, 'E' - error, 'F' - failure, 'U' - undefined
+# * run_time [float] - time taken to run this test
+# * test_suite_run_id [integer] - belongs_to TestSuiteRun
+# * test_unit_id [integer] - belongs_to TestUnit
class TestUnitRun < ActiveRecord::Base
belongs_to :test_unit
belongs_to :test_suite_run
View
1  app/views/commits/_commit.html.haml
@@ -65,6 +65,7 @@
(
= link_to_function 'details', "$('#run_details_#{commit.id}_#{ts.id}').show();"
)
+ %br
%div{:id => "run_details_#{commit.id}_#{ts.id}", :style => "display: none;"}
%br
View
26 app/views/common/_aside.html.haml
@@ -1,26 +0,0 @@
-.padding.box
- %p#btn-create.box
- = link_to '#' do
- %span Add new something
-
-%ul.box
- - if @project
- = menu_li "Projent info", :controller => '/projects', :action => 'show'
- = menu_li "Latest commits", :controller => '/commits', :action => 'index', :project_name => @project.name
- -#%ul
- -#%li
- -#= link_to 'lorem', '#'
- -#%li
- -#= link_to 'lorem', '#'
-
- = menu_li "Latest test runs", :controller => '/test_suite_runs', :action => 'index'
-
-
--#.padding.box
- -#%h2 Workers
-
--#%ul.box
- -#%li
- -#= link_to 'lorem', '#'
- -#%li
- -#= link_to 'lorem', '#'
View
11 app/views/common/_sidebar.html.haml
@@ -0,0 +1,11 @@
+%ul
+ = menu_li "Latest test runs", :controller => '/test_suite_runs', :action => 'index'
+
+- if @project
+ .section= @project.name
+ %ul
+ = menu_li "Project info", :controller => '/projects', :action => 'show'
+ = menu_li "Latest commits", :controller => '/commits', :action => 'index', :project_name => @project.name
+
+
+
View
16 app/views/common/_top_menu.html.haml
@@ -1,16 +1,10 @@
-#menu.box
- %ul.box.f-right
- %li
- = link_to '#' do
- %span
- %strong
- Visit Site &raquo;
- %ul.box
+#menu
+ Projects:
+ %ul
- Project.order('name').all.each do |project|
- if project == @project
- %li#menu-active
- = link_to :action => :show, :controller => '/projects', :project_name => project.name do
- %span= @project.name
+ %li.active
+ %span= @project.name
- else
%li
= link_to :action => :show, :controller => '/projects', :project_name => project.name do
View
87 app/views/layouts/application.html.erb
@@ -1,87 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="content-language" content="en" />
- <meta name="robots" content="noindex,nofollow" />
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/reset.css" /> <!-- RESET -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/main.css" /> <!-- MAIN STYLE SHEET -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/2col.css" title="2col" /> <!-- DEFAULT: 2 COLUMNS -->
- <link rel="alternate stylesheet" media="screen,projection" type="text/css" href="/stylesheets/1col.css" title="1col" /> <!-- ALTERNATE: 1 COLUMN -->
- <!--[if lte IE 6]><link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/main-ie6.css" /><![endif]--> <!-- MSIE6 -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/style.css" /> <!-- GRAPHIC THEME -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/mystyle.css" /> <!-- WRITE YOUR CSS CODE HERE -->
- <%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" %>
- <%= javascript_include_tag "jquery.simplemodal" %>
- <title>moci</title>
-</head>
-
-<body>
-
-<div id="main">
-
- <!-- Tray -->
- <div id="tray" class="box">
-
- <p class="f-left box">
-
- <!-- Switcher -->
- <!--
- <span class="f-left" id="switcher">
- <a href="#" rel="1col" class="styleswitch ico-col1" title="Display one column"><img src="design/switcher-1col.gif" alt="1 Column" /></a>
- <a href="#" rel="2col" class="styleswitch ico-col2" title="Display two columns"><img src="design/switcher-2col.gif" alt="2 Columns" /></a>
- </span>-->
-
- <strong>moci</strong>
-
- </p>
-
- <p class="f-right">User: <strong><a href="#">Administrator</a></strong> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong><a href="#" id="logout">Log out</a></strong></p>
-
- </div> <!-- /tray -->
-
- <hr class="noscreen" />
-
-
- <!-- Menu -->
-
- <%= render :partial => '/common/top_menu.html.haml' %>
- <!-- /header -->
-
- <hr class="noscreen" />
-
- <!-- Columns -->
- <div id="cols" class="box">
-
- <!-- Aside (Left Column) -->
- <div id="aside" class="box">
-
- <%= render :partial => '/common/aside' %>
-
- </div> <!-- /aside -->
-
- <hr class="noscreen" />
-
- <!-- Content (Right Column) -->
- <div id="content" class="box">
- <%= yield %>
- </div> <!-- /content -->
-
- </div> <!-- /cols -->
-
- <hr class="noscreen" />
-
- <!-- Footer -->
- <div id="footer" class="box">
-
- <p class="f-left">&copy; 2009 <a href="#">Your Company</a>, All Rights Reserved &reg;</p>
-
- <p class="f-right">Templates by <a href="http://www.adminizio.com/">Adminizio</a></p>
-
- </div> <!-- /footer -->
-
-</div> <!-- /main -->
-
-</body>
-</html>
View
14 app/views/layouts/application.html.erb.back
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>StupidCi</title>
- <%= stylesheet_link_tag :all %>
- <%= javascript_include_tag :defaults %>
- <%= csrf_meta_tag %>
-</head>
-<body>
-
-<%= yield %>
-
-</body>
-</html>
View
17 app/views/layouts/application.html.haml
@@ -0,0 +1,17 @@
+!!!
+%head
+ = stylesheet_link_tag 'mystyle'
+ = javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"
+ = javascript_include_tag "jquery.simplemodal"
+%body
+
+ #header
+ .title moci
+ = render :partial => '/common/top_menu.html.haml'
+
+ #cols
+ #sidebar
+ = render :partial => '/common/sidebar'
+
+ #content
+ = yield
View
505 app/views/layouts/application_layout.html.erb
@@ -1,505 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="content-language" content="en" />
- <meta name="robots" content="noindex,nofollow" />
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/reset.css" /> <!-- RESET -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/main.css" /> <!-- MAIN STYLE SHEET -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/2col.css" title="2col" /> <!-- DEFAULT: 2 COLUMNS -->
- <link rel="alternate stylesheet" media="screen,projection" type="text/css" href="/stylesheets/1col.css" title="1col" /> <!-- ALTERNATE: 1 COLUMN -->
- <!--[if lte IE 6]><link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/main-ie6.css" /><![endif]--> <!-- MSIE6 -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/style.css" /> <!-- GRAPHIC THEME -->
- <link rel="stylesheet" media="screen,projection" type="text/css" href="/stylesheets/mystyle.css" /> <!-- WRITE YOUR CSS CODE HERE -->
- <script type="text/javascript" src="js/jquery.js"></script>
- <script type="text/javascript" src="js/switcher.js"></script>
- <script type="text/javascript" src="js/toggle.js"></script>
- <script type="text/javascript" src="js/ui.core.js"></script>
- <script type="text/javascript" src="js/ui.tabs.js"></script>
- <script type="text/javascript">
- $(document).ready(function(){
- $(".tabs > ul").tabs();
- });
- </script>
- <title>Adminizio Lite</title>
-</head>
-
-<body>
-
-<div id="main">
-
- <!-- Tray -->
- <div id="tray" class="box">
-
- <p class="f-left box">
-
- <!-- Switcher -->
- <span class="f-left" id="switcher">
- <a href="#" rel="1col" class="styleswitch ico-col1" title="Display one column"><img src="design/switcher-1col.gif" alt="1 Column" /></a>
- <a href="#" rel="2col" class="styleswitch ico-col2" title="Display two columns"><img src="design/switcher-2col.gif" alt="2 Columns" /></a>
- </span>
-
- Project: <strong>Your Project</strong>
-
- </p>
-
- <p class="f-right">User: <strong><a href="#">Administrator</a></strong> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong><a href="#" id="logout">Log out</a></strong></p>
-
- </div> <!-- /tray -->
-
- <hr class="noscreen" />
-
- <!-- Menu -->
- <div id="menu" class="box">
-
- <ul class="box f-right">
- <li><a href="#"><span><strong>Visit Site &raquo;</strong></span></a></li>
- </ul>
-
- <ul class="box">
- <li id="menu-active"><a href="#"><span>Lorem ipsum</span></a></li> <!-- Active -->
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- <li><a href="#"><span>Lorem ipsum</span></a></li>
- </ul>
-
- </div> <!-- /header -->
-
- <hr class="noscreen" />
-
- <!-- Columns -->
- <div id="cols" class="box">
-
- <!-- Aside (Left Column) -->
- <div id="aside" class="box">
-
- <div class="padding box">
-
- <!-- Logo (Max. width = 200px) -->
- <p id="logo"><a href="#"><img src="tmp/logo.gif" alt="Our logo" title="Visit Site" /></a></p>
-
- <!-- Search -->
- <form action="#" method="get" id="search">
- <fieldset>
- <legend>Search</legend>
-
- <p><input type="text" size="17" name="" class="input-text" />&nbsp;<input type="submit" value="OK" class="input-submit-02" /><br />
- <a href="javascript:toggle('search-options');" class="ico-drop">Advanced search</a></p>
-
- <!-- Advanced search -->
- <div id="search-options" style="display:none;">
-
- <p>
- <label><input type="checkbox" name="" checked="checked" /> Option I.</label><br />
- <label><input type="checkbox" name="" /> Option II.</label><br />
- <label><input type="checkbox" name="" /> Option III.</label>
- </p>
-
- </div> <!-- /search-options -->
-
- </fieldset>
- </form>
-
- <!-- Create a new project -->
- <p id="btn-create" class="box"><a href="#"><span>Create a new project</span></a></p>
-
- </div> <!-- /padding -->
-
- <ul class="box">
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li id="submenu-active"><a href="#">Active Page</a> <!-- Active -->
- <ul>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- </ul>
- </li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a>
- <ul>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- <li><a href="#">Lorem ipsum</a></li>
- </ul>
- </li>
- <li><a href="#">Lorem ipsum</a></li>
- </ul>
-
- </div> <!-- /aside -->
-
- <hr class="noscreen" />
-
- <!-- Content (Right Column) -->
- <div id="content" class="box">
-
- <h1>Styles</h1>
-
- <!-- Headings -->
- <h2>Heading H2</h2>
- <h3>Heading H3</h3>
- <h4>Heading H4</h4>
- <h5>Heading H5</h5>
-
- <!-- System Messages -->
- <h3 class="tit">System Messages</h3>
-
- <p class="msg warning">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
-
- <p class="msg info">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
-
- <p class="msg done">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
-
- <p class="msg error">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
-
- <!-- Tabs -->
- <h3 class="tit">Tabs</h3>
-
- <div class="tabs box">
- <ul>
- <li><a href="#tab01"><span>Lorem ipsum</span></a></li>
- <li><a href="#tab02"><span>Lorem ipsum</span></a></li>
- <li><a href="#tab03"><span>Lorem ipsum</span></a></li>
- </ul>
- </div> <!-- /tabs -->
-
- <!-- Tab01 -->
- <div id="tab01">
-
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
-
- </div> <!-- /tab01 -->
-
- <!-- Tab02 -->
- <div id="tab02">
-
- <p>Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa.</p>
-
- </div> <!-- /tab02 -->
-
- <!-- Tab03 -->
- <div id="tab03">
-
- <p>Nam ut lorem eu orci placerat iaculis.</p>
-
- </div> <!-- /tab03 -->
-
- <!-- 2 columns -->
- <h3 class="tit">2 Columns (50-50)</h3>
-
- <div class="col50">
-
- <p class="t-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et risus. Maecenas non nunc. Proin eleifend viverra sapien. Donec id augue. Duis erat nunc, volutpat a, bibendum quis, placerat vitae, enim. Etiam consectetur, velit in viverra tempus, urna augue sollicitudin tellus, vitae interdum arcu mi at est. Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa. Cras suscipit, neque ac auctor interdum, pede nibh porta lectus, nec aliquet nulla ipsum ac nibh. Morbi feugiat ipsum id metus. In urna sapien, porttitor sed, consectetur quis, lacinia eu, ante. Donec at ipsum. Sed arcu tellus, dapibus sit amet, auctor nec, rutrum non, lacus. Nam ut lorem eu orci placerat iaculis. Proin bibendum. Suspendisse consequat.</p>
-
- </div> <!-- /col50 -->
-
- <div class="col50 f-right">
-
- <p class="t-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et risus. Maecenas non nunc. Proin eleifend viverra sapien. Donec id augue. Duis erat nunc, volutpat a, bibendum quis, placerat vitae, enim. Etiam consectetur, velit in viverra tempus, urna augue sollicitudin tellus, vitae interdum arcu mi at est. Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa. Cras suscipit, neque ac auctor interdum, pede nibh porta lectus, nec aliquet nulla ipsum ac nibh. Morbi feugiat ipsum id metus. In urna sapien, porttitor sed, consectetur quis, lacinia eu, ante. Donec at ipsum. Sed arcu tellus, dapibus sit amet, auctor nec, rutrum non, lacus. Nam ut lorem eu orci placerat iaculis. Proin bibendum. Suspendisse consequat.</p>
-
- </div> <!-- /col50 -->
-
- <div class="fix"></div>
-
- <!-- 3 columns -->
- <h3 class="tit">3 Columns (33-33-33)</h3>
-
- <div class="col33">
-
- <p class="t-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et risus. Maecenas non nunc. Proin eleifend viverra sapien. Donec id augue. Duis erat nunc, volutpat a, bibendum quis, placerat vitae, enim. Etiam consectetur, velit in viverra tempus, urna augue sollicitudin tellus, vitae interdum arcu mi at est. Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa. Cras suscipit, neque ac auctor interdum, pede nibh porta lectus, nec aliquet nulla ipsum ac nibh. Morbi feugiat ipsum id metus. In urna sapien, porttitor sed, consectetur quis, lacinia eu, ante. Donec at ipsum. Sed arcu tellus, dapibus sit amet, auctor nec, rutrum non, lacus. Nam ut lorem eu orci placerat iaculis. Proin bibendum. Suspendisse consequat.</p>
-
- </div> <!-- /col33 -->
-
- <div class="col33 center">
-
- <p class="t-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et risus. Maecenas non nunc. Proin eleifend viverra sapien. Donec id augue. Duis erat nunc, volutpat a, bibendum quis, placerat vitae, enim. Etiam consectetur, velit in viverra tempus, urna augue sollicitudin tellus, vitae interdum arcu mi at est. Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa. Cras suscipit, neque ac auctor interdum, pede nibh porta lectus, nec aliquet nulla ipsum ac nibh. Morbi feugiat ipsum id metus. In urna sapien, porttitor sed, consectetur quis, lacinia eu, ante. Donec at ipsum. Sed arcu tellus, dapibus sit amet, auctor nec, rutrum non, lacus. Nam ut lorem eu orci placerat iaculis. Proin bibendum. Suspendisse consequat.</p>
-
- </div> <!-- /col33 -->
-
- <div class="col33">
-
- <p class="t-justify">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus et risus. Maecenas non nunc. Proin eleifend viverra sapien. Donec id augue. Duis erat nunc, volutpat a, bibendum quis, placerat vitae, enim. Etiam consectetur, velit in viverra tempus, urna augue sollicitudin tellus, vitae interdum arcu mi at est. Donec ornare, libero vitae facilisis molestie, mi sapien venenatis felis, sed mattis lectus nisi ac massa. Cras suscipit, neque ac auctor interdum, pede nibh porta lectus, nec aliquet nulla ipsum ac nibh. Morbi feugiat ipsum id metus. In urna sapien, porttitor sed, consectetur quis, lacinia eu, ante. Donec at ipsum. Sed arcu tellus, dapibus sit amet, auctor nec, rutrum non, lacus. Nam ut lorem eu orci placerat iaculis. Proin bibendum. Suspendisse consequat.</p>
-
- </div> <!-- /col33 -->
-
- <div class="fix"></div>
-
- <!-- Text Alignment -->
- <h3 class="tit">Text Alignment</h3>
- <p class="t-left">Left <span class="tag">(.t-left)</span></p>
- <p class="t-center">Center <span class="tag">(.t-center)</span></p>
- <p class="t-right">Right <span class="tag">(.t-right)</span></p>
-
- <!-- Size and Highlight -->
- <h3 class="tit">Text Size and Highlight</h3>
- <p>Lorem ipsum dolor sit amet</p>
- <p><strong>Lorem ipsum dolor sit amet</strong> <span class="tag">(&lt;strong&gt;)</span></p>
- <p><em>Lorem ipsum dolor sit amet</em> <span class="tag">(&lt;em&gt;)</span></p>
- <p><abbr>Lorem ipsum dolor sit amet</abbr> <span class="tag">(&lt;abbr&gt;)</span></p>
- <p><acronym>Lorem ipsum dolor sit amet</acronym> <span class="tag">(&lt;acronym&gt;)</span></p>
- <p><code>Lorem ipsum dolor sit amet</code> <span class="tag">(&lt;code&gt;)</span></p>
- <p><span class="help">Lorem ipsum dolor sit amet</span> <span class="tag">(.help)</span></p>
- <p><span class="high">Lorem ipsum dolor sit amet</span> <span class="tag">(.high)</span></p>
- <p><span class="low">Lorem ipsum dolor sit amet</span> <span class="tag">(.low)</span></p>
- <p><span class="bigger">Lorem ipsum dolor sit amet</span> <span class="tag">(.bigger)</span></p>
- <p><span class="smaller">Lorem ipsum dolor sit amet</span> <span class="tag">(.smaller)</span></p>
-
- <!-- Unordered List -->
- <h3 class="tit">Unordered List - <span class="tag">(ul.nostyle)</span></h3>
- <ul class="nostyle">
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ul>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ul>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
-
- <!-- Unordered List -->
- <h3 class="tit">Unordered List</h3>
- <ul>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ul>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ul>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ul>
-
- <!-- Ordered List (OL) -->
- <h3 class="tit">Ordered List</h3>
- <ol>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ol>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet
- <ol>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ol>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ol>
- </li>
- <li>Lorem ipsum dolor sit amet</li>
- <li>Lorem ipsum dolor sit amet</li>
- </ol>
-
- <!-- Table -->
- <h3 class="tit">Table <span class="tag">(table.nostyle)</span></h3>
- <table class="nostyle">
- <tr>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- </table>
-
- <!-- Table (TABLE) -->
- <h3 class="tit">Table</h3>
- <table>
- <tr>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- <th>Lorem ipsum</th>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr class="bg">
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr class="bg">
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- <tr>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- <td>Lorem ipsum</td>
- </tr>
- </table>
-
- <!-- Form -->
- <h3 class="tit">Form</h3>
- <fieldset>
- <legend>Legend</legend>
- <table class="nostyle">
- <tr>
- <td style="width:70px;">Input:</td>
- <td><input type="text" size="40" name="" class="input-text" /></td>
- </tr>
- <tr>
- <td>Input:</td>
- <td><input type="text" size="40" name="" class="input-text" disabled="disabled" /></td>
- </tr>
- <tr>
- <td class="va-top">Input:</td>
- <td><textarea cols="75" rows="7" class="input-text"></textarea></td>
- </tr>
- <tr>
- <td>Input:</td>
- <td>
- <label><input type="checkbox" /> Lorem ipsum</label> &nbsp;
- <label><input type="checkbox" /> Lorem ipsum</label> &nbsp;
- <label><input type="checkbox" /> Lorem ipsum</label>
- </td>
- </tr>
- <tr>
- <td>Input:</td>
- <td>
- <label><input type="radio" /> Lorem ipsum</label> &nbsp;
- <label><input type="radio" /> Lorem ipsum</label> &nbsp;
- <label><input type="radio" /> Lorem ipsum</label>
- </td>
- </tr>
- <tr>
- <td colspan="2" class="t-right"><input type="submit" class="input-submit" value="Submit" /></td>
- </tr>
- </table>
- </fieldset>
-
- <!-- Definition List -->
- <h3 class="tit">Definition List <span class="tag">(dl.nostyle)</span></h3>
- <dl class="nostyle">
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- </dl>
-
- <!-- Definition List -->
- <h3 class="tit">Definition List</h3>
- <dl>
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- <dt>Lorem ipsum</dt>
- <dd>Lorem ipsum dolor sit amet.</dd>
- </dl>
-
- </div> <!-- /content -->
-
- </div> <!-- /cols -->
-
- <hr class="noscreen" />
-
- <!-- Footer -->
- <div id="footer" class="box">
-
- <p class="f-left">&copy; 2009 <a href="#">Your Company</a>, All Rights Reserved &reg;</p>
-
- <p class="f-right">Templates by <a href="http://www.adminizio.com/">Adminizio</a></p>
-
- </div> <!-- /footer -->
-
-</div> <!-- /main -->
-
-</body>
-</html>
View
13 app/views/projects/show.html.haml
@@ -13,14 +13,14 @@
&nbsp;
%br
- if !last_commits.empty?
- %table{:style => 'width: 100%'}
+ %table.grid{:style => 'width: 100%'}
- last_commits[0..5].each_with_index do |commit, i|
-# commit = @project.commits.order('committed_at DESC').first
%tr{:class => "build_state #{commit.build_state}"}
%td{:style => 'width: 20px;'}
= image_tag commit.author.gravatar_url :size => 15
%td
- = commit.short_description
+ = link_to commit.short_description, commit_path(commit)
%td
= commit.build_state
- if i == 0
@@ -39,7 +39,7 @@
.about
%h3 About project
- %table{:class => 'keyvalue nostyle', :style => 'width: 100%; float: right;'}
+ %table{:class => 'keyvalue nostyle', :style => 'width: 100%;'}
%tr
%td.key Monitored since
%td.value= @project.created_at
@@ -48,3 +48,10 @@
%td.value= @project.commits.count
+ %h3 Currently runnning
+
+ %table
+ - @project.test_suite_runs.order('updated_at DESC').limit(5).all.each do |tr|
+ %tr
+ %td= tr.updated_at
+ %td= tr.state
View
1  config/routes.rb
@@ -45,6 +45,7 @@
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
+ resources :commits
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
View
1  db/schema.rb
@@ -1,3 +1,4 @@
+# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
View
4 lib/moci/project_handler/base.rb
@@ -31,11 +31,11 @@ def working_directory
end
def execute(command, output='')
- @project_instance.execute(command, output='')
+ @project_instance.execute(command, output)
end
def execute!(command, output='')
- @project_instance.execute!(command, output='')
+ @project_instance.execute!(command, output)
end
end
View
4 lib/moci/test_runner/base.rb
@@ -23,6 +23,10 @@ def options
@tr.test_suite.options
end
+ def execute(command, output='', &block)
+ @tr.project_instance.execute(command, output, &block)
+ end
+
# Used by implementations to push info about test results
# Two params with key and value can be given, or one param with a hash.
def push(name, value = nil)
View
7 lib/moci/test_runner/rails_units.rb
@@ -3,16 +3,16 @@ module TestRunner
class RailsUnits < Base
# TODO: maybe try some implementing some test runner to avoid parsing
- # Parsing is safer however in case some other gems modified tests already somehow though.
+ # However parsing is safer in case when some other gems modified tests runner internals (which happens)
# TODO: error messages parsing
def run
t0 = lt = Time.now
output = ""
- Bundler.with_clean_env do
- IO.popen("cd #{working_directory}; BUNDLE_GEMFILE=\"Gemfile\" TESTOPTS=\"-v\" rake test:#{test_type} 2>&1", 'r+') do |pipe|
+ execute("TESTOPTS=\"-v\" rake test:#{test_type}") do |pid, stdin, stdout, stderr|
running = false
+ pipe = stdout
pipe.sync = true ### you can do this once
buf = ''
@@ -64,7 +64,6 @@ def run
end
end
end
- end #bundle clean env
push(
:run_time => Time.now - t0,
:output => output,
View
62 lib/moci/test_runner/spec.rb
@@ -10,43 +10,39 @@ def run
output = ""
specs = options['specs']
formatter_path = File.expand_path File.join(File.dirname(__FILE__),'rspec','moci_formatter.rb')
- cmd = "[[ -s \"$HOME/.rvm/scripts/rvm\" ]] && . \"$HOME/.rvm/scripts/rvm\" && cd #{working_directory}; BUNDLE_GEMFILE=\"Gemfile\" rspec --require #{formatter_path} #{specs} 2>&1" #FIXME spec/models hardcoded, Gemfile
- puts "!!!#{cmd}"
- Bundler.with_clean_env do
- IO.popen(cmd, 'r+') do |pipe|
- pipe.sync = true
- dt0 = Time.now
+ execute("rspec --require #{formatter_path} #{specs}") do |pid, stdin, stdout, stderr|
+ pipe = stdout
+ pipe.sync = true
+ dt0 = Time.now
- while line = pipe.gets
- output += line
- line = line.strip
- #puts "LINE: #{line}"
- if line == "START"
- dt0 = Time.now
- else
- if line.match(/^.--EX\[/)
- result, stuff = line.split('--',2)
- class_name = stuff.match(/EX\[\[(.*?)\]\]/)[1]
- name = stuff.split(']]',2).last
- push_test name, class_name
- last_test result, (Time.now - dt0)
- end
- if line.match(/^STATS:/)
- stats = line.split("STATS:",2)[1].split(',').map(&:to_f)
- push(
- :tests_count => stats[1],
- :assertions_count => stats[1],
- :errors_count => stats[2]
- )
- end
+ while line = pipe.gets
+ output += line
+ line = line.strip
+ if line == "START"
+ dt0 = Time.now
+ else
+ if line.match(/^.--EX\[/)
+ result, stuff = line.split('--',2)
+ class_name = stuff.match(/EX\[\[(.*?)\]\]/)[1]
+ name = stuff.split(']]',2).last
+ push_test name, class_name
+ last_test result, (Time.now - dt0)
+ end
+ if line.match(/^STATS:/)
+ stats = line.split("STATS:",2)[1].split(',').map(&:to_f)
+ push(
+ :tests_count => stats[1],
+ :assertions_count => stats[1],
+ :errors_count => stats[2]
+ )
end
end
- push(
- :run_time => Time.now - t0,
- :output => output,
- :finished => true
- )
end
+ push(
+ :run_time => Time.now - t0,
+ :output => output,
+ :finished => true
+ )
end
end
View
14 public/stylesheets/1col.css
@@ -1,14 +0,0 @@
-/* =============================================================================
-
- 1COL.CSS
- version: 1.7
- updated: 2009-03-14, 12:44 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-LAYOUT
-============================================================================= */
-
-#cols {margin:15px; background:none;}
-#aside, #tray .ico-col1 {display:none;}
View
19 public/stylesheets/2col.css
@@ -1,19 +0,0 @@
-/* =============================================================================
-
- 2COL.CSS
- version: 1.7
- updated: 2009-03-14, 12:44 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-LAYOUT
-============================================================================= */
-
-#cols {position:relative; margin:15px 0; padding-right:15px; background:url("../design/content.gif") 230px 0 repeat-y;}
-#aside {float:left; width:215px; margin-right:0;}
-#content {margin-left:232px; overflow:visible;}
-#tray .ico-col2 {display:none;}
-
-html>body #aside {margin-right:20px;}
-html>body #content {margin-left:0; overflow:hidden;}
View
35 public/stylesheets/main-ie6.css
@@ -1,35 +0,0 @@
-/* =============================================================================
-
- MAIN-IE6.CSS
- version: 1.7
- updated: 2009-03-14, 12:44 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-RESET
-============================================================================= */
-
-.box {height:1%;}
-
-/* =============================================================================
-HTML
-============================================================================= */
-
-table {font-size:100%;}
-table th, table td {padding:6px 6px !important;}
-code {font-size:105%;}
-
-/* =============================================================================
-OTHERS
-============================================================================= */
-
-#aside ul li#submenu-active a {width:228px;}
-#aside ul li a, #aside ul ul li a, #aside ul li#submenu-active ul li a {width:215px;}
-#aside #btn-create a span {width:175px; background-position:0 0;}
-#aside #search fieldset .input-text {width:145px;}
-#content .col33.center {width:36%;}
-#content .tabs a {cursor:hand;}
-#content .tabs {height:30px;}
-.input-text-02 {height:39px;}
-.input-submit-02 {padding:0;}
View
132 public/stylesheets/main.css
@@ -1,132 +0,0 @@
-/* =============================================================================
-
- MAIN.CSS
- version: 1.7
- updated: 2009-03-14, 12:44 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-HTML - styles
-============================================================================= */
-
-body {font:0.8em/1.5 "arial", sans-serif;}
-h1, h2, h3, h4, h5, h6, address, blockquote, dl, fieldset, ol, p, table, ul {margin:15px 0;}
-#content h1 {font-size:180%;}
-#content h2 {font-size:160%;}
-#content h3 {font-size:140%;}
-#content h4 {font-size:120%;}
-#content h5, h6 {font-size:100%;}
-#content table {margin:0; border-collapse:collapse;}
-#content table.width100 {width:100%;}
-#content table th, #content table td {padding:5px 5px;}
-#content table th {text-align:left; vertical-align:middle; font-weight:bold;}
-#content ul {margin:15px 0; list-style:none;}
-#content ul li {padding-left:15px; background:url("../design/ul.gif") 0 4px no-repeat;}
-#content ul li.green {background:url("../design/ul_green.gif") 0 4px no-repeat;}
-#content ul li.warn {background:url("../design/ul_warn.png") 0 4px no-repeat;}
-#content ul ul {margin:0 0 0 10px;}
-#content ul ul li {padding-left:15px; background:url("../design/ul-ul.gif") 0 4px no-repeat;}
-#content ol {margin:15px 0 15px 30px; list-style-type:decimal;}
-#content ol ol {margin:0 0 0 20px;}
-#content ol ol li {list-style-type:lower-alpha;}
-#content dl {clear:both;}
-#content dl dt {font-weight:bold;}
-#content dl dd {margin:0 0 5px 0;}
-#content fieldset {position:relative; margin:10px 0; padding:10px;}
-#content legend {font-size:120%; font-weight:bold;}
-#content code {font-family:"",monospace;}
-#content .help {cursor:help;}
-
-/* =============================================================================
-HTML - without styles
-============================================================================= */
-
-table.nostyle, table.nostyle th, table.nostyle td {border:0 !important;}
-table.nostyle th {background:none !important; text-align:left !important;}
-table.nostyle th, table.nostyle td {padding:3px 5px !important;}
-ul.nostyle {margin:15px 0 15px 20px !important; list-style-type:square !important;}
-ul.nostyle ul {margin:0 0 0 25px !important; list-style-type:square !important;}
-ul.nostyle li {padding:0 !important; background:none !important;}
-dl.nostyle dt {font-weight:bold !important;}
-dl.nostyle dd {margin:0 !important;}
-
-/* =============================================================================
-LAYOUT
-============================================================================= */
-
-#main {min-width:980px; width:expression(document.body.clientWidth < 980? "980px" : "auto" );}
-#tray {padding:12px 15px; background:url("../design/tray.gif") 0 0 repeat-x; font:85%/1.2 "tahoma",sans-serif;}
-#tray p {margin:0;}
-#tray p.f-left {width:50%;}
-#tray #logout {padding-left:18px; background:url("../design/tray-logout.gif") 0 50% no-repeat; text-transform:uppercase;}
-#tray #switcher {margin-right:15px;}
-#tray #switcher img {display:block; float:left; width:16px; height:16px; border:0;}
-#menu {padding:15px 15px 13px 15px; background:url("../design/menu.gif") 0 0 repeat-x;}
-#menu ul {margin:0; padding:0; list-style-type:none;}
-#menu ul li {display:inline; margin:0; padding:0;}
-#menu ul li a {float:left; margin-right:5px; padding-left:5px; background:url("../design/menu-left.gif") 0 0 no-repeat; text-decoration:none; cursor:pointer;}
-#menu ul li a span {float:left; display:block; padding:7px 15px 9px 8px; background:url("../design/menu-right.gif") 100% 0 no-repeat;}
-#menu ul li a:hover, #menu ul li#menu-active a {background:url("../design/menu-left.gif") 0 -35px no-repeat;}
-#menu ul li a:hover span, #menu ul li#menu-active a span {background:url("../design/menu-right.gif") 100% -35px no-repeat;}
-#menu ul li#menu-active a {font-weight:bold;}
-#content {padding:20px; overflow:hidden;}
-#footer {clear:both; padding:15px; background:url("../design/separator.gif") 0 0 repeat-x; font:85%/1.2 "tahoma",sans-serif;}
-#footer p {margin:0;}
-
-/* =============================================================================
-/* =============================================================================
-OTHERS
-============================================================================= */
-
-#aside .padding {padding-left:15px;}
-#aside #logo {margin:0 0 15px 0;}
-#aside #logo img {display:block; width:200px;}
-#aside #search fieldset {padding:7px 10px;}
-#aside #search fieldset p {margin:0;}
-#aside #search fieldset legend {font-weight:bold;}
-#aside #search fieldset .input-text {width:130px;}
-#aside #search fieldset #search-options {margin-top:10px;}
-#aside #btn-create {margin:0 0 15px 0;}
-#aside #btn-create a {float:left; padding-left:27px; height:37px; overflow:hidden; background:url("../design/btn-create-left.gif") 0 0 no-repeat; text-decoration:none; font-weight:bold; cursor:pointer;}
-#aside #btn-create a span {float:left; display:block; width:163px; padding:8px 0 10px 10px; background:url("../design/btn-create-right.gif") -2px 0 no-repeat;}
-#aside #btn-create a:hover {background-position:0 -37px;}
-#aside ul {width:215px; margin:0 0 15px 0; list-style:none;}
-#aside ul li {display:inline;}
-#aside ul li a {display:block; width:185px; padding:4px 15px; text-decoration:none;}
-#aside ul li#submenu-active a {width:198px; border:0; background:url("../design/submenu-active.gif") 100% 50% no-repeat; font-weight:bold; z-index:999;}
-#aside ul ul {margin:0; position:static;}
-#aside ul ul li a, #aside ul li#submenu-active ul li a {width:170px; padding:5px 15px 5px 30px; background:url("../design/submenu-sub.gif") 15px 7px no-repeat; font:85%/1.2 "tahoma",sans-serif; font-weight:normal;}
-#content h1 {margin:0; padding:10px 15px; background:url("../design/content-h1.gif") 0 0 repeat-x; letter-spacing:-1px;}
-#content .col50 {float:left; width:49%;}
-#content .col33 {float:left; width:32%;}
-#content .col33.center {padding:0 2%;}
-#content .tabs {margin:15px 0;}
-#content .tabs ul {margin:0; padding:0; list-style-type:none;}
-#content .tabs ul li {display:inline; margin:0; padding:0;}
-#content .tabs a {float:left; margin-right:3px; padding-left:4px; background:url("../design/tabs-l.gif") 0 -100px no-repeat; text-decoration:none;}
-#content .tabs a span {float:left; display:block; padding:8px 15px 6px 11px; background:url("../design/tabs-r.gif") 100% -100px no-repeat;}
-#content .tabs a:hover, .tabs a:hover span {text-decoration:underline;}
-#content .tabs .ui-tabs-selected a {background:url("../design/tabs-l.gif") 0 0 no-repeat; font-weight:bold;}
-#content .tabs .ui-tabs-selected a span {background:url("../design/tabs-r.gif") 100% 0 no-repeat;}
-#content .tabs .ui-tabs-selected a:hover, #content .tabs .ui-tabs-selected a:hover span {text-decoration:none;}
-#content .ui-tabs-hide {display: none !important;}
-.input-text {padding:3px; font:100%/1.5 "arial", sans-serif;}
-.input-text-02 {padding:5px; font:140%/1.5 "arial", sans-serif;}
-.input-submit {padding:5px; font-size:120%;}
-.input-submit-02 {padding:1px; font-size:100%;}
-.msg {padding:10px; padding-left:35px;}
-.msg.warning {background:url("../design/ico-warning.gif") 10px 50% no-repeat;}
-.msg.info {background:url("../design/ico-info.gif") 10px 50% no-repeat;}
-.msg.done {background:url("../design/ico-done.gif") 10px 50% no-repeat;}
-.msg.error {background:url("../design/ico-delete.gif") 10px 50% no-repeat;}
-
-/* =============================================================================
-FONT STYLES
-============================================================================= */
-
-.bigger {font-size:120%;}
-.smaller {font:85%/1.2 "tahoma",sans-serif;}
-
-/* This line can be deleted */
-.tit {padding:10px; background:#f5f5f5;} .tag {background:#ffa;}
View
70 public/stylesheets/mystyle.css
@@ -1,3 +1,73 @@
+body {
+ font-family: Trebuchet MS, Liberation Sans, DejaVu Sans, sans-serif;
+ font-size: 12px;
+}
+
+
+table {
+ color:#333333;
+ border-width: 1px;
+ border-color: #666;
+ border-collapse: collapse;
+}
+table th {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #666;
+}
+table td {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #666;
+}
+
+#header {
+ border: 1px solid #ddd;
+ border-width: 0px 0px 1px 0px;
+}
+#header .title {
+ font-size: 30px;
+ font-weight: bold;
+}
+
+#header h1 {
+ padding: 3px;
+}
+
+#menu ul li {
+ display: inline;
+ padding: 10px;
+}
+
+#menu ul {
+ display: inline;
+ list-style-type: none;
+ padding: 0px;
+ margin: 0px;
+}
+
+#sidebar .section {
+ font-weight: bold;
+ font-size: 1.5em;
+ padding-left: 30px;
+}
+
+#sidebar {
+ float:left;
+ width:215px;
+ margin-right:0;
+ background-color: #eee;
+}
+#content {margin-left:232px; overflow:visible;}
+
+/*
+ #cols {position:relative; margin:15px 0; padding-right:15px; }
+ html>body #sidebar {margin-right:20px;}
+ html>body #content {margin-left:0; overflow:hidden;}
+*/
+
/* project show */
.branch_title .name {
float: left;
View
31 public/stylesheets/reset.css
@@ -1,31 +0,0 @@
-/* =============================================================================
-
- RESET.CSS
- version: 1.0
- updated: 2009-02-02, 11:47 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-RESET
-============================================================================= */
-
-* {margin:0; padding:0;}
-html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {border:0; outline:0; vertical-align:baseline; background:transparent;}
-.hidden {position:absolute; left:-1000em; top:-1000em; width:1px; height:1px; overflow:hidden;}
-.noscreen {display:none;}
-.box {min-height:1px;}
-.box:after {display:block; visibility:hidden; clear:both; line-height:0; font-size:0; content:".";}
-.fix {float:none; clear:both; width:0; height:0; margin:0; padding:0; border:0; line-height:0; font-size:0;}
-.f-left {float:left !important;}
-.f-right {float:right !important;}
-.t-left {text-align:left !important;}
-.t-center {text-align:center !important;}
-.t-right {text-align:right !important;}
-.t-justify {text-align:justify !important;}
-.va-top {vertical-align:top !important;}
-.va-middle {vertical-align:middle !important;}
-.va-bottom {vertical-align:bottom !important;}
-.nom {margin:0 !important;}
-.nomt {margin-top:0 !important;}
-.nomb {margin-bottom:0 !important;}
View
86 public/stylesheets/style.css
@@ -1,86 +0,0 @@
-/* =============================================================================
-
- STYLE.CSS
- version: 1.6
- updated: 2009-03-06, 13:00 GMT+1
-
-============================================================================= */
-
-/* =============================================================================
-HTML - styles
-============================================================================= */
-
-body {background-color:#eaeaea; color:#303030;}
-a {color:#0085cc;}
-a:hover, a:active, a:focus {color:#df0000;}
-#content h2 {color:#0085cc;}
-#content table {border:2px solid #cfcfcf;}
-#content table th {border-right:1px solid #0074B3; background-color:#0085cc; color:#fff;}
-#content table td {border:1px solid #cfcfcf;}
-#content table tr.bg td {background-color:#e8f6ff;}
-#content table tr.bg2 td {background-color:#ffffff;}
-#content dl dt {color:#df0000;}
-#content fieldset {border:1px solid #ccc;}
-#content legend {background:#FFF; color:#0085cc;}
-#content acronym, #content abbr, #content .help {border-bottom:1px dotted #cfcfcf;}
-
-/* =============================================================================
-HTML - without styles
-============================================================================= */
-
-table.nostyle th, dl.nostyle dt {color:#303030 !important;}
-
-/* =============================================================================
-LAYOUT
-============================================================================= */
-
-#tray {background-color:#303030; color:#cfcfcf;}
-#tray a, #tray strong {color:#fff;}
-#tray a:hover, #tray a:active, #tray a:focus {color:#b4e3ff;}
-#menu {background-color:#0085cc;}
-#menu ul li a {background-color:#fff; color:#303030;}
-#menu ul li a span {background-color:#FFF;}
-#menu ul li a:hover, #menu ul li a:active, #menu ul li a:focus, #menu ul li#menu-active a {background-color:#FFF; color:#df0000;}
-#menu ul li a:hover span, #menu ul li#menu-active a span {background-color:#FFF;}
-#menu ul li#menu-active a {color:#0085cc;}
-#menu ul.f-right a {color:#df0000;}
-#content {border:1px solid #afafaf; background:#fff;}
-#footer {color:#707070;}
-#footer a {color:#707070;}
-#footer a:hover, #footer a:active, #footer a:focus {color:#303030;}
-
-/* =============================================================================
-OTHERS
-============================================================================= */
-
-#aside #logo img {border:1px solid #bfbfbf;}
-#aside #search fieldset a {color:#303030;}
-#aside #search fieldset {border:1px solid #bfbfbf;}
-#aside #search fieldset a:hover, #aside #search fieldset a:active, #aside #search fieldset a:focus {color:#df0000;}
-#aside #btn-create a {background-color:#fff; color:#303030;}
-#aside #btn-create a span {background-color:#fff;}
-#aside ul li a {border-bottom:1px solid #cfcfcf; color:#303030;}
-#aside ul li#submenu-active a {background-color:#df0000; color:#fff;}
-#aside ul li a:hover, #aside ul li a:active, #aside ul li a:focus {color:#df0000;}
-#aside ul ul li a, #aside ul li#submenu-active ul li a {border-bottom:1px solid #cfcfcf; background-color:#f5f5f5; color:#303030;}
-#aside ul li ul li a {background-color:#e3e3e3;}
-#aside ul ul li a:hover, #aside ul ul li a:active, #aside ul ul li a:focus, #aside ul li#submenu-active ul li a:hover, #aside ul li#submenu-active ul li a:active, #aside ul li#submenu-active ul li a:focus {color:#df0000;}
-#content h1 {background-color:#303030; color:#fff;}
-#content .tabs {border-bottom:1px solid #cfcfcf;}
-#content .tabs a {color:#303030;}
-#content .tabs a span {color:#303030;}
-#content .tabs .ui-tabs-selected a {color:#fff;}
-#content .tabs .ui-tabs-selected a span {color:#fff;}
-.high {color:#df0000;}
-.high-bg {background:#FFB;}
-.low {color:#707070;}
-
-/* =============================================================================
-MESSAGES
-============================================================================= */
-
-.msg.warning {border:2px solid #F2DD8C; background-color:#FFF5CC;}
-.msg.warning a {color:#df0000;} .msg.warning a:hover, .msg.warning a:active, .msg.warning a:focus {color:#303030;}
-.msg.info {border:2px solid #B8E2FB; background-color:#E8F6FF;}
-.msg.done {border:2px solid #BBDF8D; background-color:#EAF7D9;}
-.msg.error {border:2px solid #FFAEAE; background-color:#FEEBEB;}
View
5 test/factories/project.rb
@@ -0,0 +1,5 @@
+FactoryGirl.define do
+ factory :project do
+ name "foo"
+ end
+end
View
10 test/factories/project_instance.rb
@@ -0,0 +1,10 @@
+FactoryGirl.define do
+ factory :project_instance do
+ project
+ working_directory "#{Rails.root}/tmp/test_run/#{$instance_dir = $instance_dir.to_i + 1}"
+ after_create do |o|
+ # cleaned up in test_helper
+ FileUtils.mkdir_p o.working_directory
+ end
+ end
+end
View
3  test/test_helper.rb
@@ -1,6 +1,9 @@
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
+require 'fileutils'
+
+FileUtils.rm_rf("#{Rails.root}/tmp/test_run") if File.exists? Rails.root
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
View
42 test/unit/project_instance_test.rb
@@ -1,8 +1,46 @@
require 'test_helper'
class ProjectInstanceTest < ActiveSupport::TestCase
+
# Replace this with your real tests.
- test "the truth" do
- assert true
+ test "locking" do
+ project = Factory.create :project
+ instance = Factory.create :project_instance, :project => project
+ assert instance.try_to_acquire("foo")
+ assert !instance.try_to_acquire("baz")
+ instance.free!
+ assert_nil instance.locked_by
+ assert_nil instance.reload.locked_by
+ assert instance.try_to_acquire("baz")
+ assert_equal instance.locked_by, "baz"
+ instance.free!
+ assert_nil instance.locked_by
+ end
+
+ test "collecting output from execution" do
+ instance = Factory.create :project_instance
+ output = ''
+ assert instance.execute "echo 'this is test'", output
+ lines = output.split("\n")
+ assert lines[0].starts_with? '$' # first line is command being executed
+ assert_equal lines[1], '' # second separating line
+ assert_equal lines[2], 'this is test'
+ end
+
+ test "collecting execution status" do
+ instance = Factory.create :project_instance
+ assert instance.execute("exit 0")
+ assert !instance.execute("exit 1")
end
+
+ test "execute!" do
+ instance = Factory.create :project_instance
+ instance.execute!("exit 0")
+ assert_raise RuntimeError do
+ instance.execute!("exit 1")
+ end
+ end
+
+
end
+

No commit comments for this range

Something went wrong with that request. Please try again.