alphasights-integrity 0.1.9.8 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +0 -1
  2. data/AUTHORS +35 -0
  3. data/CHANGES +21 -3
  4. data/LICENSE +20 -0
  5. data/README.md +10 -52
  6. data/config/config.sample.yml +4 -0
  7. data/config/heroku/.gems +1 -1
  8. data/config/heroku/integrity-config.rb +1 -0
  9. data/integrity.gemspec +6 -11
  10. data/lib/integrity.rb +4 -4
  11. data/lib/integrity/app.rb +1 -1
  12. data/lib/integrity/build.rb +8 -18
  13. data/lib/integrity/commit.rb +13 -8
  14. data/lib/integrity/helpers/pretty_output.rb +8 -0
  15. data/lib/integrity/helpers/urls.rb +3 -3
  16. data/lib/integrity/installer.rb +20 -11
  17. data/lib/integrity/migrations.rb +43 -13
  18. data/lib/integrity/notifier.rb +1 -1
  19. data/lib/integrity/notifier/base.rb +2 -2
  20. data/lib/integrity/notifier/test/fixtures.rb +12 -6
  21. data/lib/integrity/project.rb +34 -38
  22. data/lib/integrity/project/push.rb +4 -5
  23. data/test/acceptance/api_test.rb +1 -1
  24. data/test/acceptance/browse_project_test.rb +12 -6
  25. data/test/acceptance/build_notifications_test.rb +26 -2
  26. data/test/acceptance/installer_test.rb +1 -1
  27. data/test/acceptance/manual_build_project_test.rb +2 -2
  28. data/test/acceptance/notifier_test_test.rb +37 -0
  29. data/test/acceptance/stylesheet_test.rb +2 -1
  30. data/test/helpers.rb +3 -2
  31. data/test/unit/build_test.rb +11 -46
  32. data/test/unit/commit_test.rb +37 -28
  33. data/test/unit/helpers_test.rb +16 -0
  34. data/test/unit/migrations_test.rb +6 -4
  35. data/test/unit/project_test.rb +64 -95
  36. data/views/_commit_info.haml +6 -10
  37. data/views/home.haml +3 -2
  38. data/views/integrity.sass +24 -4
  39. data/views/project.haml +5 -4
  40. metadata +6 -20
  41. data/lib/integrity/helpers/gravatar.rb +0 -16
  42. data/lib/integrity/project_builder.rb +0 -56
  43. data/lib/integrity/scm.rb +0 -19
  44. data/lib/integrity/scm/git.rb +0 -84
  45. data/lib/integrity/scm/git/uri.rb +0 -57
  46. data/test/unit/project_builder_test.rb +0 -118
  47. data/test/unit/scm_test.rb +0 -54
@@ -6,6 +6,11 @@ module Integrity
6
6
  class Installer < Thor
7
7
  include FileUtils
8
8
 
9
+ def self.database_path
10
+ File.join(ENV["HOME"], ".integrity.sqlite3")
11
+ end
12
+ private_class_method :database_path
13
+
9
14
  desc "install [PATH]",
10
15
  "Copy template files to PATH for desired deployement strategy
11
16
  (either Thin, Passenger or Heroku). Next, go there and edit them."
@@ -37,22 +42,25 @@ module Integrity
37
42
  end
38
43
 
39
44
  desc "launch [CONFIG]",
40
- "Launch Integrity real quick."
41
- method_options :config => :optional, :port => 4567
45
+ "Launch Integrity real quick. Database is saved in #{database_path}."
46
+ method_options :config => :optional, :port => :optional
42
47
  def launch
43
48
  require "thin"
44
49
  require "do_sqlite3"
45
50
 
46
- File.file?(options[:config].to_s) ?
47
- Integrity.new(options[:config]) : Integrity.new
48
- Integrity.config[:base_uri] = "http://0.0.0.0:#{options[:port]}"
51
+ port = options[:port] || 4567
52
+
53
+ config = { :database_uri => "sqlite3://#{ENV["HOME"]}/.integrity.db",
54
+ :base_uri => "http://0.0.0.0:#{options[:port]}",
55
+ :export_directory => "/tmp/integrity-exports" }
56
+ config.merge!(YAML.load_file(options[:config])) if options[:config]
49
57
 
50
- DataMapper.auto_migrate!
58
+ migrate_db(config)
51
59
 
