foca-integrity 0.1.9.1 → 0.1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/.gitignore +12 -0
  2. data/CHANGES +28 -0
  3. data/README.markdown +6 -0
  4. data/Rakefile +44 -83
  5. data/config/heroku/.gems +0 -3
  6. data/config/heroku/integrity-config.rb +4 -1
  7. data/integrity.gemspec +18 -6
  8. data/lib/integrity.rb +9 -5
  9. data/lib/integrity/app.rb +8 -8
  10. data/lib/integrity/build.rb +14 -7
  11. data/lib/integrity/commit.rb +0 -8
  12. data/lib/integrity/helpers/authorization.rb +1 -1
  13. data/lib/integrity/helpers/breadcrumbs.rb +1 -1
  14. data/lib/integrity/helpers/rendering.rb +8 -2
  15. data/lib/integrity/helpers/urls.rb +33 -23
  16. data/lib/integrity/installer.rb +18 -17
  17. data/lib/integrity/notifier/base.rb +12 -3
  18. data/lib/integrity/project.rb +6 -6
  19. data/lib/integrity/project_builder.rb +35 -35
  20. data/test/acceptance/api_test.rb +1 -1
  21. data/test/acceptance/browse_project_builds_test.rb +1 -1
  22. data/test/acceptance/browse_project_test.rb +1 -1
  23. data/test/acceptance/build_notifications_test.rb +1 -1
  24. data/test/acceptance/create_project_test.rb +1 -1
  25. data/test/acceptance/delete_project_test.rb +1 -1
  26. data/test/acceptance/edit_project_test.rb +1 -1
  27. data/test/acceptance/error_page_test.rb +1 -1
  28. data/test/acceptance/installer_test.rb +2 -6
  29. data/test/acceptance/manual_build_project_test.rb +1 -1
  30. data/test/acceptance/not_found_page_test.rb +29 -0
  31. data/test/acceptance/notifier_test.rb +1 -1
  32. data/test/acceptance/project_syndication_test.rb +1 -1
  33. data/test/acceptance/stylesheet_test.rb +10 -2
  34. data/test/acceptance/unauthorized_page_test.rb +20 -0
  35. data/test/helpers.rb +20 -7
  36. data/test/helpers/acceptance.rb +1 -0
  37. data/test/unit/build_test.rb +33 -0
  38. data/test/unit/commit_test.rb +0 -21
  39. data/test/unit/helpers_test.rb +67 -20
  40. data/test/unit/integrity_test.rb +23 -6
  41. data/test/unit/migrations_test.rb +2 -2
  42. data/test/unit/notifier_test.rb +5 -0
  43. data/test/unit/project_builder_test.rb +8 -1
  44. data/test/unit/project_test.rb +7 -0
  45. data/views/home.haml +2 -2
  46. data/views/layout.haml +6 -5
  47. data/views/new.haml +1 -1
  48. data/views/not_found.haml +2 -2
  49. data/views/unauthorized.haml +4 -4
  50. metadata +105 -6
  51. data/test/acceptance/helpers.rb +0 -2
  52. data/vendor/sinatra-ditties/README.rdoc +0 -3
  53. data/vendor/sinatra-ditties/lib/sinatra/ditties.rb +0 -12
  54. data/vendor/sinatra-ditties/lib/sinatra/ditties/authorization.rb +0 -61
  55. data/vendor/sinatra-ditties/lib/sinatra/ditties/mailer.rb +0 -146
@@ -1,4 +1,4 @@
1
- require "sinatra/ditties"
1
+ require "sinatra/authorization"
2
2
 
3
3
  module Integrity
4
4
  module Helpers
@@ -2,7 +2,7 @@ module Integrity
2
2
  module Helpers
3
3
  module Breadcrumbs
4
4
  def pages
5
- @pages ||= [["projects", "/"], ["new project", "/new"]]
5
+ @pages ||= [["projects", root_path], ["new project", root_path("/new")]]
6
6
  end
7
7
 
8
8
  def breadcrumbs(*crumbs)
@@ -1,9 +1,15 @@
1
1
  module Integrity
2
2
  module Helpers
3
3
  module Rendering
4
+ def stylesheets(*sheets)
5
+ sheets.each { |sheet|
6
+ haml_tag(:link, :href => root_path("/#{sheet}.css"),
7
+ :type => "text/css", :rel => "stylesheet")
8
+ }
9
+ end
10
+
4
11
  def stylesheet_hash
5
- @_hash ||= Digest::MD5.file(
6
- options.views + "/integrity.sass").tap { |file| file.hexdigest }
12
+ @_hash ||= Digest::MD5.file(options.views + "/integrity.sass").hexdigest
7
13
  end
