houston-core 0.7.0.beta3 → 0.7.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +56 -56
  3. data/app/assets/javascripts/houston/app/infinite_scroll.coffee +6 -2
  4. data/app/assets/javascripts/houston/app/models/ticket.coffee +0 -42
  5. data/app/assets/javascripts/houston/app/ticket_tracker_refresh.coffee +0 -2
  6. data/app/assets/javascripts/houston/app/views/keyboard_shortcuts_modal.coffee +0 -6
  7. data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +0 -5
  8. data/app/assets/stylesheets/houston/application/actions.scss +15 -0
  9. data/app/assets/stylesheets/houston/application/layout.scss +3 -0
  10. data/app/assets/stylesheets/houston/application/markdown.scss +1 -1
  11. data/app/assets/stylesheets/houston/application/navigation.scss +3 -1
  12. data/app/assets/stylesheets/houston/application/project_banner_buttons.scss +2 -0
  13. data/app/assets/stylesheets/houston/application/tables.scss +0 -1
  14. data/app/assets/stylesheets/houston/application/timeline.scss +1 -1
  15. data/app/assets/stylesheets/houston/core/overrides.scss +2 -1
  16. data/app/concerns/houston/props.rb +11 -4
  17. data/app/concerns/project_adapter.rb +1 -1
  18. data/app/concerns/unique_add.rb +1 -1
  19. data/app/controllers/actions_controller.rb +39 -0
  20. data/app/controllers/commits_controller.rb +1 -1
  21. data/app/controllers/errors_controller.rb +10 -0
  22. data/app/controllers/hooks_controller.rb +1 -1
  23. data/app/controllers/omnibar_controller.rb +1 -11
  24. data/app/controllers/project_hooks_controller.rb +2 -2
  25. data/app/controllers/projects_controller.rb +2 -0
  26. data/app/controllers/test_runs_controller.rb +14 -3
  27. data/app/controllers/triggers_controller.rb +8 -0
  28. data/app/helpers/actions_helper.rb +7 -0
  29. data/app/helpers/application_helper.rb +1 -1
  30. data/app/interactors/cache_key_dependencies.rb +1 -1
  31. data/app/interactors/test_run_comparer.rb +1 -1
  32. data/app/mailers/project_notification.rb +0 -31
  33. data/app/models/ability.rb +0 -11
  34. data/app/models/{job.rb → action.rb} +19 -7
  35. data/app/models/commit.rb +2 -2
  36. data/app/models/deploy.rb +3 -3
  37. data/app/models/github/comment_event.rb +9 -3
  38. data/app/models/github/post_receive_event.rb +1 -1
  39. data/app/models/github/pull_request.rb +5 -5
  40. data/app/models/persistent_trigger.rb +46 -0
  41. data/app/models/project.rb +0 -1
  42. data/app/models/release.rb +1 -1
  43. data/app/models/run_tests_on_post_receive.rb +17 -17
  44. data/app/models/task.rb +4 -4
  45. data/app/models/test_run.rb +18 -5
  46. data/app/models/ticket.rb +2 -21
  47. data/app/models/ticket_antecedent.rb +3 -3
  48. data/app/models/user.rb +0 -1
  49. data/app/views/actions/index.html.erb +69 -0
  50. data/app/views/actions/show.html.erb +45 -0
  51. data/app/views/commits/show.html.erb +7 -8
  52. data/app/views/errors/_actions.html.erb +11 -0
  53. data/app/views/errors/index.html.erb +39 -0
  54. data/app/views/layouts/_mobile_navigation.html.erb +1 -9
  55. data/app/views/layouts/_navigation.html.erb +14 -8
  56. data/app/views/layouts/application.html.erb +1 -3
  57. data/app/views/project_notification/test_run.html.erb +13 -3
  58. data/app/views/projects/_form.html.erb +13 -7
  59. data/app/views/triggers/index.html.erb +39 -0
  60. data/config/initializers/add_navigation_renderers.rb +0 -6
  61. data/config/initializers/houston_async.rb +4 -2
  62. data/config/initializers/houston_scheduler_daemon.rb +6 -0
  63. data/config/initializers/load_persistent_triggers.rb +7 -0
  64. data/config/initializers/requirements.rb +2 -1
  65. data/config/initializers/sync_commits_on_post_receive.rb +2 -2
  66. data/config/routes.rb +17 -15
  67. data/db/migrate/20160711170921_rename_jobs_to_actions.rb +5 -0
  68. data/db/migrate/20160713204605_add_trigger_and_params_to_actions.rb +6 -0
  69. data/db/migrate/20160715173039_create_persistent_triggers.rb +10 -0
  70. data/db/structure.sql +197 -221
  71. data/houston-core.gemspec +1 -1
  72. data/lib/houston/boot/actions.rb +105 -0
  73. data/lib/houston/boot/active_record_serializer.rb +24 -0
  74. data/lib/houston/boot/configuration.rb +118 -49
  75. data/lib/houston/boot/events.rb +46 -0
  76. data/lib/houston/boot/extensions.rb +118 -14
  77. data/lib/houston/boot/observer.rb +122 -24
  78. data/lib/houston/boot/readonly_hash_serializer.rb +15 -0
  79. data/lib/houston/boot/serializer.rb +83 -0
  80. data/lib/houston/boot/ticket_antecedent_serializer.rb +21 -0
  81. data/lib/houston/boot/timer.rb +45 -0
  82. data/lib/houston/boot/triggers.rb +75 -0
  83. data/lib/houston/boot.rb +5 -0
  84. data/lib/houston/version.rb +1 -1
  85. data/lib/params_serializer.rb +18 -0
  86. data/lib/tasks/actions.rake +12 -0
  87. data/lib/tasks/events.rake +11 -0
  88. data/templates/new-instance/config/abilities.rb +0 -8
  89. data/templates/new-instance/config/{triggers → events}/alerts/slack_when_assigned.rb +1 -1
  90. data/templates/new-instance/config/{triggers → events}/alerts/slack_when_opened.rb +1 -1
  91. data/templates/new-instance/config/{triggers → events}/daemons/health.rb +6 -6
  92. data/templates/new-instance/config/{triggers → events}/deploy/autoresolve_errs.rb +1 -1
  93. data/templates/new-instance/config/{triggers → events}/deploy/checkout_mentioned_alerts.rb +1 -1
  94. data/templates/new-instance/config/{triggers → events}/deploy/notify_deployer_when_finished.rb +2 -2
  95. data/templates/new-instance/config/{triggers → events}/github/publish_comments_on_slack.rb +9 -9
  96. data/templates/new-instance/config/{triggers → events}/tests/slack_when_analyzed.rb +1 -1
  97. data/templates/new-instance/config/{triggers → events}/tests/slack_when_completed.rb +1 -1
  98. data/templates/new-instance/config/{triggers → events}/tickets/mark_tasks_completed_on_commit.rb +1 -1
  99. data/templates/new-instance/config/main.rb +8 -35
  100. data/templates/new-instance/config/{jobs → timers}/cache_key_dependencies.rb +0 -0
  101. data/templates/new-instance/config/{jobs → timers}/email_about_open_alerts.rb +0 -0
  102. data/templates/new-instance/config/{jobs → timers}/purge_jobs.rb +0 -0
  103. data/templates/new-instance/config/{jobs → timers}/slack_reminders_about_alerts.rb +0 -0
  104. data/templates/new-instance/config/{jobs → timers}/sync_commits.rb +0 -0
  105. data/templates/new-instance/config/{jobs → timers}/sync_pull_requests.rb +0 -0
  106. data/templates/new-instance/config/{jobs → timers}/sync_tickets.rb +0 -0
  107. data/templates/new-module/lib/houston/%name%.rb +13 -0
  108. data/test/integration/ci_integration_test.rb +5 -5
  109. data/test/integration/web_hook_test.rb +1 -1
  110. data/test/test_helper.rb +14 -0
  111. data/test/unit/controllers/hooks_controller_test.rb +2 -2
  112. data/test/unit/initializers/sync_commits_on_post_receive_test.rb +1 -1
  113. data/test/unit/models/actions_test.rb +107 -0
  114. data/test/unit/models/configuration_test.rb +108 -0
  115. data/test/unit/models/observer_test.rb +87 -3
  116. data/test/unit/models/persistent_trigger_test.rb +94 -0
  117. data/test/unit/models/serializer_test.rb +80 -0
  118. data/test/unit/models/triggers_test.rb +53 -0
  119. metadata +60 -60
  120. data/app/assets/javascripts/houston/app/models/testing_note.coffee +0 -18
  121. data/app/assets/javascripts/houston/app/views/commit_view.coffee +0 -13
  122. data/app/assets/javascripts/houston/app/views/testing_note_view.coffee +0 -85
  123. data/app/assets/javascripts/houston/app/views/testing_report_view.coffee +0 -29
  124. data/app/assets/javascripts/houston/app/views/testing_ticket_view.coffee +0 -203
  125. data/app/assets/stylesheets/houston/application/jobs.scss +0 -5
  126. data/app/assets/stylesheets/houston/application/testing_report.scss +0 -279
  127. data/app/assets/templates/commit.hbs +0 -9
  128. data/app/assets/templates/testing_notes/edit.hbs +0 -20
  129. data/app/assets/templates/testing_notes/new.hbs +0 -27
  130. data/app/assets/templates/testing_notes/show.hbs +0 -11
  131. data/app/assets/templates/testing_report/description.hbs +0 -12
  132. data/app/assets/templates/testing_report/ticket.hbs +0 -21
  133. data/app/assets/templates/testing_report/verdict.hbs +0 -4
  134. data/app/controllers/jobs_controller.rb +0 -42
  135. data/app/controllers/testing_notes_controller.rb +0 -50
  136. data/app/controllers/testing_report_controller.rb +0 -38
  137. data/app/models/testing_note.rb +0 -64
  138. data/app/presenters/testing_note_presenter.rb +0 -27
  139. data/app/presenters/testing_report_ticket_presenter.rb +0 -71
  140. data/app/views/jobs/index.html.erb +0 -72
  141. data/app/views/jobs/show.html.erb +0 -41
  142. data/app/views/project_notification/testing_note.html.erb +0 -9
  143. data/app/views/testing_report/_scripts.html.erb +0 -12
  144. data/app/views/testing_report/index.html.erb +0 -31
  145. data/app/views/testing_report/show.html.erb +0 -29
  146. data/config/initializers/houston_scheduler.rb +0 -23
  147. data/db/migrate/20120424212706_create_testing_notes.rb +0 -14
  148. data/db/migrate/20120501231817_add_expires_at_to_testing_notes.rb +0 -5
  149. data/db/migrate/20120501231948_add_unfuddle_id_to_testing_notes.rb +0 -5
  150. data/db/migrate/20120715230526_change_testing_notes_comment_to_text.rb +0 -9
  151. data/db/migrate/20130211015046_add_min_passing_verdicts_to_projects.rb +0 -5
  152. data/db/migrate/20130407220039_add_project_id_to_testing_notes.rb +0 -26
  153. data/db/migrate/20140511024021_rename_testing_notes_unfuddle_id_to_remote_id.rb +0 -5
  154. data/templates/new-instance/config/triggers/tickets/email_testing_notes.rb +0 -7
  155. data/templates/new-instance/log/development.log +0 -41253
  156. data/templates/new-instance/log/test.log +0 -545
  157. data/templates/new-module/config/initializers/add_navigation_renderer.rb +0 -3