52
- Thin::Server.start("0.0.0.0", options[:port], Integrity::App)
60
+ Thin::Server.start("0.0.0.0", port, Integrity::App)
53
61
  rescue LoadError => boom
54
- missing_dependency = boom.message.split("--").last.lstrip
55
- puts "Please install #{missing_dependency} to launch Integrity"
62
+ $stderr << "Make sure thin and do_sqlite3 are insatalled\n\n"
63
+ raise
56
64
  end
57
65
 
58
66
  private
@@ -101,8 +109,9 @@ Your Integrity install is ready to be deployed onto Heroku. Next steps:
101
109
 
102
110
  1. git init && git add . && git commit -am "Initial import"
103
111
  2. heroku create
104
- 3. git push heroku master
105
- 4. heroku rake db:migrate
112
+ 3. Add heroku-given domain as :base_uri in integrity-config.rb
113
+ 4. git push heroku master
114
+ 5. heroku rake db:migrate
106
115
  EOF
107
116
  end
108
117
 
@@ -39,9 +39,9 @@ module Integrity
39
39
  column :id, Integer, :serial => true
40
40
  column :name, String, :nullable => false
41
41
  column :permalink, String
42
- column :uri, Text, :nullable => false
42
+ column :uri, URI, :nullable => false
43
43
  column :branch, String, :nullable => false, :default => "master"
44
- column :command, Text, :nullable => false, :default => "rake"
44
+ column :command, String, :nullable => false, :default => "rake"
45
45
  column :public, Boolean, :default => true
46
46
  column :building, Boolean, :default => false
47
47
  column :created_at, DateTime
@@ -83,12 +83,12 @@ module Integrity
83
83
 
84
84
  create_table :integrity_commits do
85
85
  column :id, Integer, :serial => true
86
- column :identifier, String, :size => 40, :nullable => false
87
- column :message, Text, :nullable => true
88
- column :author, String, :nullable => true, :length => 255
86
+ column :identifier, String, :nullable => false
87
+ column :message, String, :nullable => false, :length => 255
88
+ column :author, String, :nullable => false, :length => 255
89
89
  column :committed_at, DateTime, :nullable => false
90
- column :created_at, DateTime
91
- column :updated_at, DateTime
90
+ column :created_at, DateTime
91
+ column :updated_at, DateTime
92
92
 
93
93
  column :project_id, Integer
94
94
  end
@@ -124,7 +124,6 @@ module Integrity
124
124
  commit = Commit.create(:identifier => build.commit_identifier,
125
125
  :message => build.commit_metadata[:message],
126
126
  :author => build.commit_metadata[:author],
127
- :url => build.commit_metadata[:url],
128
127
  :committed_at => build.commit_metadata[:date],
129
128
  :project_id => build.project_id)
130
129
  end
@@ -149,14 +148,45 @@ module Integrity
149
148
  end
150
149
  end
151
150
 
152
- migration 4, :add_url_to_commits do
151
+ migration 4, :add_commit_uri_column do
152
+ up do
153
+ modify_table(:integrity_commits) { add_column :uri, URI }
154
+ end
155
+
156
+ down do
157
+ #modify_table(:integrity_commits) { add_column :changeset, String }
158
+ end
159
+ end
160
+ end
161
+
162
+ migration 5, :nil_commit_metadata do
153
163
  up do
154
- modify_table(:integrity_commits) { add_column :url, Text }
164
+ all_commits = Commit.all.collect { |c| c.dup }
165
+ drop_table :integrity_commits
166
+
167
+ create_table :integrity_commits do
168
+ column :id, Integer, :serial => true
169
+ column :identifier, String, :nullable => false
170
+ column :message, String, :nullable => true, :length => 255
171
+ column :author, String, :nullable => true, :length => 255
172
+ column :committed_at, DateTime, :nullable => false
173
+ column :created_at, DateTime
174
+ column :updated_at, DateTime
175
+
176
+ column :project_id, Integer
177
+ end
178
+
179
+ all_commits.each { |commit| Commit.create(commit.attributes) }
155
180
  end
181
+ end
156
182
 
157
- down do
158
- #modify_table(:integrity_commits) { drop_column :url }
183
+ =begin
184
+ TODO: drop the :building column of the project table
185
+
186
+ migration 5, :remove_building_column do
187
+ up do
188
+ modify_table(:integrity_projects) { drop_column :building }
159
189
  end
