sr-integrity 0.1.8.1
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/README.markdown +73 -0
- data/Rakefile +91 -0
- data/VERSION.yml +4 -0
- data/bin/integrity +4 -0
- data/config/config.sample.ru +21 -0
- data/config/config.sample.yml +41 -0
- data/config/thin.sample.yml +13 -0
- data/integrity.gemspec +55 -0
- data/lib/integrity/app.rb +137 -0
- data/lib/integrity/author.rb +39 -0
- data/lib/integrity/build.rb +84 -0
- data/lib/integrity/commit.rb +71 -0
- data/lib/integrity/core_ext/object.rb +6 -0
- data/lib/integrity/helpers/authorization.rb +33 -0
- data/lib/integrity/helpers/breadcrumbs.rb +20 -0
- data/lib/integrity/helpers/forms.rb +28 -0
- data/lib/integrity/helpers/pretty_output.rb +45 -0
- data/lib/integrity/helpers/rendering.rb +14 -0
- data/lib/integrity/helpers/resources.rb +13 -0
- data/lib/integrity/helpers/urls.rb +49 -0
- data/lib/integrity/helpers.rb +16 -0
- data/lib/integrity/installer.rb +121 -0
- data/lib/integrity/migrations.rb +140 -0
- data/lib/integrity/notifier/base.rb +65 -0
- data/lib/integrity/notifier.rb +50 -0
- data/lib/integrity/project.rb +142 -0
- data/lib/integrity/project_builder.rb +56 -0
- data/lib/integrity/scm/git/uri.rb +57 -0
- data/lib/integrity/scm/git.rb +84 -0
- data/lib/integrity/scm.rb +19 -0
- data/lib/integrity.rb +80 -0
- data/public/buttons.css +82 -0
- data/public/reset.css +7 -0
- data/public/spinner.gif +0 -0
- data/test/helpers/acceptance/git_helper.rb +99 -0
- data/test/helpers/acceptance/textfile_notifier.rb +26 -0
- data/test/helpers/acceptance.rb +80 -0
- data/test/helpers/expectations/be_a.rb +23 -0
- data/test/helpers/expectations/change.rb +90 -0
- data/test/helpers/expectations/have.rb +105 -0
- data/test/helpers/expectations/have_tag.rb +128 -0
- data/test/helpers/expectations/predicates.rb +37 -0
- data/test/helpers/expectations.rb +5 -0
- data/test/helpers/fixtures.rb +107 -0
- data/test/helpers/initial_migration_fixture.sql +44 -0
- data/test/helpers.rb +70 -0
- data/views/_commit_info.haml +24 -0
- data/views/build.haml +2 -0
- data/views/error.haml +37 -0
- data/views/home.haml +21 -0
- data/views/integrity.sass +400 -0
- data/views/layout.haml +28 -0
- data/views/new.haml +51 -0
- data/views/not_found.haml +31 -0
- data/views/notifier.haml +7 -0
- data/views/project.builder +21 -0
- data/views/project.haml +30 -0
- data/views/unauthorized.haml +38 -0
- metadata +190 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module Breadcrumbs
|
4
|
+
def pages
|
5
|
+
@pages ||= [["projects", "/"], ["new project", "/new"]]
|
6
|
+
end
|
7
|
+
|
8
|
+
def breadcrumbs(*crumbs)
|
9
|
+
crumbs[0..-2].map do |crumb|
|
10
|
+
if page_data = pages.detect {|c| c.first == crumb }
|
11
|
+
%Q(<a href="#{page_data.last}">#{page_data.first}</a>)
|
12
|
+
elsif @project && @project.permalink == crumb
|
13
|
+
%Q(<a href="#{project_url(@project)}">#{@project.permalink}</a>)
|
14
|
+
end
|
15
|
+
end + [crumbs.last]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module Forms
|
4
|
+
def errors_on(object, field)
|
5
|
+
return "" unless errors = object.errors.on(field)
|
6
|
+
errors.map {|e| e.gsub(/#{field} /i, "") }.join(", ")
|
7
|
+
end
|
8
|
+
|
9
|
+
def error_class(object, field)
|
10
|
+
object.errors.on(field).nil? ? "" : "with_errors"
|
11
|
+
end
|
12
|
+
|
13
|
+
def checkbox(name, condition, extras={})
|
14
|
+
attrs = { :name => name, :type => "checkbox", :value => "1" }
|
15
|
+
attrs[:checked] = !!condition
|
16
|
+
attrs.update(extras)
|
17
|
+
end
|
18
|
+
|
19
|
+
def notifier_form(notifier)
|
20
|
+
haml(notifier.to_haml, :layout => :notifier, :locals => {
|
21
|
+
:config => current_project.config_for(notifier),
|
22
|
+
:notifier => "#{notifier.to_s.split(/::/).last}",
|
23
|
+
:enabled => current_project.notifies?(notifier)
|
24
|
+
})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module PrettyOutput
|
4
|
+
def cycle(*values)
|
5
|
+
@cycles ||= {}
|
6
|
+
@cycles[values] ||= -1 # first value returned is 0
|
7
|
+
next_value = @cycles[values] = (@cycles[values] + 1) % values.size
|
8
|
+
values[next_value]
|
9
|
+
end
|
10
|
+
|
11
|
+
def bash_color_codes(string)
|
12
|
+
string.gsub("\e[0m", '</span>').
|
13
|
+
gsub("\e[31m", '<span class="color31">').
|
14
|
+
gsub("\e[32m", '<span class="color32">').
|
15
|
+
gsub("\e[33m", '<span class="color33">').
|
16
|
+
gsub("\e[34m", '<span class="color34">').
|
17
|
+
gsub("\e[35m", '<span class="color35">').
|
18
|
+
gsub("\e[36m", '<span class="color36">').
|
19
|
+
gsub("\e[37m", '<span class="color37">')
|
20
|
+
end
|
21
|
+
|
22
|
+
def pretty_date(date_time)
|
23
|
+
days_away = (Date.today - Date.new(date_time.year, date_time.month, date_time.day)).to_i
|
24
|
+
if days_away == 0
|
25
|
+
"today"
|
26
|
+
elsif days_away == 1
|
27
|
+
"yesterday"
|
28
|
+
else
|
29
|
+
strftime_with_ordinal(date_time, "on %b %d%o")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def strftime_with_ordinal(date_time, format_string)
|
34
|
+
ordinal = case date_time.day
|
35
|
+
when 1, 21, 31 then "st"
|
36
|
+
when 2, 22 then "nd"
|
37
|
+
when 3, 23 then "rd"
|
38
|
+
else "th"
|
39
|
+
end
|
40
|
+
|
41
|
+
date_time.strftime(format_string.gsub("%o", ordinal))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module Rendering
|
4
|
+
def show(view, options={})
|
5
|
+
@title = breadcrumbs(*options[:title])
|
6
|
+
haml view
|
7
|
+
end
|
8
|
+
|
9
|
+
def partial(template, locals={})
|
10
|
+
haml("_#{template}".to_sym, :locals => locals, :layout => false)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module Resources
|
4
|
+
def current_project
|
5
|
+
@project ||= Project.first(:permalink => params[:project]) or raise Sinatra::NotFound
|
6
|
+
end
|
7
|
+
|
8
|
+
def current_commit
|
9
|
+
@commit ||= current_project.commits.first(:identifier => params[:commit]) or raise Sinatra::NotFound
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Integrity
|
2
|
+
module Helpers
|
3
|
+
module Urls
|
4
|
+
def url(path)
|
5
|
+
Addressable::URI.parse(request.url).join(path).to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
def root_url
|
9
|
+
url("/")
|
10
|
+
end
|
11
|
+
|
12
|
+
def project_path(project, *path)
|
13
|
+
"/" << [project.permalink, *path].join("/")
|
14
|
+
end
|
15
|
+
|
16
|
+
def project_url(project, *path)
|
17
|
+
url project_path(project, *path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def push_url_for(project)
|
21
|
+
Addressable::URI.parse(project_url(project, "push")).tap do |url|
|
22
|
+
if Integrity.config[:use_basic_auth]
|
23
|
+
url.user = Integrity.config[:admin_username]
|
24
|
+
url.password = Integrity.config[:hash_admin_password] ?
|
25
|
+
"<password>" : Integrity.config[:admin_password]
|
26
|
+
end
|
27
|
+
end.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
def commit_path(commit, *path)
|
31
|
+
project_path(commit.project, "commits", commit.identifier, *path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_path(build, *path)
|
35
|
+
warn "#build_path is deprecated, use #commit_path instead"
|
36
|
+
commit_path build.commit, *path
|
37
|
+
end
|
38
|
+
|
39
|
+
def commit_url(commit)
|
40
|
+
url commit_path(commit)
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_url(build)
|
44
|
+
warn "#build_url is deprecated, use #commit_url instead"
|
45
|
+
commit_url build.commit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Dir["#{File.dirname(__FILE__)}/helpers/*.rb"].each &method(:require)
|
2
|
+
|
3
|
+
module Integrity
|
4
|
+
module Helpers
|
5
|
+
include Authorization
|
6
|
+
include Breadcrumbs
|
7
|
+
include Forms
|
8
|
+
include PrettyOutput
|
9
|
+
include Rendering
|
10
|
+
include Resources
|
11
|
+
include Urls
|
12
|
+
|
13
|
+
include Rack::Utils
|
14
|
+
alias :h :escape_html
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../integrity"
|
2
|
+
require "thor"
|
3
|
+
|
4
|
+
module Integrity
|
5
|
+
class Installer < Thor
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
desc "install [PATH]",
|
9
|
+
"Copy template files to PATH for desired deployement strategy
|
10
|
+
(either Thin or Passenger). Next, go there and edit them."
|
11
|
+
method_options :passenger => false, :thin => false
|
12
|
+
def install(path)
|
13
|
+
@root = Pathname(path).expand_path
|
14
|
+
|
15
|
+
create_dir_structure
|
16
|
+
copy_template_files
|
17
|
+
edit_template_files
|
18
|
+
migrate_db(root.join("config.yml"))
|
19
|
+
after_setup_message
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "migrate_db [CONFIG]",
|
23
|
+
"Checks the `database_uri` in CONFIG and migrates the
|
24
|
+
database up to the lastest version."
|
25
|
+
def migrate_db(config)
|
26
|
+
Integrity.new(config)
|
27
|
+
|
28
|
+
require "integrity/migrations"
|
29
|
+
Integrity.migrate_db
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "launch [CONFIG]",
|
33
|
+
"Launch Integrity real quick."
|
34
|
+
method_options :config => :optional, :port => 4567
|
35
|
+
def launch
|
36
|
+
require "thin"
|
37
|
+
require "do_sqlite3"
|
38
|
+
|
39
|
+
if File.file?(options[:config].to_s)
|
40
|
+
Integrity.new(options[:config])
|
41
|
+
else
|
42
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
43
|
+
end
|
44
|
+
|
45
|
+
DataMapper.auto_migrate!
|
46
|
+
|
47
|
+
Thin::Server.start("0.0.0.0", options[:port], Integrity::App)
|
48
|
+
rescue LoadError => boom
|
49
|
+
missing_dependency = boom.message.split("--").last.lstrip
|
50
|
+
puts "Please install #{missing_dependency} to launch Integrity"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "version",
|
54
|
+
"Print the current integrity version"
|
55
|
+
def version
|
56
|
+
puts Integrity.version
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
attr_reader :root
|
61
|
+
|
62
|
+
def create_dir_structure
|
63
|
+
mkdir_p root
|
64
|
+
mkdir_p root / "builds"
|
65
|
+
mkdir_p root / "log"
|
66
|
+
|
67
|
+
if options[:passenger]
|
68
|
+
mkdir_p root / "public"
|
69
|
+
mkdir_p root / "tmp"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def copy_template_files
|
74
|
+
copy "config/config.sample.ru"
|
75
|
+
copy "config/config.sample.yml"
|
76
|
+
copy "config/thin.sample.yml" if options[:thin]
|
77
|
+
end
|
78
|
+
|
79
|
+
def edit_template_files
|
80
|
+
edit_integrity_configuration
|
81
|
+
edit_thin_configuration if options[:thin]
|
82
|
+
end
|
83
|
+
|
84
|
+
def edit_integrity_configuration
|
85
|
+
config = File.read(root / "config.yml")
|
86
|
+
config.gsub! %r(sqlite3:///var/integrity.db), "sqlite3://#{root}/integrity.db"
|
87
|
+
config.gsub! %r(/path/to/scm/exports), "#{root}/builds"
|
88
|
+
config.gsub! %r(/var/log), "#{root}/log"
|
89
|
+
File.open(root / "config.yml", "w") { |f| f.puts config }
|
90
|
+
end
|
91
|
+
|
92
|
+
def edit_thin_configuration
|
93
|
+
config = File.read(root / "thin.yml")
|
94
|
+
config.gsub! %r(/apps/integrity), root
|
95
|
+
File.open(root / "thin.yml", 'w') { |f| f.puts config }
|
96
|
+
end
|
97
|
+
|
98
|
+
def after_setup_message
|
99
|
+
puts
|
100
|
+
puts %Q(Awesome! Integrity was installed successfully!)
|
101
|
+
puts
|
102
|
+
puts %Q(If you want to enable notifiers, install the gems and then require them)
|
103
|
+
puts %Q(in #{root}/config.ru)
|
104
|
+
puts
|
105
|
+
puts %Q(For example:)
|
106
|
+
puts
|
107
|
+
puts %Q( sudo gem install -s http://gems.github.com foca-integrity-email)
|
108
|
+
puts
|
109
|
+
puts %Q(And then in #{root}/config.ru add:)
|
110
|
+
puts
|
111
|
+
puts %Q( require "notifier/email")
|
112
|
+
puts
|
113
|
+
puts %Q(Don't forget to tweak #{root / "config.yml"} to your needs.)
|
114
|
+
end
|
115
|
+
|
116
|
+
def copy(path)
|
117
|
+
cp(File.dirname(__FILE__) + "/../../#{path}",
|
118
|
+
root.join(File.basename(path).gsub(/\.sample/, "")))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require "dm-migrations"
|
2
|
+
require "migration_runner"
|
3
|
+
|
4
|
+
module Integrity
|
5
|
+
def self.migrate_db
|
6
|
+
setup_initial_migration if pre_migrations?
|
7
|
+
Integrity::Migrations.migrate_up!
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.setup_initial_migration
|
11
|
+
database_adapter.execute %q(CREATE TABLE "migration_info" ("migration_name" VARCHAR(255));)
|
12
|
+
database_adapter.execute %q(INSERT INTO "migration_info" ("migration_name") VALUES ("initial"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.pre_migrations?
|
16
|
+
!table_exists?("migration_info") &&
|
17
|
+
( table_exists?("integrity_projects") &&
|
18
|
+
table_exists?("integrity_builds") &&
|
19
|
+
table_exists?("integrity_notifiers") )
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.table_exists?(table_name)
|
23
|
+
database_adapter.storage_exists?(table_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.database_adapter
|
27
|
+
DataMapper.repository(:default).adapter
|
28
|
+
end
|
29
|
+
|
30
|
+
module Migrations
|
31
|
+
# This is what is actually happening:
|
32
|
+
# include DataMapper::MigrationRunner
|
33
|
+
|
34
|
+
include DataMapper::Types
|
35
|
+
|
36
|
+
migration 1, :initial, :verbose => true do
|
37
|
+
up do
|
38
|
+
create_table :integrity_projects do
|
39
|
+
column :id, Integer, :serial => true
|
40
|
+
column :name, String, :nullable => false
|
41
|
+
column :permalink, String
|
42
|
+
column :uri, URI, :nullable => false
|
43
|
+
column :branch, String, :nullable => false, :default => "master"
|
44
|
+
column :command, String, :nullable => false, :default => "rake"
|
45
|
+
column :public, Boolean, :default => true
|
46
|
+
column :building, Boolean, :default => false
|
47
|
+
column :created_at, DateTime
|
48
|
+
column :updated_at, DateTime
|
49
|
+
|
50
|
+
column :build_id, Integer
|
51
|
+
column :notifier_id, Integer
|
52
|
+
end
|
53
|
+
|
54
|
+
create_table :integrity_builds do
|
55
|
+
column :id, Integer, :serial => true
|
56
|
+
column :output, Text, :nullable => false, :default => ""
|
57
|
+
column :successful, Boolean, :nullable => false, :default => false
|
58
|
+
column :commit_identifier, String, :nullable => false
|
59
|
+
column :commit_metadata, Yaml, :nullable => false
|
60
|
+
column :created_at, DateTime
|
61
|
+
column :updated_at, DateTime
|
62
|
+
|
63
|
+
column :project_id, Integer
|
64
|
+
end
|
65
|
+
|
66
|
+
create_table :integrity_notifiers do
|
67
|
+
column :id, Integer, :serial => true
|
68
|
+
column :name, String, :nullable => false
|
69
|
+
column :config, Yaml, :nullable => false
|
70
|
+
|
71
|
+
column :project_id, Integer
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
migration 2, :add_commits, :verbose => true do
|
77
|
+
up do
|
78
|
+
class ::Integrity::Build
|
79
|
+
property :commit_identifier, String
|
80
|
+
property :commit_metadata, Yaml, :lazy => false
|
81
|
+
property :project_id, Integer
|
82
|
+
end
|
83
|
+
|
84
|
+
create_table :integrity_commits do
|
85
|
+
column :id, Integer, :serial => true
|
86
|
+
column :identifier, String, :nullable => false
|
87
|
+
column :message, String, :nullable => false, :length => 255
|
88
|
+
column :author, String, :nullable => false, :length => 255
|
89
|
+
column :committed_at, DateTime, :nullable => false
|
90
|
+
column :created_at, DateTime
|
91
|
+
column :updated_at, DateTime
|
92
|
+
|
93
|
+
column :project_id, Integer
|
94
|
+
end
|
95
|
+
|
96
|
+
modify_table :integrity_builds do
|
97
|
+
add_column :commit_id, Integer
|
98
|
+
add_column :started_at, DateTime
|
99
|
+
add_column :completed_at, DateTime
|
100
|
+
end
|
101
|
+
|
102
|
+
# Die, orphans, die
|
103
|
+
Build.all(:project_id => nil).destroy!
|
104
|
+
|
105
|
+
# sqlite hodgepockery
|
106
|
+
all_builds = Build.all.each {|b| b.freeze }
|
107
|
+
drop_table :integrity_builds
|
108
|
+
create_table :integrity_builds do
|
109
|
+
column :id, Integer, :serial => true
|
110
|
+
column :started_at, DateTime
|
111
|
+
column :completed_at, DateTime
|
112
|
+
column :successful, Boolean
|
113
|
+
column :output, Text, :nullable => false, :default => ""
|
114
|
+
column :created_at, DateTime
|
115
|
+
column :updated_at, DateTime
|
116
|
+
|
117
|
+
column :commit_id, Integer
|
118
|
+
end
|
119
|
+
|
120
|
+
all_builds.each do |build|
|
121
|
+
commit = Commit.first(:identifier => build.commit_identifier)
|
122
|
+
|
123
|
+
if commit.nil?
|
124
|
+
commit = Commit.create(:identifier => build.commit_identifier,
|
125
|
+
:message => build.commit_metadata[:message],
|
126
|
+
:author => build.commit_metadata[:author],
|
127
|
+
:committed_at => build.commit_metadata[:date],
|
128
|
+
:project_id => build.project_id)
|
129
|
+
end
|
130
|
+
|
131
|
+
Build.create(:commit_id => commit.id,
|
132
|
+
:started_at => build.created_at,
|
133
|
+
:completed_at => build.updated_at,
|
134
|
+
:successful => build.successful,
|
135
|
+
:output => build.output)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Integrity
|
2
|
+
class Notifier
|
3
|
+
class Base
|
4
|
+
def self.notify_of_build(build, config)
|
5
|
+
Timeout.timeout(8) { new(build, config).deliver! }
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.to_haml
|
9
|
+
raise NoMethodError, "you need to implement this method in your notifier"
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :commit
|
13
|
+
|
14
|
+
def initialize(commit, config)
|
15
|
+
@commit = commit
|
16
|
+
@config = config
|
17
|
+
end
|
18
|
+
|
19
|
+
def build
|
20
|
+
warn "Notifier::Base#build is deprecated, use Notifier::Base#commit instead"
|
21
|
+
commit
|
22
|
+
end
|
23
|
+
|
24
|
+
def deliver!
|
25
|
+
raise NoMethodError, "you need to implement this method in your notifier"
|
26
|
+
end
|
27
|
+
|
28
|
+
def short_message
|
29
|
+
commit.human_readable_status
|
30
|
+
end
|
31
|
+
|
32
|
+
def full_message
|
33
|
+
<<-EOM
|
34
|
+
"Build #{commit.identifier} #{commit.successful? ? "was successful" : "failed"}"
|
35
|
+
|
36
|
+
Commit Message: #{commit.message}
|
37
|
+
Commit Date: #{commit.committed_at}
|
38
|
+
Commit Author: #{commit.author.name}
|
39
|
+
|
40
|
+
Link: #{commit_url}
|
41
|
+
|
42
|
+
Build Output:
|
43
|
+
|
44
|
+
#{stripped_commit_output}
|
45
|
+
EOM
|
46
|
+
end
|
47
|
+
|
48
|
+
def commit_url
|
49
|
+
raise if Integrity.config[:base_uri].nil?
|
50
|
+
Integrity.config[:base_uri] / commit.project.permalink / "commits" / commit.identifier
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def stripped_commit_output
|
56
|
+
commit.output.gsub("\e[0m", "").gsub(/\e\[3[1-7]m/, "")
|
57
|
+
end
|
58
|
+
|
59
|
+
def stripped_build_output
|
60
|
+
warn "Notifier::Base#stripped_build_output is deprecated, use Notifier::base#stripped_commit_output instead"
|
61
|
+
stripped_commit_output
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Integrity
|
2
|
+
class Notifier
|
3
|
+
include DataMapper::Resource
|
4
|
+
|
5
|
+
property :id, Integer, :serial => true
|
6
|
+
property :name, String, :nullable => false
|
7
|
+
property :config, Yaml, :nullable => false, :lazy => false
|
8
|
+
|
9
|
+
belongs_to :project, :class_name => "Integrity::Project"
|
10
|
+
|
11
|
+
validates_is_unique :name, :scope => :project_id
|
12
|
+
validates_present :project_id
|
13
|
+
|
14
|
+
def self.available
|
15
|
+
@available ||= constants.map { |name| const_get(name) }.select { |notifier| valid_notifier?(notifier) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.enable_notifiers(project, enabled, config={})
|
19
|
+
all(:project_id => project).destroy!
|
20
|
+
list_of_enabled_notifiers(enabled).each do |name|
|
21
|
+
create! :project_id => project, :name => name, :config => config[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def notify_of_build(build)
|
27
|
+
to_const.notify_of_build(build, config)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def to_const
|
33
|
+
self.class.module_eval(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.list_of_enabled_notifiers(names)
|
37
|
+
[*names].reject { |n| n.nil? }
|
38
|
+
end
|
39
|
+
private_class_method :list_of_enabled_notifiers
|
40
|
+
|
41
|
+
def self.valid_notifier?(notifier)
|
42
|
+
notifier.respond_to?(:to_haml) && notifier.respond_to?(:notify_of_build) && notifier != Notifier::Base
|
43
|
+
end
|
44
|
+
private_class_method :valid_notifier?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
require File.dirname(__FILE__) / "notifier" / "base"
|
49
|
+
|
50
|
+
Dir["#{File.dirname(__FILE__)}/notifier/*.rb"].each &method(:require)
|