8
14
 
9
15
  def show(view, options={})
@@ -1,49 +1,59 @@
1
1
  module Integrity
2
2
  module Helpers
3
3
  module Urls
4
- def url(path)
5
- Addressable::URI.parse(request.url).join(path).to_s
6
- end
7
-
8
4
  def root_url
9
- url("/")
5
+ @url ||= Addressable::URI.parse(base_url)
10
6
  end
11
7
 
12
- def project_path(project, *path)
13
- "/" << [project.permalink, *path].join("/")
8
+ def root_path(path="")
9
+ url(path).path
14
10
  end
15
11
 
16
12
  def project_url(project, *path)
17
- url project_path(project, *path)
13
+ url("/" << [project.permalink, *path].flatten.join("/"))
18
14
  end
19
15
 
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
16
+ def project_path(project, *path)
17
+ project_url(project, path).path
18
+ end
19
+
20
+ def commit_url(commit)
21
+ project_url(commit.project, "commits", commit.identifier)
28
22
  end
29
23
 
30
24
  def commit_path(commit, *path)
31
- project_path(commit.project, "commits", commit.identifier, *path)
25
+ commit_url(commit).path
32
26
  end
33
27
 
34
28
  def build_path(build, *path)
35
- warn "#build_path is deprecated, use #commit_path instead"
29
+ warn "#build_path is deprecated, use #commit_path instead (#{caller[0]})"
36
30
  commit_path build.commit, *path
37
31
  end
38
32
 
39
- def commit_url(commit)
40
- url commit_path(commit)
41
- end
42
-
43
33
  def build_url(build)
44
- warn "#build_url is deprecated, use #commit_url instead"
34
+ warn "#build_url is deprecated, use #commit_url instead (#{caller[0]})"
45
35
  commit_url build.commit
46
36
  end
37
+
38
+ def push_url_for(project)
39
+ Addressable::URI.parse(project_url(project, "push")).tap do |url|
40
+ if Integrity.config[:use_basic_auth]
41
+ url.user = Integrity.config[:admin_username]
42
+ url.password = Integrity.config[:hash_admin_password] ?
43
+ "<password>" : Integrity.config[:admin_password]
44
+ end
45
+ end.to_s
46
+ end
47
+
48
+ private
49
+ def url(path="")
50
+ root_url.dup.tap { |url| url.path = root_url.path + path }
51
+ end
52
+
53
+ def base_url
54
+ Integrity.config[:base_uri] || ((respond_to?(:request) &&
55
+ request.respond_to?(:url)) ? request.url : fail("set base_uri"))
56
+ end
47
57
  end
48
58
  end
49
59
  end
@@ -16,20 +16,13 @@ module Integrity
16
16
 
17
17
  if options[:heroku]
18
18
  cp_r Pathname(__FILE__).join("../../../config/heroku"), root
19
- puts <<EOF
20
- Your Integrity install is ready to be deployed onto Heroku. Next steps:
21
-
22
- 1. git init && git add . && git commit -am "Initial import"
23
- 2. heroku create
24
- 3. git push heroku master
25
- 4. heroku rake db:migrate
26
- EOF
19
+ puts post_heroku_install_message
27
20
  else
28
21
  create_dir_structure
29
22
  copy_template_files
30
23
  edit_template_files
31
24
  migrate_db(root.join("config.yml"))
32
- after_setup_message
25
+ puts post_install_message
33
26
  end
34
27
  end
35
28
 
@@ -50,11 +43,8 @@ EOF
50
43
  require "thin"
51
44
  require "do_sqlite3"
52
45
 
53
- if File.file?(options[:config].to_s)
54
- Integrity.new(options[:config])
55
- else
56
- DataMapper.setup(:default, "sqlite3::memory:")
57
- end
46
+ File.file?(options[:config].to_s) ?
47
+ Integrity.new(options[:config]) : Integrity.new
58
48
 
59
49
  DataMapper.auto_migrate!
60
50
 
@@ -104,8 +94,19 @@ EOF
104
94
  File.open(root / "thin.yml", 'w') { |f| f.puts config }
105
95
  end
106
96
 
107
- def after_setup_message
108
- puts <<EOF
97
+ def post_heroku_install_message
98
+ <<EOF
99
+ Your Integrity install is ready to be deployed onto Heroku. Next steps:
100
+
101
+ 1. git init && git add . && git commit -am "Initial import"
102
+ 2. heroku create
103
+ 3. git push heroku master
104
+ 4. heroku rake db:migrate
105
+ EOF
106
+ end
107
+
108
+ def post_install_message
109
+ <<EOF
109
110
  Awesome! Integrity was installed successfully!
110
111
 