@@ -4,7 +4,18 @@ class TestRunsController < ApplicationController
4
4
 
5
5
  def show
6
6
  @title = "Test Results for #{@test_run.sha[0...8]}"
7
- render template: "project_notification/test_run"
7
+
8
+ if request.format.oembed?
9
+ render json: MultiJson.dump({
10
+ version: "1.0",
11
+ type: "link",
12
+ provider_name: "Houston",
13
+ author_name: @project.slug,
14
+ title: @test_run.summary,
15
+ html: @test_run.short_description(with_duration: true) })
16
+ else
17
+ render template: "project_notification/test_run"
18
+ end
8
19
  end
9
20
 
10
21
  def confirm_retry
@@ -43,8 +54,8 @@ class TestRunsController < ApplicationController
43
54
  private
44
55
 
45
56
  def find_test_run
46
- @project = Project.find_by_slug!(params[:slug])
47
- @test_run = @project.test_runs.find_by_sha!(params[:commit])
57
+ @test_run = TestRun.find_by_sha!(params[:commit])
58
+ @project = @test_run.project if @test_run
48
59
  end
49
60
 
50
61
  end
@@ -0,0 +1,8 @@
1
+ class TriggersController < ApplicationController
2
+
3
+ def index
4
+ authorize! :show, :triggers
5
+ @triggers = Houston.triggers
6
+ end
7
+
8
+ end
@@ -0,0 +1,7 @@
1
+ module ActionsHelper
2
+
3
+ def format_action_params(params)
4
+ MultiJson.dump params
5
+ end
6
+
7
+ end
@@ -70,7 +70,7 @@ module ApplicationHelper
70
70
  end
