integrity 0.1.8

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.
Files changed (57) hide show
  1. data/README.markdown +66 -0
  2. data/Rakefile +165 -0
  3. data/VERSION.yml +4 -0
  4. data/app.rb +138 -0
  5. data/bin/integrity +4 -0
  6. data/config/config.sample.ru +31 -0
  7. data/config/config.sample.yml +38 -0
  8. data/config/thin.sample.yml +13 -0
  9. data/integrity.gemspec +76 -0
  10. data/lib/integrity.rb +80 -0
  11. data/lib/integrity/build.rb +61 -0
  12. data/lib/integrity/core_ext/object.rb +6 -0
  13. data/lib/integrity/core_ext/string.rb +5 -0
  14. data/lib/integrity/helpers.rb +16 -0
  15. data/lib/integrity/helpers/authorization.rb +33 -0
  16. data/lib/integrity/helpers/breadcrumbs.rb +20 -0
  17. data/lib/integrity/helpers/forms.rb +28 -0
  18. data/lib/integrity/helpers/pretty_output.rb +45 -0
  19. data/lib/integrity/helpers/rendering.rb +14 -0
  20. data/lib/integrity/helpers/resources.rb +13 -0
  21. data/lib/integrity/helpers/urls.rb +47 -0
  22. data/lib/integrity/installer.rb +132 -0
  23. data/lib/integrity/migrations.rb +157 -0
  24. data/lib/integrity/notifier.rb +50 -0
  25. data/lib/integrity/notifier/base.rb +55 -0
  26. data/lib/integrity/project.rb +117 -0
  27. data/lib/integrity/project_builder.rb +47 -0
  28. data/lib/integrity/scm.rb +19 -0
  29. data/lib/integrity/scm/git.rb +83 -0
  30. data/lib/integrity/scm/git/uri.rb +57 -0
  31. data/public/buttons.css +82 -0
  32. data/public/reset.css +7 -0
  33. data/public/spinner.gif +0 -0
  34. data/test/helpers.rb +47 -0
  35. data/test/helpers/acceptance.rb +127 -0
  36. data/test/helpers/acceptance/git_helper.rb +99 -0
  37. data/test/helpers/acceptance/textfile_notifier.rb +26 -0
  38. data/test/helpers/expectations.rb +5 -0
  39. data/test/helpers/expectations/be_a.rb +23 -0
  40. data/test/helpers/expectations/change.rb +90 -0
  41. data/test/helpers/expectations/have.rb +105 -0
  42. data/test/helpers/expectations/have_tag.rb +128 -0
  43. data/test/helpers/expectations/predicates.rb +37 -0
  44. data/test/helpers/fixtures.rb +83 -0
  45. data/views/_build_info.haml +18 -0
  46. data/views/build.haml +2 -0
  47. data/views/error.haml +36 -0
  48. data/views/home.haml +23 -0
  49. data/views/integrity.sass +387 -0
  50. data/views/layout.haml +28 -0
  51. data/views/new.haml +51 -0
  52. data/views/not_found.haml +31 -0
  53. data/views/notifier.haml +7 -0
  54. data/views/project.builder +21 -0
  55. data/views/project.haml +28 -0
  56. data/views/unauthorized.haml +38 -0
  57. metadata +258 -0