111
112
  If you want to enable notifiers, install the gems and then require them
@@ -113,7 +114,7 @@ in #{root}/config.ru
113
114
 
114
115
  For example:
115
116
 
116
- sudo gem install -s http://gems.github.com foca-integrity-email)
117
+ sudo gem install -s http://gems.github.com foca-integrity-email
117
118
 
118
119
  And then in #{root}/config.ru add:
119
120
 
@@ -2,7 +2,11 @@ module Integrity
2
2
  class Notifier
3
3
  class Base
4
4
  def self.notify_of_build(build, config)
5
- Timeout.timeout(8) { new(build, config).deliver! }
5
+ Integrity.log "Notifying of build #{build.commit.short_identifier} using the #{self.class} notifier"
6
+ Timeout.timeout(8) { new(build.commit, config).deliver! }
7
+ rescue Timeout::Error
8
+ Integrity.log "#{notifier.name} notifier timed out"
9
+ false
6
10
  end
7
11
 
8
12
  def self.to_haml
@@ -17,7 +21,7 @@ module Integrity
17
21
  end
18
22
 
19
23
  def build
20
- warn "Notifier::Base#build is deprecated, use Notifier::Base#commit instead"
24
+ warn "Notifier::Base#build is deprecated, use Notifier::Base#commit instead (#{caller[0]})"
21
25
  commit
22
26
  end
23
27
 
@@ -50,6 +54,11 @@ EOM
50
54
  Integrity.config[:base_uri] / commit.project.permalink / "commits" / commit.identifier
51
55
  end
52
56
 
57
+ def build_url
58
+ warn "Notifier::Base#build_url is deprecated, use Notifier::Base#commit_url instead (#{caller[0]})"
59
+ commit_url
60
+ end
61
+
53
62
  private
54
63
 
55
64
  def stripped_commit_output
@@ -57,7 +66,7 @@ EOM
57
66
  end
58
67
 
59
68
  def stripped_build_output
60
- warn "Notifier::Base#stripped_build_output is deprecated, use Notifier::base#stripped_commit_output instead"
69
+ warn "Notifier::Base#stripped_build_output is deprecated, use Notifier::base#stripped_commit_output instead (#{caller[0]})"
61
70
  stripped_commit_output
62
71
  end
63
72
  end
@@ -17,7 +17,7 @@ module Integrity
17
17
  has n, :notifiers, :class_name => "Integrity::Notifier"
18
18
 
19
19
  before :save, :set_permalink
20
- before :destroy, :delete_code
20
+ before :destroy, :delete_working_directory
21
21
 
22
22
  validates_is_unique :name
23
23
 
@@ -32,7 +32,7 @@ module Integrity
32
32
  def build(commit_identifier="HEAD")
33
33
  commit_identifier = head_of_remote_repo if commit_identifier == "HEAD"
34
34
  commit = find_or_create_commit_with_identifier(commit_identifier)
35
- commit.queue_build
35
+ Build.queue(commit)
36
36
  end
37
37
 
38
38
  def push(payload)
@@ -57,7 +57,7 @@ module Integrity
57
57
  end
58
58
 
59
59
  def last_build
60
- warn "Project#last_build is deprecated, use Project#last_commit"
60
+ warn "Project#last_build is deprecated, use Project#last_commit (#{caller[0]})"
61
61
  last_commit
62
62
  end
63
63
 
@@ -66,7 +66,7 @@ module Integrity
66
66
  end
67
67
 
68
68
  def previous_builds
69
- warn "Project#previous_builds is deprecated, use Project#previous_commits"
69
+ warn "Project#previous_builds is deprecated, use Project#previous_commits (#{caller[0]})"
70
70
  previous_commits
71
71
  end
72
72
 
@@ -131,9 +131,9 @@ module Integrity
131
131
  gsub(/-*$/, "")
132
132
  end
133
133
 
134
- def delete_code
134
+ def delete_working_directory
135
135
  commits.all(:project_id => id).destroy!
136
- ProjectBuilder.new(self).delete_code
136
+ ProjectBuilder.delete_working_directory(self)
137
137
  rescue SCM::SCMUnknownError => error
138
138
  Integrity.log "Problem while trying to deleting code: #{error}"
139
139
  end
@@ -1,24 +1,45 @@
1
+ require "forwardable"
2
+
1
3
  module Integrity
2
4
  class ProjectBuilder
5
+ extend Forwardable
6
+
7
+ attr_accessor :project, :scm
8
+ def_delegators :project, :name, :uri, :command, :branch
9
+
10
+ def self.build(commit)
11
+ new(commit.project).build(commit)
12
+ end
13
+
14
+ def self.delete_working_directory(project)
15
+ new(project).delete_code
16
+ end
17
+
3
18
  def initialize(project)