71
71
  end
72
72
 
73
- def format_job_state(job)
73
+ def format_action_state(job)
74
74
  if job.in_progress?
75
75
  '<i class="fa fa-spinner fa-pulse"></i>'.html_safe
76
76
  elsif job.succeeded?
@@ -15,7 +15,7 @@ class CacheKeyDependencies
15
15
  def perform!
16
16
  KeyDependency.all.each do |dependency|
17
17
  version = ProjectDependency.new(project, dependency).version
18
- project.props["keyDependency.#{dependency.slug}"] = version
18
+ project.props["keyDependency.#{dependency.slug}"] = version.to_s
19
19
  end
20
20
  project.update_column :props, project.props.to_h
21
21
  end
@@ -27,7 +27,7 @@ class TestRunComparer
27
27
 
28
28
  test_run2.update_attribute :compared, true
29
29
 
30
- Houston.observer.fire "test_run:compared", test_run2
30
+ Houston.observer.fire "test_run:compared", test_run: test_run2
31
31
  end
32
32
  end
33
33
 
@@ -34,37 +34,6 @@ class ProjectNotification < ViewMailer
34
34
  end
35
35
 
36
36
 
37
- def testing_note(testing_note, recipients)
38
- @note = testing_note
39
- @tester = testing_note.user
40
- @ticket = testing_note.ticket
41
- @project = testing_note.project
42
- @verdict = testing_note.verdict
43
-
44
- case @verdict
45
- when "fails"
46
- @verb = "failed"
47
- @noun = "Failing Verdict"
48
- when "none"
49
- @verb = "commented on"
50
- @noun = "Comment"
51
- when "works"
52
- @verb = "passed"
53
- @noun = "Passing Verdict"
54
- else
55
- Rails.logger.warn "[project_notification] Unhandled TestingNote verdict: #{@verdict.inspect}"
56
- return
57
- end
58
-
59
- mail({
60
- from: @tester,
61
- to: recipients - [@tester],
62
- subject: "#{@tester.name} #{@verb} ticket ##{@ticket.number}",
63
- template: "testing_note"
64
- })
65
- end
66
-
67
-
68
37
  def maintainer_of_deploy(maintainer, deploy)