160
190
  end
161
- end
191
+ =end
162
192
  end
@@ -33,7 +33,7 @@ module Integrity
33
33
  private_class_method :valid?
34
34
 
35
35
  def notify_of_build(build)
36
- to_const.notify_of_build(build, config)
36
+ to_const.notify_of_build(build, config) if to_const
37
37
  end
38
38
 
39
39
  private
@@ -2,10 +2,10 @@ module Integrity
2
2
  class Notifier
3
3
  class Base
4
4
  def self.notify_of_build(build, config)
5
- Integrity.log "Notifying of build #{build.commit.short_identifier} using the #{self} notifier"
5
+ Integrity.log "Notifying of build #{build.commit.short_identifier} using the #{to_s} notifier"
6
6
  Timeout.timeout(8) { new(build.commit, config).deliver! }
7
7
  rescue Timeout::Error
8
- Integrity.log "#{self} notifier timed out"
8
+ Integrity.log "#{notifier.name} notifier timed out"
9
9
  false
10
10
  end
11
11
 
@@ -24,8 +24,7 @@ Integrity::Project.fixture do
24
24
  :uri => "git://github.com/#{/\w+/.gen}/#{name}.git",
25
25
  :branch => ["master", "test-refactoring", "lh-34"].pick,
26
26
  :command => ["rake", "make", "ant -buildfile test.xml"].pick,
27
- :public => [true, false].pick,
28
- :building => [true, false].pick }
27
+ :public => [true, false].pick }
29
28
  end
30
29
 
31
30
  Integrity::Project.fixture(:integrity) do
@@ -33,8 +32,7 @@ Integrity::Project.fixture(:integrity) do
33
32
  :uri => "git://github.com/foca/integrity.git",
34
33
  :branch => "master",
35
34
  :command => "rake",
36
- :public => true,
37
- :building => false }
35
+ :public => true }
38
36
  end
39
37
 
40
38
  Integrity::Project.fixture(:my_test_project) do
@@ -42,8 +40,7 @@ Integrity::Project.fixture(:my_test_project) do
42
40
  :uri => File.dirname(__FILE__) + "/../../",
43
41
  :branch => "master",
44
42
  :command => "./test",
45
- :public => true,
46
- :building => false }
43
+ :public => true }
47
44
  end
48
45
 
49
46
  Integrity::Commit.fixture do
@@ -68,6 +65,10 @@ Integrity::Commit.fixture(:pending) do
68
65
  Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:pending))
69
66
  end
70
67
 
68
+ Integrity::Commit.fixture(:building) do
69
+ Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:building))
70
+ end
71
+
71
72
  Integrity::Build.fixture do
72
73
  commit = Integrity::Commit.first || Integrity::Commit.gen
73
74
 
@@ -91,6 +92,11 @@ Integrity::Build.fixture(:pending) do
91
92
  Integrity::Build.generate_attributes.update(:successful => nil, :started_at => nil, :completed_at => nil)
92
93
  end
93
94
 
95
+ Integrity::Build.fixture(:building) do
96
+ Integrity::Build.generate_attributes.update(:completed_at => nil,
97
+ :successful => nil, :output => nil)
98
+ end
99
+
94
100
  Integrity::Notifier.fixture(:irc) do
95
101
  create_notifier! "IRC"
96
102
 
@@ -4,33 +4,50 @@ require "integrity/project/push"
4
4
  module Integrity
5
5
  class Project
6
6
  include DataMapper::Resource
7
+ include Bob::Buildable
7
8
  include Notifiers, Push
8
9
 
9
- property :id, Integer, :serial => true
10
+ property :id, Serial
10
11
  property :name, String, :nullable => false
11
12
  property :permalink, String
12
13
  property :uri, URI, :nullable => false, :length => 255
13
14
  property :branch, String, :nullable => false, :default => "master"
14
- property :command, Text, :nullable => false, :default => "rake"
15
+ property :command, String, :nullable => false, :length => 255, :default => "rake"
15
16
  property :public, Boolean, :default => true
16
- property :building, Boolean, :default => false
17
- property :created_at, DateTime
18
- property :updated_at, DateTime
19
17
 
