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.
- checksums.yaml +4 -4
- data/Gemfile.lock +56 -56
- data/app/assets/javascripts/houston/app/infinite_scroll.coffee +6 -2
- data/app/assets/javascripts/houston/app/models/ticket.coffee +0 -42
- data/app/assets/javascripts/houston/app/ticket_tracker_refresh.coffee +0 -2
- data/app/assets/javascripts/houston/app/views/keyboard_shortcuts_modal.coffee +0 -6
- data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +0 -5
- data/app/assets/stylesheets/houston/application/actions.scss +15 -0
- data/app/assets/stylesheets/houston/application/layout.scss +3 -0
- data/app/assets/stylesheets/houston/application/markdown.scss +1 -1
- data/app/assets/stylesheets/houston/application/navigation.scss +3 -1
- data/app/assets/stylesheets/houston/application/project_banner_buttons.scss +2 -0
- data/app/assets/stylesheets/houston/application/tables.scss +0 -1
- data/app/assets/stylesheets/houston/application/timeline.scss +1 -1
- data/app/assets/stylesheets/houston/core/overrides.scss +2 -1
- data/app/concerns/houston/props.rb +11 -4
- data/app/concerns/project_adapter.rb +1 -1
- data/app/concerns/unique_add.rb +1 -1
- data/app/controllers/actions_controller.rb +39 -0
- data/app/controllers/commits_controller.rb +1 -1
- data/app/controllers/errors_controller.rb +10 -0
- data/app/controllers/hooks_controller.rb +1 -1
- data/app/controllers/omnibar_controller.rb +1 -11
- data/app/controllers/project_hooks_controller.rb +2 -2
- data/app/controllers/projects_controller.rb +2 -0
- data/app/controllers/test_runs_controller.rb +14 -3
- data/app/controllers/triggers_controller.rb +8 -0
- data/app/helpers/actions_helper.rb +7 -0
- data/app/helpers/application_helper.rb +1 -1
- data/app/interactors/cache_key_dependencies.rb +1 -1
- data/app/interactors/test_run_comparer.rb +1 -1
- data/app/mailers/project_notification.rb +0 -31
- data/app/models/ability.rb +0 -11
- data/app/models/{job.rb → action.rb} +19 -7
- data/app/models/commit.rb +2 -2
- data/app/models/deploy.rb +3 -3
- data/app/models/github/comment_event.rb +9 -3
- data/app/models/github/post_receive_event.rb +1 -1
- data/app/models/github/pull_request.rb +5 -5
- data/app/models/persistent_trigger.rb +46 -0
- data/app/models/project.rb +0 -1
- data/app/models/release.rb +1 -1
- data/app/models/run_tests_on_post_receive.rb +17 -17
- data/app/models/task.rb +4 -4
- data/app/models/test_run.rb +18 -5
- data/app/models/ticket.rb +2 -21
- data/app/models/ticket_antecedent.rb +3 -3
- data/app/models/user.rb +0 -1
- data/app/views/actions/index.html.erb +69 -0
- data/app/views/actions/show.html.erb +45 -0
- data/app/views/commits/show.html.erb +7 -8
- data/app/views/errors/_actions.html.erb +11 -0
- data/app/views/errors/index.html.erb +39 -0
- data/app/views/layouts/_mobile_navigation.html.erb +1 -9
- data/app/views/layouts/_navigation.html.erb +14 -8
- data/app/views/layouts/application.html.erb +1 -3
- data/app/views/project_notification/test_run.html.erb +13 -3
- data/app/views/projects/_form.html.erb +13 -7
- data/app/views/triggers/index.html.erb +39 -0
- data/config/initializers/add_navigation_renderers.rb +0 -6
- data/config/initializers/houston_async.rb +4 -2
- data/config/initializers/houston_scheduler_daemon.rb +6 -0
- data/config/initializers/load_persistent_triggers.rb +7 -0
- data/config/initializers/requirements.rb +2 -1
- data/config/initializers/sync_commits_on_post_receive.rb +2 -2
- data/config/routes.rb +17 -15
- data/db/migrate/20160711170921_rename_jobs_to_actions.rb +5 -0
- data/db/migrate/20160713204605_add_trigger_and_params_to_actions.rb +6 -0
- data/db/migrate/20160715173039_create_persistent_triggers.rb +10 -0
- data/db/structure.sql +197 -221
- data/houston-core.gemspec +1 -1
- data/lib/houston/boot/actions.rb +105 -0
- data/lib/houston/boot/active_record_serializer.rb +24 -0
- data/lib/houston/boot/configuration.rb +118 -49
- data/lib/houston/boot/events.rb +46 -0
- data/lib/houston/boot/extensions.rb +118 -14
- data/lib/houston/boot/observer.rb +122 -24
- data/lib/houston/boot/readonly_hash_serializer.rb +15 -0
- data/lib/houston/boot/serializer.rb +83 -0
- data/lib/houston/boot/ticket_antecedent_serializer.rb +21 -0
- data/lib/houston/boot/timer.rb +45 -0
- data/lib/houston/boot/triggers.rb +75 -0
- data/lib/houston/boot.rb +5 -0
- data/lib/houston/version.rb +1 -1
- data/lib/params_serializer.rb +18 -0
- data/lib/tasks/actions.rake +12 -0
- data/lib/tasks/events.rake +11 -0
- data/templates/new-instance/config/abilities.rb +0 -8
- data/templates/new-instance/config/{triggers → events}/alerts/slack_when_assigned.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/alerts/slack_when_opened.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/daemons/health.rb +6 -6
- data/templates/new-instance/config/{triggers → events}/deploy/autoresolve_errs.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/deploy/checkout_mentioned_alerts.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/deploy/notify_deployer_when_finished.rb +2 -2
- data/templates/new-instance/config/{triggers → events}/github/publish_comments_on_slack.rb +9 -9
- data/templates/new-instance/config/{triggers → events}/tests/slack_when_analyzed.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/tests/slack_when_completed.rb +1 -1
- data/templates/new-instance/config/{triggers → events}/tickets/mark_tasks_completed_on_commit.rb +1 -1
- data/templates/new-instance/config/main.rb +8 -35
- data/templates/new-instance/config/{jobs → timers}/cache_key_dependencies.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/email_about_open_alerts.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/purge_jobs.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/slack_reminders_about_alerts.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/sync_commits.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/sync_pull_requests.rb +0 -0
- data/templates/new-instance/config/{jobs → timers}/sync_tickets.rb +0 -0
- data/templates/new-module/lib/houston/%name%.rb +13 -0
- data/test/integration/ci_integration_test.rb +5 -5
- data/test/integration/web_hook_test.rb +1 -1
- data/test/test_helper.rb +14 -0
- data/test/unit/controllers/hooks_controller_test.rb +2 -2
- data/test/unit/initializers/sync_commits_on_post_receive_test.rb +1 -1
- data/test/unit/models/actions_test.rb +107 -0
- data/test/unit/models/configuration_test.rb +108 -0
- data/test/unit/models/observer_test.rb +87 -3
- data/test/unit/models/persistent_trigger_test.rb +94 -0
- data/test/unit/models/serializer_test.rb +80 -0
- data/test/unit/models/triggers_test.rb +53 -0
- metadata +60 -60
- data/app/assets/javascripts/houston/app/models/testing_note.coffee +0 -18
- data/app/assets/javascripts/houston/app/views/commit_view.coffee +0 -13
- data/app/assets/javascripts/houston/app/views/testing_note_view.coffee +0 -85
- data/app/assets/javascripts/houston/app/views/testing_report_view.coffee +0 -29
- data/app/assets/javascripts/houston/app/views/testing_ticket_view.coffee +0 -203
- data/app/assets/stylesheets/houston/application/jobs.scss +0 -5
- data/app/assets/stylesheets/houston/application/testing_report.scss +0 -279
- data/app/assets/templates/commit.hbs +0 -9
- data/app/assets/templates/testing_notes/edit.hbs +0 -20
- data/app/assets/templates/testing_notes/new.hbs +0 -27
- data/app/assets/templates/testing_notes/show.hbs +0 -11
- data/app/assets/templates/testing_report/description.hbs +0 -12
- data/app/assets/templates/testing_report/ticket.hbs +0 -21
- data/app/assets/templates/testing_report/verdict.hbs +0 -4
- data/app/controllers/jobs_controller.rb +0 -42
- data/app/controllers/testing_notes_controller.rb +0 -50
- data/app/controllers/testing_report_controller.rb +0 -38
- data/app/models/testing_note.rb +0 -64
- data/app/presenters/testing_note_presenter.rb +0 -27
- data/app/presenters/testing_report_ticket_presenter.rb +0 -71
- data/app/views/jobs/index.html.erb +0 -72
- data/app/views/jobs/show.html.erb +0 -41
- data/app/views/project_notification/testing_note.html.erb +0 -9
- data/app/views/testing_report/_scripts.html.erb +0 -12
- data/app/views/testing_report/index.html.erb +0 -31
- data/app/views/testing_report/show.html.erb +0 -29
- data/config/initializers/houston_scheduler.rb +0 -23
- data/db/migrate/20120424212706_create_testing_notes.rb +0 -14
- data/db/migrate/20120501231817_add_expires_at_to_testing_notes.rb +0 -5
- data/db/migrate/20120501231948_add_unfuddle_id_to_testing_notes.rb +0 -5
- data/db/migrate/20120715230526_change_testing_notes_comment_to_text.rb +0 -9
- data/db/migrate/20130211015046_add_min_passing_verdicts_to_projects.rb +0 -5
- data/db/migrate/20130407220039_add_project_id_to_testing_notes.rb +0 -26
- data/db/migrate/20140511024021_rename_testing_notes_unfuddle_id_to_remote_id.rb +0 -5
- data/templates/new-instance/config/triggers/tickets/email_testing_notes.rb +0 -7
- data/templates/new-instance/log/development.log +0 -41253
- data/templates/new-instance/log/test.log +0 -545
- 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
|
-
|
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
|
-
@
|
47
|
-
@
|
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
|
@@ -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
|
@@ -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
|
data/app/models/ability.rb
CHANGED
@@ -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
|
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(
|
15
|
-
|
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
|
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: {
|
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
|
-
|
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: {
|
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,
|
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:#{
|
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
|
data/app/models/project.rb
CHANGED
@@ -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
|
data/app/models/release.rb
CHANGED
@@ -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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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?
|
data/app/models/test_run.rb
CHANGED
@@ -10,7 +10,8 @@ class TestRun < ActiveRecord::Base
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
|
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}/
|
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, :
|
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"
|