4
19
  @project = project
5
- @uri = project.uri
6
- @build_script = project.command
7
- @branch = project.branch
8
- @scm = SCM.new(@uri, @branch, export_directory)
20
+ @scm = SCM.new(uri, branch, export_directory)
9
21
  end
10
22
 
11
23
  def build(commit)
12
- @commit = commit
13
- @build = commit.build
14
- @build.start!
15
- Integrity.log "Building #{commit.identifier} (#{@branch}) of #{@project.name} in #{export_directory} using #{@scm.name}"
16
- @scm.with_revision(commit.identifier) { run_build_script }
17
- @build
24
+ build = commit.build
25
+ build.start!
26
+
27
+ Integrity.log "Building #{commit.identifier} (#{branch}) of #{name} in" +
28
+ "#{export_directory} using #{scm.name}"
29
+
30
+ scm.with_revision(commit.identifier) do
31
+ Integrity.log "Running `#{command}` in #{scm.working_directory}"
32
+
33
+ IO.popen("(cd #{scm.working_directory} && #{command}) 2>&1", "r") {
34
+ |output| build.output = output.read }
35
+ build.successful = $?.success?
36
+ end
37
+
38
+ build
18
39
  ensure
19
- @build.complete!
20
- @commit.update_attributes(@scm.info(commit.identifier))
21
- send_notifications
40
+ build.complete!
41
+ commit.update_attributes(scm.info(commit.identifier) || {})
42
+ project.notifiers.each { |notifier| notifier.notify_of_build(build) }
22
43
  end
23
44
 
24
45
  def delete_code
@@ -28,29 +49,8 @@ module Integrity
28
49
  end
29
50
 
30
51
  private
31
- def send_notifications
32
- @project.notifiers.each do |notifier|
33
- begin
34
- Integrity.log "Notifying of build #{@commit.short_identifier} using the #{notifier.name} notifier"
35
- notifier.notify_of_build @commit
36
- rescue Timeout::Error
37
- Integrity.log "#{notifier.name} notifier timed out"
38
- next
39
- end
40
- end
41
- end
42
-
43
52
  def export_directory
44
- Integrity.config[:export_directory] / "#{SCM.working_tree_path(@uri)}-#{@branch}"
45
- end
46
-
47
- def run_build_script
48
- Integrity.log "Running `#{@build_script}` in #{@scm.working_directory}"
49
-
50
- IO.popen "(cd #{@scm.working_directory} && #{@build_script}) 2>&1", "r" do |pipe|
51
- @build.output = pipe.read
52
- end
53
- @build.successful = $?.success?
53
+ Integrity.config[:export_directory] / "#{SCM.working_tree_path(uri)}-#{branch}"
54
54
  end
55
55
  end
56
56
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class ApiTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOF
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class BrowseProjectBuildsTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class BrowsePublicProjectsTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
  require "helpers/acceptance/textfile_notifier"
3
3
 
4
4
  class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class CreateProjectTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class DeleteProjectTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class EditProjectTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class ErrorPageTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
  require "integrity/installer"
3
3
 
4
4
  class InstallerTest < Test::Unit::AcceptanceTestCase
@@ -65,11 +65,7 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
65
65
  scenario "Installing Integrity for Heroku" do
66
66
  message = install("--heroku")
67
67
 
68
- gemifest = root.join(".gems").read
69
- assert gemifest.include?("mailfactory")
70
- assert gemifest.include?("tlsmail")
71
- assert gemifest.include?("foca-sinatra-ditties")
72
- assert gemifest.include?("integrity")
68
+ assert_equal "integrity --version 0.1.9.0", root.join(".gems").read.chomp
73
69
 
74
70
  assert root.join("Rakefile").file?
75
71
  assert root.join("integrity-config.rb").file?
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/helpers"
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
 
3
3
  class ManualBuildProjectTest < Test::Unit::AcceptanceTestCase
4
4
  story <<-EOS
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class NotFoundPageTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As an visitor,
6
+ I want to be shown a friendly four oh four
7
+ So that I DON'T HAVE TO THINK.
8
+ EOS
9
+
10
+ scenario "chilling on some Integrity instance found via The Holy Hub" do
11
+ project = Project.gen
12
+
13
+ visit "/42"
14
+ assert_equal 404, response_code
15
+
16
+ click_link "list of projects"
17
+ assert_contain(project.name)
18
+
19
+ visit "/42"
20
+
21
+ click_link "the projects list"
22
+ assert_contain(project.name)
23
+
24
+ visit "/42"
25
+
26
+ click_link "back from whence you came"
27
+ assert_contain("Add a new project")
28
+ end
29
+ end