20
- has n, :commits, :class_name => "Integrity::Commit",
21
- :order => [:committed_at.desc]
18
+ timestamps :at
19
+
20
+ default_scope(:default).update(:order => [:name.asc])
21
+
22
+ has n, :commits, :class_name => "Integrity::Commit"
22
23
  has n, :notifiers, :class_name => "Integrity::Notifier"
23
24
 
24
25
  before :save, :set_permalink
25
- before :destroy, :delete_working_directory
26
+
27
+ before :destroy do
28
+ commits.destroy!
29
+ end
26
30
 
27
31
  validates_is_unique :name
28
32
 
29
- def build(commit_identifier="HEAD")
30
- commit_identifier = head_of_remote_repo if commit_identifier == "HEAD"
31
- commit = find_or_create_commit_with_identifier(commit_identifier)
33
+ def kind
34
+ :git
35
+ end
36
+
37
+ alias_method :build_script, :command
38
+
39
+ def start_building(commit_id, commit_info)
40
+ @commit = commits.first_or_create({:identifier => commit_id},
41
+ commit_info.update(:project_id => id))
42
+ @build = Build.new(:started_at => Time.now)
43
+ @commit.update_attributes(:build => @build)
44
+ end
32
45
 
33
- Build.queue(commit)
46
+ def finish_building(commit_id, status, output)
47
+ @build.update_attributes(
48
+ :successful => status, :output => output,
49
+ :completed_at => Time.now) if @build
50
+ enabled_notifiers.each { |notifier| notifier.notify_of_build(@build) }
34
51
  end
35
52
 
36
53
  def last_commit
@@ -42,8 +59,12 @@ module Integrity
42
59
  tap {|commits| commits.shift }
43
60
  end
44
61
 
62
+ def building?
63
+ commits.any? { |c| c.building? }
64
+ end
65
+
45
66
  def status
46
- last_commit && last_commit.status
67
+ last_commit ? last_commit.status : :blank
47
68
  end
48
69
 
49
70
  def human_readable_status
@@ -58,24 +79,6 @@ module Integrity
58
79
  end
59
80
 
60
81
  private
61
- def find_or_create_commit_with_identifier(identifier)
62
- # We abuse +committed_at+ here setting it to Time.now because we use it
63
- # to sort (for last_commit and previous_commits). I don't like this
64
- # very much, but for now it's the only solution I can find.
65
- #
66
- # This also creates a dependency, as now we *always* have to update the
67
- # +committed_at+ field after building to ensure the date is correct :(
68
- #
69
- # This might also make your commit listings a little jumpy, if some
70
- # commits change place every time a build finishes =\
71
- commits.first_or_create({:identifier => identifier, :project_id => id},
72
- :committed_at => Time.now)
73
- end
74
-
75
- def head_of_remote_repo
76
- SCM.new(uri, branch).head
77
- end
78
-
79
82
  def set_permalink
80
83
  attribute_set(:permalink, (name || "").downcase.
81
84
  gsub(/'s/, "s").
@@ -83,12 +86,5 @@ module Integrity
83
86
  gsub(/[^a-z0-9]+/, "-").
84
87
  gsub(/-*$/, ""))
85
88
  end
86
-
87
- def delete_working_directory
88
- commits.destroy!
89
- ProjectBuilder.delete_working_directory(self)
90
- rescue SCM::SCMUnknownError => error
91
- Integrity.log "Problem while trying to deleting code: #{error}"
92
- end
93
89
  end
94
90
  end
@@ -13,9 +13,8 @@ module Integrity
13
13
  end
14
14
 
15
15
  commits.each { |commit_data|
16
- commit = commit_from(commit_data)
17
- commit.create
18
- build(commit.identifier)
16
+ commit_from(commit_data).create
17
+ build(commit_data["id"])
19
18
  }
20
19
  end
21
20
 
@@ -24,8 +23,8 @@ module Integrity
24
23
  commits.new(:identifier => data["id"],
25
24
  :author => "#{data["author"]["name"]} <#{data["author"]["email"]}>",
26
25
  :message => data["message"],
27
- :url => data["url"],
28
- :committed_at => data["timestamp"])
26
+ :committed_at => data["timestamp"],
27
+ :uri => data["url"])
29
28
  end
30
29
 
31
30
  def valid_payload?(payload)
@@ -33,7 +33,7 @@ class ApiTest < Test::Unit::AcceptanceTestCase
33
33
  assert_contain("No builds for this project")