69
38
  @project = deploy.project
70
39
  @release = deploy.build_release
@@ -25,17 +25,6 @@ class Ability
25
25
  # If you're logged in, you can update yourself
26
26
  can :update, user
27
27
 
28
-
29
- if user.developer? or user.tester?
30
-
31
- # Developers and Testers can see and comment on Testing Reports
32
- # They can also edit their own notes
33
- can [:create, :read], TestingNote
34
- can [:update, :destroy], TestingNote, user_id: user.id
35
-
36
- end
37
-
38
-
39
28
  if user.developer?
40
29
 
41
30
  # Developers can manage projects and releases
@@ -1,18 +1,20 @@
1
- class Job < ActiveRecord::Base
1
+ class Action < ActiveRecord::Base
2
2
 
3
3
  validates :name, :started_at, presence: true
4
4
  belongs_to :error
5
5
 
6
6
  default_scope -> { order(started_at: :desc) }
7
7
 
8
+ serialize :params, Houston::ParamsSerializer.new
9
+
8
10
 
9
11
 
10
12
  def self.started_before(time)
11
13
  where arel_table[:started_at].lteq time
12
14
  end
13
15
 
14
- def self.record(job_name)
15
- job = Job.create!(name: job_name, started_at: Time.now)
16
+ def self.record(action_name, params, trigger)
17
+ action = create!(name: action_name, started_at: Time.now, trigger: trigger, params: params)
16
18
  begin
17
19
  exception = nil
18
20
 
@@ -35,22 +37,32 @@ class Job < ActiveRecord::Base
35
37
  Net::OpenTimeout,
36
38
  exceptions_wrapping(PG::ConnectionBad)
37
39
 
38
- # Note that the job failed, but do not report _these_ exceptions
40
+ # Note that the action failed, but do not report _these_ exceptions
39
41
  exception = $!
40
42
 
41
43
  rescue Exception # rescues StandardError by default; but we want to rescue and report all errors
42
44
 
43
45
  # Report all other exceptions
44
46
  exception = $!
45
- Houston.report_exception($!, parameters: {job_id: job.id, job_name: job_name})
47
+ Houston.report_exception($!, parameters: {
48
+ action_id: action.id,
49
+ action_name: action_name,
50
+ trigger: trigger,
51
+ params: params
52
+ })
46
53
 
47
54
  ensure
48
55
  begin
49
56
  Houston.reconnect do
50
- job.finish! exception
57
+ action.finish! exception
51
58
  end
52
59
  rescue Exception # rescues StandardError by default; but we want to rescue and report all errors
53
- Houston.report_exception($!, parameters: {job_id: job.id, job_name: job_name})
60
+ Houston.report_exception($!, parameters: {
61
+ action_id: action.id,
62
+ action_name: action_name,
63
+ trigger: trigger,
64
+ params: params
65
+ })
54
66
  end
55
67
  end
56
68
  end
data/app/models/commit.rb CHANGED
@@ -15,10 +15,10 @@ class Commit < ActiveRecord::Base
15
15
  after_create :associate_committers_with_self
16
16
  after_create :associate_tickets_with_self
17
17
  after_create :associate_tasks_with_self
18
- after_create { Houston.observer.fire "commit:create", self }
18
+ after_create { Houston.observer.fire "commit:create", commit: self }
19
19
 
20
20
  validates :project, presence: true
21
- validates :sha, presence: true, :uniqueness => {scope: :project_id}
21
+ validates :sha, presence: true, uniqueness: true
22
22
  validates :message, presence: true
23
23
  validates :authored_at, presence: true
24
24
  validates :committer, presence: true
data/app/models/deploy.rb CHANGED
@@ -105,11 +105,11 @@ private
105
105
  if just_completed?
106
106
  update_column :duration, completed_at - created_at if duration.nil?