data/README.markdown ADDED
@@ -0,0 +1,66 @@
1
+ Integrity
2
+ =========
3
+
4
+ [Integrity][website] is your friendly automated Continuous Integration server.
5
+
6
+ * See our [website][] for documentation and a [live demo][demo]
7
+ * Report bugs and submit features request on our [Lighthouse account][lighthouse]
8
+ * Join us on [#integrity][irc-channel] for ideas, help, patches or something
9
+ * Get the code on [GitHub][repo]
10
+
11
+ Thanks
12
+ ------
13
+
14
+ Thanks to the fellowing people for their feedbacks, ideas and patches :
15
+
16
+ * [James Adam][james]
17
+ * [Elliott Cable][ec]
18
+ * [Corey Donohoe][atmos]
19
+ * [Kyle Hargraves][kyle]
20
+ * [Pier-Hugues Pellerin][ph]
21
+ * [Simon Rozet][sr]
22
+ * [Scott Taylor][scott]
23
+
24
+ License
25
+ -------
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2008 [Nicolás Sanguinetti][foca], [entp][]
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
+
50
+ [website]: http://integrityapp.com
51
+ [demo]: http://builder.integrityapp.com
52
+ [repo]: http://github.com/foca/integrity
53
+ [lighthouse]: http://integrity.lighthouseapp.com/projects/14308-integrity
54
+ [irc-channel]: irc://irc.freenode.net/integrity
55
+
56
+ [foca]: http://nicolassanguinetti.info/
57
+ [entp]: http://entp.com
58
+
59
+ [james]: http://github.com/lazyatom
60
+ [ec]: http://github.com/elliotcabble
61
+ [atmos]: http://github.com/atmos
62
+ [kyle]: http://github.com/pd
63
+ [ph]: http://github.com/ph
64
+ [sr]: http://purl.org/net/sr/
65
+ [scott]: http://github.com/smtlaissezfaire
66
+
data/Rakefile ADDED
@@ -0,0 +1,165 @@
1
+ require "rake/testtask"
2
+ require "rake/clean"
3
+ require "rcov/rcovtask"
4
+
5
+ require File.dirname(__FILE__) + "/lib/integrity"
6
+
7
+ desc "Run all tests and check test coverage"
8
+ task :default => "test:coverage:verify"
9
+
10
+ desc "Run tests"
11
+ task :test => %w(test:units test:acceptance)
12
+
13
+ namespace :test do
14
+ Rake::TestTask.new(:units) do |t|
15
+ t.test_files = FileList["test/unit/*_test.rb"]
16
+ end
17
+
18
+ Rake::TestTask.new(:acceptance) do |t|
19
+ t.test_files = FileList["test/acceptance/*_test.rb"]
20
+ end
21
+
22
+ desc "Measure test coverage"
23
+ task :coverage => %w(test:coverage:units test:coverage:acceptance)
24
+
25
+ namespace :coverage do
26
+ desc "Measure test coverage of unit tests"
27
+ Rcov::RcovTask.new(:units) do |rcov|
28
+ rcov.pattern = "test/unit/*_test.rb"
29
+ rcov.rcov_opts = %w(--html --aggregate .aggregated_coverage_report)
30
+ rcov.rcov_opts << ENV["RCOV_OPTS"] if ENV["RCOV_OPTS"]
31
+ end
32
+
33
+ desc "Measure test coverage of acceptance tests"
34
+ Rcov::RcovTask.new(:acceptance) do |rcov|
35
+ rcov.pattern = "test/acceptance/*_test.rb"
36
+ rcov.rcov_opts = %w(--html --aggregate .aggregated_coverage_report)
37
+ rcov.rcov_opts << ENV["RCOV_OPTS"] if ENV["RCOV_OPTS"]
38
+ end
39
+
40
+ desc "Verify test coverage"
41
+ task :verify => "test:coverage" do
42
+ File.read("coverage/index.html") =~ /<tt class='coverage_total'>\s*(\d+\.\d+)%\s*<\/tt>/
43
+ coverage = $1.to_f
44
+
45
+ puts
46
+ if coverage == 100
47
+ puts "\e[32m100% coverage! Awesome!\e[0m"
48
+ else
49
+ puts "\e[31mOnly #{coverage}% code coverage. You can do better ;)\e[0m"
50
+ end
51
+ end
52
+ end
53
+
54
+ desc "Install all gems on which the tests depend on"
55
+ task :install_dependencies do
56
+ system 'gem install redgreen rr mocha ruby-debug dm-sweatshop webrat'
57
+ system 'gem install -s http://gems.github.com jeremymcanally-context jeremymcanally-matchy jeremymcanally-pending foca-storyteller'
58
+ end
59
+ end
60
+
61
+ namespace :db do
62
+ desc "Setup connection."
63
+ task :connect do
64
+ config = File.expand_path(ENV['CONFIG']) if ENV['CONFIG']
65
+ config = Integrity.root / 'config.yml' if File.exists?(Integrity.root / 'config.yml')
66
+ Integrity.new(config)
67
+ end
68
+
69
+ desc "Automigrate the database"
70
+ task :migrate => :connect do
71
+ require "project"
72
+ require "build"
73
+ require "notifier"
74
+ DataMapper.auto_migrate!
75
+ end
76
+ end
77
+
78
+ # tx RMT :)
79
+ namespace :rubyforge do
80
+ def package(ext="")
81
+ "dist/integrity-#{Integrity.version}" + ext
82
+ end
83
+
84
+ directory "dist/"
85
+ CLOBBER.include("dist")
86
+
87
+ desc "Build packages"
88
+ task :package => %w[.gem .tar.gz].map { |ext| package(ext) } << :changelog
89
+
90
+ desc "Build and install as local gem"
91
+ task :install => package(".gem") do
92
+ sh "gem install #{package(".gem")}"
93
+ end
94
+
95
+ file package(".gem") => %w[dist/ integrity.gemspec] do |f|
96
+ sh "gem build integrity.gemspec"
97
+ mv File.basename(f.name), f.name
98
+ end
99
+
100
+ file package('.tar.gz') => %w[dist/] do |f|
101
+ sh <<-SH
102
+ git archive \
103
+ --prefix=integrity-#{Integrity.version}/ \
104
+ --format=tar \
105
+ HEAD | gzip > #{f.name}
106
+ SH
107
+ end
108
+
109
+ desc "Publish gem and tarball to rubyforge"
110
+ task "publish:gem" => [package(".gem"), package(".tar.gz")] do |t|
111
+ sh <<-end
112
+ rubyforge add_release integrity integrity #{Integrity.version} #{package('.gem')} &&
113
+ rubyforge add_file integrity integrity #{Integrity.version} #{package('.tar.gz')}
114
+ end
115
+ end
116
+
117
+ file "dist/git-changelog.py" => %w[dist/] do
118
+ sh "cd dist && wget http://gist.github.com/raw/62837/bc6d2c6102933c3eac5fa33afd3effd7ab97edb7/git-changelog.py"
119
+ end
120
+
121
+ task :changelog => ["dist/git-changelog.py"] do
122
+ sh "python git-changelog.py"
123
+ sh "git add ChangeLog"
124
+ sh 'git commit -m "Regenerated ChangeLog"'
125
+ end
126
+ end
127
+
128
+ begin
129
+ require "jeweler"
130
+
131
+ namespace :jeweler do
132
+ Jeweler::Tasks.new do |s|
133
+ files = `git ls-files`.split("\n").reject {|f| f =~ %r(^test/acceptance) || f =~ %r(^test/unit) || f =~ /^\.git/ }
134
+
135
+ s.name = 'integrity'
136
+ s.summary = 'The easy and fun Continuous Integration server'
137
+ s.description = 'Your Friendly Continuous Integration server. Easy, fun and painless!'
138
+ s.homepage = 'http://integrityapp.com'
139
+ s.rubyforge_project = 'integrity'
140
+ s.email = 'contacto@nicolassanguinetti.info'
141
+ s.authors = ['Nicolás Sanguinetti', 'Simon Rozet']
142
+ s.files = files
143
+ s.executables = ['integrity']
144
+ s.post_install_message = 'Run `integrity help` for information on how to setup Integrity.'
145
+
146
+ s.add_dependency 'sinatra', ['>= 0.9.0.3']
147
+ s.add_dependency 'haml', ['>= 2.0.0']
148
+ s.add_dependency 'dm-core', ['>= 0.9.5']
149
+ s.add_dependency 'dm-validations', ['>= 0.9.5']
150
+ s.add_dependency 'dm-types', ['>= 0.9.5']
151
+ s.add_dependency 'dm-timestamps', ['>= 0.9.5']
152
+ s.add_dependency 'dm-aggregates', ['>= 0.9.5']
153
+ s.add_dependency 'dm-migrations', ['>= 0.9.5']
154
+ s.add_dependency 'data_objects', ['>= 0.9.5']
155
+ s.add_dependency 'do_sqlite3', ['>= 0.9.5']
156
+ s.add_dependency 'json'
157
+ s.add_dependency 'foca-sinatra-diddies', ['>= 0.0.2']
158
+ s.add_dependency 'thor'
159
+ s.add_dependency 'uuidtools' # required by dm-types
160
+ s.add_dependency 'bcrypt-ruby' # required by dm-types
161
+ end
162
+ end
163
+ rescue LoadError
164
+ end
165
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ major: 0
3
+ patch: 8
4
+ minor: 1
data/app.rb ADDED
@@ -0,0 +1,138 @@
1
+ require "sinatra"
2
+
3
+ require File.dirname(__FILE__) + "/lib/integrity"
4
+ require "integrity/helpers"
5
+
6
+ set :root, Integrity.root
7
+ set :public, Integrity.root / "public"
8
+ set :views, Integrity.root / "views"
9
+
10
+ enable :sessions
11
+
12
+ include Integrity
13
+
14
+ configure :development do
15
+ config = Integrity.root / "config" / "config.yml"
16
+ Integrity.config = config if File.exists? config
17
+ end
18
+
19
+ configure do
20
+ Integrity.new
21
+ end
22
+
23
+ not_found do
24
+ status 404
25
+ show :not_found, :title => "lost, are we?"
26
+ end
27
+
28
+ error do
29
+ @error = request.env['sinatra.error']
30
+ status 500
31
+ show :error, :title => "something has gone terribly wrong"
32
+ end
33
+
34
+ before do
35
+ # The browser only sends http auth data for requests that are explicitly
36
+ # required to do so. This way we get the real values of +#logged_in?+ and
37
+ # +#current_user+
38
+ login_required if session[:user]
39
+ end
40
+
41
+ get "/" do
42
+ @projects = Project.only_public_unless(authorized?)
43
+ show :home, :title => "projects"
44
+ end
45
+
46
+ get "/login" do
47
+ login_required
48
+ session[:user] = current_user
49
+ redirect root_url
50
+ end
51
+
52
+ get "/new" do
53
+ login_required
54
+
55
+ @project = Project.new
56
+ show :new, :title => ["projects", "new project"]
57
+ end
58
+
59
+ post "/" do
60
+ login_required
61
+
62
+ @project = Project.new(params[:project_data])
63
+ if @project.save
64
+ @project.enable_notifiers(params["enabled_notifiers[]"], params["notifiers"])
65
+ redirect project_url(@project)
66
+ else
67
+ show :new, :title => ["projects", "new project"]
68
+ end
69
+ end
70
+
71
+ get "/:project" do
72
+ login_required unless current_project.public?
73
+ show :project, :title => ["projects", current_project.name]
74
+ end
75
+
76
+ get "/:project.atom" do
77
+ login_required unless current_project.public?
78
+ response["Content-Type"] = "application/rss+xml; charset=utf-8"
79
+ builder :project
80
+ end
81
+
82
+ put "/:project" do
83
+ login_required
84
+
85
+ if current_project.update_attributes(params[:project_data])
86
+ current_project.enable_notifiers(params["enabled_notifiers"], params["notifiers"])
87
+ redirect project_url(current_project)
88
+ else
89
+ show :new, :title => ["projects", current_project.permalink, "edit"]
90
+ end
91
+ end
92
+
93
+ delete "/:project" do
94
+ login_required
95
+
96
+ current_project.destroy
97
+ redirect root_url
98
+ end
99
+
100
+ get "/:project/edit" do
101
+ login_required
102
+
103
+ show :new, :title => ["projects", current_project.permalink, "edit"]
104
+ end
105
+
106
+ post "/:project/push" do
107
+ login_required
108
+
109
+ content_type "text/plain"
110
+
111
+ begin
112
+ current_project.push(params[:payload])
113
+ "Thanks, build started."
114
+ rescue JSON::ParserError => exception
115
+ throw :halt, [422, exception.to_s]
116
+ end
117
+ end
118
+
119
+ post "/:project/builds" do
120
+ login_required
121
+
122
+ current_project.build
123
+ redirect project_url(@project)
124
+ end
125
+
126
+ get "/:project/builds/:build" do
127
+ login_required unless current_project.public?
128
+ show :build, :title => ["projects", current_project.permalink, current_build.short_commit_identifier]
129
+ end
130
+
131
+ get "/integrity.css" do
132
+ response["Content-Type"] = "text/css; charset=utf-8"
133
+ sass :integrity
134
+ end
135
+
136
+ helpers do
137
+ include Helpers
138
+ end
data/bin/integrity ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + "/../lib/integrity/installer"
3
+
4
+ Integrity::Installer.start
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "integrity"
4
+
5
+ # If you want to add any notifiers, install the gems and then require them here
6
+ # For example, to enable the Email notifier: install the gem (from github:
7
+ #
8
+ # sudo gem install -s http://gems.github.com foca-integrity-email
9
+ #
10
+ # And then uncomment the following line:
11
+ #
12
+ # require "notifier/email"
13
+
14
+ # Load integrity's configuration.
15
+ Integrity.config = File.expand_path("./config.yml")
16
+
17
+ #######################################################################
18
+ ## ##
19
+ ## == DON'T EDIT ANYTHING BELOW UNLESS YOU KNOW WHAT YOU'RE DOING == ##
20
+ ## ##
21
+ #######################################################################
22
+ require Integrity.root / "app"
23
+
24
+ set :environment, ENV["RACK_ENV"] || :production
25
+ set :public, Integrity.root / "public"
26
+ set :views, Integrity.root / "views"
27
+ set :port, 8910
28
+ disable :run, :reload
29
+
30
+ use Rack::CommonLogger, Integrity.logger if Integrity.config[:log_debug_info]
31
+ run Sinatra::Application
@@ -0,0 +1,38 @@
1
+ # Domain where integrity will be running from. This is used to have
2
+ # nice URLs in your notifications.
3
+ # For example:
4
+ # http://builder.integrityapp.com
5
+ :base_uri: http://integrity.domain.tld
6
+
7
+ # This should be a complete connection string to your database. For example
8
+ # `mysql://user@localhost/integrity` (you need an `integrity` db created in
9
+ # localhost, of course).
10
+ :database_uri: sqlite3:///var/integrity.db
11
+
12
+ # This is where your project's code will be checked out to. Make sure it's
13
+ # writable by the user that runs Integrity.
14
+ :export_directory: /path/to/scm/exports
15
+
16
+ # Path to the integrity log file
17
+ :log: /var/log/integrity.log
18
+
19
+ # Enable/Disable debug logging. Turning this on will log queries made to the
20
+ # database and web requests (if using the provided rackup file)
21
+ :log_debug_info: false
22
+
23
+ # Enable or disable HTTP authentication for the app. BE AWARE that if you
24
+ # disable this anyone can delete and alter projects, so do it only if your
25
+ # app is running in a controlled environment (ie, behind your company's
26
+ # firewall.)
27
+ :use_basic_auth: false
28
+
29
+ # When `use_basic_auth` is true, the admin's username for HTTP authentication.
30
+ :admin_username: username
31
+
32
+ # When `use_basic_auth` is true, the admin's password. Usually saved as a
33
+ # SHA1 hash. See the next option.
34
+ :admin_password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
35
+
36
+ # If this is true, then whenever we authenticate the admin user, will hash
37
+ # it using SHA1. If not, we'll assume the provided password is in plain text.
38
+ :hash_admin_password: true