34
34
  end
35
35
 
36
- it "receiving a build request with build_all_commits *enabled* builds all commits, most recent first" do
36
+ scenario "receiving a build request with build_all_commits *enabled* builds all commits, most recent first" do
37
37
  Integrity.config[:build_all_commits] = true
38
38
 
39
39
  repo = git_repo(:my_test_project) # initial commit && successful commit
@@ -30,15 +30,21 @@ class BrowsePublicProjectsTest < Test::Unit::AcceptanceTestCase
30
30
  scenario "a user can see the projects status on the home page" do
31
31
  integrity = Project.gen(:integrity, :commits => 3.of { Commit.gen(:successful) })
32
32
  test = Project.gen(:my_test_project, :commits => 2.of { Commit.gen(:failed) })
33
- no_build = Project.gen(:public => true, :building => false)
34
- building = Project.gen(:public => true, :building => true)
33
+ no_build = Project.gen(:name => "none yet", :public => true)
34
+ building = Project.gen(:name => "building", :public => true,
35
+ :commits => 1.of{ Commit.gen(:building) })
35
36
 
36
37
  visit "/"
37
38
 
38
- assert_contain("Built #{integrity.last_commit.short_identifier} successfully")
39
- assert_contain("Built #{test.last_commit.short_identifier} and failed")
40
- assert_contain("Never built yet")
41
- assert_contain("Building!")
39
+ assert_have_tag("li[@class~=success]",
40
+ :content => "Built #{integrity.last_commit.short_identifier} successfully")
41
+
42
+ assert_have_tag("li[@class~=failed]",
43
+ :content => "Built #{test.last_commit.short_identifier} and failed")
44
+
45
+ assert_have_tag("li[@class~=blank]", :content => "Never built yet")
46
+
47
+ assert_have_tag("li[@class~=building]", :content => "Building!")
42
48
  end
43
49
 
44
50
  scenario "a user clicking through a link on the home page for a public project arrives at the project page" do
@@ -1,6 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/../helpers/acceptance"
2
2
  require "helpers/acceptance/notifier_helper"
3
- require "helpers/acceptance/textfile_notifier"
4
3
  require "helpers/acceptance/email_notifier"
5
4
 
6
5
  class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
@@ -14,7 +13,11 @@ class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
14
13
 
15
14
  before(:each) do
16
15
  # This is needed before any available notifier is unset
17
- # in the global #before
16
+ # in the global #before.
17
+ # But, we need the reload this one because we remove_const
18
+ # it in a test case. Sigh.
19
+ load "helpers/acceptance/textfile_notifier.rb"
20
+
18
21
  Notifier.register(Integrity::Notifier::Textfile)
19
22
  Notifier.register(Integrity::Notifier::Email)
20
23
  end
@@ -79,6 +82,27 @@ class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
79
82
  assert_have_email_notifier
80
83
  end
81
84
 
85
+ scenario "an admin enables the Textfile notifier and get rid of it later" do
86
+ git_repo(:my_test_project).add_successful_commit
87
+ Project.gen(:my_test_project, :uri => git_repo(:my_test_project).path)
88
+
89
+ login_as "admin", "test"
90
+ visit "/my-test-project"
91
+
92
+ click_link "Edit Project"
93
+ check "enabled_notifiers_textfile"
94
+ fill_in "File", :with => "/tmp/textfile_notifications.txt"
95
+ click_button "Update Project"
96
+
97
+ Notifier.send(:remove_const, :Textfile)
98
+ Notifier.available.clear
99
+ rm_f "/tmp/textfile_notifications.txt"
100
+
101
+ click_button "manual build"
102
+
103
+ assert ! File.file?("/tmp/textfile_notifications.txt")
104
+ end
105
+
82
106
  scenario "an admin configures various notifiers accros multiple projects" do
83
107
  Project.first(:permalink => "integrity").should be_nil
84
108
 
@@ -70,7 +70,7 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
70
70
  scenario "Installing Integrity for Heroku" do
71
71
  message = install("--heroku")
72
72
 
73
- assert_equal "integrity --version 0.1.9.0", root.join(".gems").read.chomp
73
+ assert_equal "integrity --version 0.1.9.3", root.join(".gems").read.chomp
74
74
 
75
75
  assert root.join("Rakefile").file?
76
76
  assert root.join("integrity-config.rb").file?