107
107
  if successful?
108
- Houston.observer.fire "deploy:succeeded", self
108
+ Houston.observer.fire "deploy:succeeded", deploy: self
109
109
  else
110
- Houston.observer.fire "deploy:failed", self
110
+ Houston.observer.fire "deploy:failed", deploy: self
111
111
  end
112
- Houston.observer.fire "deploy:completed", self
112
+ Houston.observer.fire "deploy:completed", deploy: self
113
113
  end
114
114
  end
115
115
 
@@ -16,14 +16,20 @@ module Github
16
16
  def initialize(payload)
17
17
  super
18
18
  @comment = payload.fetch "comment"
19
- @action = payload.fetch "action", "created"
19
+ @action = ACTION_MAP.fetch(payload.fetch "action", "created")
20
20
  comment["project"] = Project.find_by_slug payload["repository"]["name"]
21
21
  end
22
22
 
23
23
  def process!
24
- Houston.observer.fire "github:comment:#{action}", comment
25
- Houston.observer.fire "github:comment:#{action}:#{type}", comment
24
+ Houston.observer.fire "github:comment:#{action}", comment: comment
25
+ Houston.observer.fire "github:comment:#{type}:#{action}", comment: comment
26
26
  end
27
27
 
28
+ ACTION_MAP = {
29
+ "created" => "create",
30
+ "edited" => "update",
31
+ "deleted" => "delete"
32
+ }.freeze
33
+
28
34
  end
29
35
  end
@@ -7,7 +7,7 @@ module Github
7
7
  def process!
8
8
  Rails.logger.info "\e[34m[github] Processing Post-Receive Event\e[0m"
9
9
  project = Project.find_by_slug! payload["repository"]["name"]
10
- Houston.observer.fire "hooks:post_receive", project, payload
10
+ Houston.observer.fire "hooks:project:post_receive", project: project, params: payload
11
11
  end
12
12
 
13
13
  end
@@ -18,13 +18,13 @@ module Github
18
18
  after_commit :associate_commits_with_self
19
19
 
20
20
  after_create do
21
- Houston.observer.fire "github:pull:opened", self
21
+ Houston.observer.fire "github:pull:opened", pull_request: self
22
22
  end
23
23
 
24
24
  after_update do
25
- Houston.observer.fire "github:pull:updated", self, changes
26
- Houston.observer.fire "github:pull:closed", self if closed_at_changed? && closed_at
27
- Houston.observer.fire "github:pull:reopened", self if closed_at_changed? && !closed_at
25
+ Houston.observer.fire "github:pull:updated", pull_request: self, changes: changes
26
+ Houston.observer.fire "github:pull:closed", pull_request: self if closed_at_changed? && closed_at
27
+ Houston.observer.fire "github:pull:reopened", pull_request: self if closed_at_changed? && !closed_at
28
28
  end
29
29
 
30
30
  validates :project_id, :title, :number, :repo, :url, :base_ref, :base_sha, :head_ref, :head_sha, :username, presence: true
@@ -258,7 +258,7 @@ module Github
258
258
  self.commits = project.commits.between(base_sha, head_sha)
259
259
  end
260
260
 
261
- Houston.observer.fire "github:pull:synchronize", self
261
+ Houston.observer.fire "github:pull:synchronize", pull_request: self
262
262
  end
263
263
 
264
264
  def commits_changes_before_commit?
@@ -0,0 +1,46 @@
1
+ class PersistentTrigger < ActiveRecord::Base
2
+ self.inheritance_column = nil
3
+
4
+ serialize :value, Houston::Serializer.new
5
+ serialize :params, Houston::ParamsSerializer.new
6
+
7
+ TYPES = [:at, :on, :every].freeze
8
+ validates :type, inclusion: { in: TYPES, message: "{value} is not valid Trigger type; use #{TYPES.map(&:inspect).to_sentence(two_words_connector: " or ", last_word_connector: ", or ")}" }
9
+ validate :action_must_be_defined
10
+
11
+ after_create :register!
12
+
13
+
14
+ TYPES.each do |type|
15
+ instance_eval <<-RUBY, __FILE__, __LINE__ + 1
16
+ def #{type}(value, action, params={})
17
+ self.new(type: :#{type}, value: value, action: action, params: params)
18
+ end
19
+ RUBY
20
+ end
21
+
22
+
23
+ def self.load_all
24
+ all.find_each(&:register!)
25
+ end
26
+
27
+
28
+ def type
29
+ super && super.to_sym
30
+ end
31
+
32
+
33
+ def register!
34
+ trigger = Houston.config.triggers.build(type, value, action, params)
35
+ Houston.config.triggers.push(trigger) unless Houston.config.triggers.member?(trigger)
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def action_must_be_defined
42
+ return if Houston.config.actions.exists?(action)
43
+ errors.add :action, "#{action.inspect} is not defined"
44
+ end
45
+
46
+ end
@@ -9,7 +9,6 @@ class Project < ActiveRecord::Base
9
9
  has_many :tickets, dependent: :destroy, extend: TicketSynchronizer
10
10
  has_many :milestones, dependent: :destroy, extend: MilestoneSynchronizer
11
11
  has_many :uncompleted_milestones, -> { uncompleted }, class_name: "Milestone"
12
- has_many :testing_notes, dependent: :destroy
13
12
  has_many :test_runs, dependent: :destroy
14
13
  has_many :tests, dependent: :destroy
15
14
  has_many :deploys
@@ -4,7 +4,7 @@ class Release < ActiveRecord::Base
4
4
  after_create :release_each_ticket!
5
5
  after_create :release_each_task!
6
6
  after_create :release_each_antecedent!
7
- after_create { Houston.observer.fire "release:create", self }
7
+ after_create { Houston.observer.fire "release:create", release: self }
8
8
  after_save :update_search_vector, :if => :search_vector_should_change?
9
9
 
10
10
  belongs_to :project
@@ -16,20 +16,20 @@ class RunTestsOnPostReceive
16
16
  # 1. GitHub receives a `git push` and triggers all Web Hooks:
17
17
  # POST /projects/houston/hooks/post_receive.
18
18
  # 2. Houston receives this request and fires the
19
- # 'hooks:post_receive' event.
19
+ # 'hooks:project:post_receive' event.
20
20
  # 3. Houston creates a TestRun and tells a CI server to build
21
21
  # then corresponding job:
22
22
  # POST /job/houston/buildWithParameters.
23
- Houston.observer.on "hooks:post_receive" do |project, params|
24
- Rails.logger.info "\e[34m[hooks:post_receive] creating a TestRun\e[0m"
25
- create_a_test_run(project, params)
23
+ Houston.observer.on "hooks:project:post_receive" do |e|
24
+ Rails.logger.info "\e[34m[hooks:project:post_receive] creating a TestRun\e[0m"
25
+ create_a_test_run(e.project, e.params)
26
26
  end
27
27
 
28
28
  # 4. Houston notifies GitHub that the test run has started:
29
29
  # POST /repos/houston/houston/statuses/:sha
30
- Houston.observer.on "test_run:start" do |test_run|
30
+ Houston.observer.on "test_run:start" do |e|
31
31
  Rails.logger.info "\e[34m[test_run:start] publishing status on GitHub\e[0m"
32
- publish_status_to_github(test_run)
32
+ publish_status_to_github(e.test_run)
33
33
  end
34
34
 
35
35
  # 5. Jenkins checks out the project, runs the tests, and
@@ -40,22 +40,22 @@ class RunTestsOnPostReceive
40
40
  # 7. Houston updates the TestRun,
41
41
  # fetching additional details from Jenkins:
42
42
  # GET /job/houston/19/testReport/api/json
43
- Houston.observer.on "hooks:post_build" do |project, params|
43
+ Houston.observer.on "hooks:post_build" do |e|
44
44
  Rails.logger.info "\e[34m[hooks:post_build] fetching TestRun results\e[0m"
45
- fetch_test_run_results(project, params)
45
+ fetch_test_run_results(e.project, e.params)
46
46
  end
47
47
 
48
48
  # 8. Houston publishes results to GitHub:
49
49
  # POST /repos/houston/houston/statuses/:sha
50
- Houston.observer.on "test_run:complete" do |test_run|
50
+ Houston.observer.on "test_run:complete" do |e|
51
51
  Rails.logger.info "\e[34m[test_run:complete] publishing status on GitHub\e[0m"
52
- publish_status_to_github(test_run)
52
+ publish_status_to_github(e.test_run)
53
53
  end
54
54
 
55
55
  # 9. Houston publishes results to Code Climate.
56
- Houston.observer.on "test_run:complete" do |test_run|
56
+ Houston.observer.on "test_run:complete" do |e|
57
57
  Rails.logger.info "\e[34m[test_run:complete] publishing status on CodeClimate\e[0m"
58
- publish_coverage_to_code_climate(test_run)
58
+ publish_coverage_to_code_climate(e.test_run)
59
59
  end
60
60
  end
61
61
 
@@ -63,26 +63,26 @@ class RunTestsOnPostReceive
63
63
 
64
64
  def create_a_test_run(project, params)
65
65
  unless project.has_ci_server?
66
- Rails.logger.warn "[hooks:post_receive] the project #{project.name} is not configured to be used with a Continuous Integration server"
66
+ Rails.logger.warn "[hooks:project:post_receive] the project #{project.name} is not configured to be used with a Continuous Integration server"
67
67
  return
68
68
  end
69
69
 
70
70
  payload = PostReceivePayload.new(params)
71
71
 
72
72
  unless payload.commit
73
- Rails.logger.error "[hooks:post_receive] no commit found in payload"
73
+ Rails.logger.error "[hooks:project:post_receive] no commit found in payload"
74
74
  return
75
75
  end
76
76
 
77
77
  if payload.commit == Houston::NULL_GIT_COMMIT
78
- Rails.logger.error "[hooks:post_receive] branch was deleted; not running tests again"
78
+ Rails.logger.error "[hooks:project:post_receive] branch was deleted; not running tests again"
79
79
  return
80
80
  end
81
81
 
82
82
  test_run = project.test_runs.find_by_sha(payload.commit)
83
83
 
84
84
  if test_run
85
- Rails.logger.warn "[hooks:post_receive] a test run exists for #{test_run.short_commit}; doing nothing"
85
+ Rails.logger.warn "[hooks:project:post_receive] a test run exists for #{test_run.short_commit}; doing nothing"
86
86
  return
87
87
  end
88
88
 
@@ -97,7 +97,7 @@ class RunTestsOnPostReceive
97
97
  end
98
98
 
99
99
  rescue ActiveRecord::RecordNotUnique
100
- Rails.logger.warn "[hooks:post_receive] a test run exists for #{test_run.short_commit}; doing nothing"
100
+ Rails.logger.warn "[hooks:project:post_receive] a test run exists for #{test_run.short_commit}; doing nothing"
101
101
  rescue Exception # rescues StandardError by default; but we want to rescue and report all errors
102
102
  Houston.report_exception $!, parameters: params.merge(project: project.slug)
103
103
  end
data/app/models/task.rb CHANGED
@@ -115,7 +115,7 @@ class Task < ActiveRecord::Base
115
115
  def released!(release)
116
116
  self.releases << release unless releases.exists?(release.id)
117
117
  update_column :first_release_at, release.created_at unless released?
118
- Houston.observer.fire "task:released", self
118
+ Houston.observer.fire "task:released", task: self
119
119
  end
120
120
 
121
121
  def released?
@@ -126,7 +126,7 @@ class Task < ActiveRecord::Base
126
126
 
127
127
  def mark_committed!(commit)
128
128
  update_column :first_commit_at, commit.authored_at unless committed?
129
- Houston.observer.fire "task:committed", self
129
+ Houston.observer.fire "task:committed", task: self
130
130
  end
131
131
 
132
132
  def committed?
@@ -138,7 +138,7 @@ class Task < ActiveRecord::Base
138
138
  def completed!
139
139
  return if completed?
140
140
  touch :completed_at
141
- Houston.observer.fire "task:completed", self
141
+ Houston.observer.fire "task:completed", task: self
142
142
  end
143
143
  alias :complete! :completed!
144
144
 
@@ -160,7 +160,7 @@ class Task < ActiveRecord::Base
160
160
  def reopen!
161
161
  return unless manually_completed?
162
162
  update_column :completed_at, nil
163
- Houston.observer.fire "task:reopened", self
163
+ Houston.observer.fire "task:reopened", task: self
164
164
  end
165
165
 
166
166
  def open?
@@ -10,7 +10,8 @@ class TestRun < ActiveRecord::Base
10
10
  end
11
11
  end
12
12
 
13
- validates_presence_of :project_id, :sha
13
+ validates :project, presence: true
14
+ validates :sha, presence: true, uniqueness: true
14
15
  validates :results_url, :presence => true, :if => :completed?
15
16
  validates :result, inclusion: {in: %w{aborted pass fail error}, allow_nil: true, message: "\"%{value}\" is unknown. It must be pass, fail, error, or aborted"}
16
17
  validates_associated :test_results
@@ -127,6 +128,15 @@ class TestRun < ActiveRecord::Base
127
128
  project.test_runs.find_by_sha(last_tested_ancestor.sha).failed_or_errored?
128
129
  end
129
130
 
131
+ def summary
132
+ branch = "#{project.slug}/#{self.branch}"
133
+ case result
134
+ when "pass" then "All tests passed on #{branch}"
135
+ when "fail" then "#{fail_count} #{fail_count == 1 ? "test" : "tests"} failed on #{branch}"
136
+ else "The tests are broken on #{branch}"
137
+ end
138
+ end
139
+
130
140
  def short_description(with_duration: false)
131
141
  passes = "#{pass_count} #{pass_count == 1 ? "test" : "tests"} passed"
132
142
  fails = "#{fail_count} #{fail_count == 1 ? "test" : "tests"} failed"
@@ -148,7 +158,7 @@ class TestRun < ActiveRecord::Base
148
158
 
149
159
 
150
160
  def url
151
- "https://#{Houston.config.host}/projects/#{project.slug}/test_runs/#{sha}"
161
+ "https://#{Houston.config.host}/test_runs/#{sha}"
152
162
  end
153
163
 
154
164
 
@@ -213,7 +223,7 @@ class TestRun < ActiveRecord::Base
213
223
 
214
224
  def trigger_build!
215
225
  project.ci_server.build!(sha)
216
- Houston.observer.fire "test_run:start", self
226
+ Houston.observer.fire "test_run:start", test_run: self
217
227
  end
218
228
 
219
229
  def completed!(results_url)
@@ -236,7 +246,7 @@ class TestRun < ActiveRecord::Base
236
246
  end
237
247
 
238
248
  def fire_complete!
239
- Houston.observer.fire "test_run:complete", self
249
+ Houston.observer.fire "test_run:complete", test_run: self
240
250
  end
241
251
 
242
252
 
@@ -246,6 +256,10 @@ class TestRun < ActiveRecord::Base
246
256
  write_attribute :tests, value
247
257
  end
248
258
 
259
+ def failing_tests
260
+ tests.select { |test| test[:status] == "fail" }
261
+ end
262
+
249
263
  def tests
250
264
  @tests ||= test_results.includes(:error).joins(:test).select("test_results.*", "tests.suite", "tests.name").map do |test_result|
251
265
  message, backtrace = test_result.error.output.split("\n\n") if test_result.error
@@ -319,7 +333,6 @@ class TestRun < ActiveRecord::Base
319
333
 
320
334
  { test_run_id: id,
321
335
  test_id: tests_map[[suite, name]],
322
- error_id: output.blank? ? nil : output,
323
336
  status: status,
324
337
  error_id: error_id,
325
338
  duration: test_attributes.fetch(:duration, nil) }
data/app/models/ticket.rb CHANGED
@@ -10,7 +10,6 @@ class Ticket < ActiveRecord::Base
10
10
  belongs_to :project
11
11
  belongs_to :reporter, class_name: "User"
12
12
  belongs_to :milestone, counter_cache: true
13
- has_many :testing_notes
14
13
  has_many :tasks, validate: false
15
14
  has_and_belongs_to_many :releases
16
15
  has_and_belongs_to_many :commits, -> { where(unreachable: false) }
@@ -36,7 +35,7 @@ class Ticket < ActiveRecord::Base
36
35
 
37
36
  attr_readonly :number, :project_id
38
37
 
39
- delegate :testers, :maintainers, :min_passing_verdicts, :ticket_tracker, to: :project
38
+ delegate :testers, :maintainers, :ticket_tracker, to: :project
40
39
  delegate :nosync?, to: "self.class"
41
40
 
42
41
 
@@ -253,7 +252,7 @@ class Ticket < ActiveRecord::Base
253
252
 
254
253
  def released!(release)
255
254
  cache_release_attributes(release)
256
- Houston.observer.fire "ticket:release", self, release
255
+ Houston.observer.fire "ticket:release", ticket: self, release: release
257
256
  end
258
257
 
259
258
  def resolve!
@@ -287,24 +286,6 @@ class Ticket < ActiveRecord::Base
287
286
 
288
287
 
289
288
 
290
- def testing_notes_since_last_release
291
- last_release_at ? testing_notes.where(["created_at > ?", last_release_at]) : testing_notes
292
- end
293
-
294
-
295
-
296
- def participants
297
- @participants ||= begin # Participants in a Ticket include:
298
- User.unretired.where(id: #
299
- Array(reporter_id) + # - its reporter
300
- testing_notes.pluck(:user_id) + # - anyone who has commented on it
301
- releases.pluck(:user_id)) + # - anyone who has released it
302
- committers # - anyone who has comitted to it
303
- end #
304
- end
305
-
306
-
307
-
308
289
  private
309
290
 
310
291
  def find_reporter?
@@ -25,15 +25,15 @@ class TicketAntecedent
25
25
 
26
26
 
27
27
  def released!(release=nil)
28
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:released", self
28
+ Houston.observer.fire "antecedent:#{kind.downcase.underscore}:released", antecedent: self
29
29
  end
30
30
 
31
31
  def resolve!
32
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:resolved", self
32
+ Houston.observer.fire "antecedent:#{kind.downcase.underscore}:resolved", antecedent: self
33
33
  end
34
34
 
35
35
  def close!
36
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:closed", self
36
+ Houston.observer.fire "antecedent:#{kind.downcase.underscore}:closed", antecedent: self
37
37
  end
38
38
 
39
39
  end
data/app/models/user.rb CHANGED
@@ -2,7 +2,6 @@ class User < ActiveRecord::Base
2
2
  include Retirement
3
3
  include Houston::Props
4
4
 
5
- has_many :testing_notes
6
5
  has_many :roles, :dependent => :destroy
7
6
  has_many :credentials, :class_name => "UserCredentials", :dependent => :destroy
8
7
  has_many :tickets, foreign_key: "reporter_id"