houston-core 0.6.3 → 0.7.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +53 -63
- data/app/adapters/houston/adapters/error_tracker/errbit_adapter.rb +2 -2
- data/app/adapters/houston/adapters/ticket_tracker/github_adapter.rb +1 -1
- data/app/adapters/houston/adapters/ticket_tracker/unfuddle_adapter.rb +5 -5
- data/app/adapters/houston/adapters/version_control/git_adapter.rb +4 -4
- data/app/assets/javascripts/{app → houston/app}/boot.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/emoji.coffee.erb +0 -0
- data/app/assets/javascripts/{app → houston/app}/infinite_scroll.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/commit.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/release.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/task.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/tester.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/testing_note.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/ticket.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/models/user.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/mousetrap-bind-scoped.js +0 -0
- data/app/assets/javascripts/{app → houston/app}/releases.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/table_row_expander.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/ticket_tracker_refresh.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/_show_sprint_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/_tickets_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/all_tickets_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/commit_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/edit_sprint_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/edit_ticket_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/find_or_create_ticket_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/keyboard_shortcuts_modal.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/new_ticket_modal.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/new_ticket_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/problems_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/testing_note_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/testing_report_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/testing_ticket_view.coffee +0 -0
- data/app/assets/javascripts/{app → houston/app}/views/ticket_modal_view.coffee +0 -0
- data/app/assets/javascripts/{application.js → houston/application.js} +1 -1
- data/app/assets/javascripts/{core → houston/core}/app.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/burndown_chart.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/core_ext/array.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/core_ext/date.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/core_ext/number.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/errors.coffee +1 -1
- data/app/assets/javascripts/{core → houston/core}/handlebars_helpers.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/helpers.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/jquery_extensions.coffee +5 -3
- data/app/assets/javascripts/{core → houston/core}/stacked_area_graph.coffee +0 -0
- data/app/assets/javascripts/{core → houston/core}/stacked_bar_graph.coffee +0 -0
- data/app/assets/javascripts/{dashboard.js → houston/dashboard.js} +1 -1
- data/app/assets/javascripts/{dashboard → houston/dashboard}/refresher.coffee +0 -0
- data/app/assets/javascripts/{vendor.js → houston/vendor.js} +0 -0
- data/app/assets/stylesheets/{application.css → houston/application.css} +0 -0
- data/app/assets/stylesheets/{application → houston/application}/ansi.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/commit.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/emoji.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/exceptions.scss +1 -1
- data/app/assets/stylesheets/{application → houston/application}/find_or_create_ticket.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/follow_up.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/forms.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/freight_train.css.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/full_screen.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/github_repos.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/infinite_scroll.scss +0 -0
- data/app/assets/stylesheets/houston/application/jobs.scss +5 -0
- data/app/assets/stylesheets/{application → houston/application}/keyboard_shortcuts.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/markdown.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/mobile.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/modals.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/navigation.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/new_ticket_view.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/omnibar.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/project_banner_buttons.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/project_tiles.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/projects.css.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/pull_requests.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/queue.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/release_form.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/releases.scss +1 -1
- data/app/assets/stylesheets/{application → houston/application}/sortable_table.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/sprint.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/tables.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/test.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/test_run.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/testing_report.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/ticket.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/ticket_modal.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/tickets.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/timeline.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/tips.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/typeahead.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/uploading.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/user_wall.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/users.scss +0 -0
- data/app/assets/stylesheets/{application → houston/application}/welcome.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/alerts.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/avatars.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/burndown_chart.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/colors.scss.erb +0 -0
- data/app/assets/stylesheets/{core → houston/core}/misc.scss +3 -0
- data/app/assets/stylesheets/{core → houston/core}/octicons-icons.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/octicons.scss.erb +0 -0
- data/app/assets/stylesheets/{core → houston/core}/overrides.scss +0 -0
- data/app/assets/stylesheets/{core → houston/core}/roboto.scss.erb +0 -0
- data/app/assets/stylesheets/{core → houston/core}/scores.scss +0 -0
- data/app/assets/stylesheets/{dashboard.css → houston/dashboard.css} +0 -0
- data/app/assets/stylesheets/{dashboard → houston/dashboard}/dashboard.scss +0 -0
- data/app/assets/stylesheets/{print.css.scss → houston/print.css.scss} +0 -0
- data/app/assets/stylesheets/{variables.scss → houston/variables.scss} +0 -0
- data/app/assets/stylesheets/{vendor.css → houston/vendor.css} +0 -0
- data/app/concerns/houston/props.rb +96 -0
- data/app/concerns/project_adapter.rb +1 -1
- data/app/controllers/api/v1/measurements_controller.rb +32 -0
- data/app/controllers/application_controller.rb +1 -1
- data/app/controllers/authorizations_controller.rb +61 -0
- data/app/controllers/github/pulls_controller.rb +1 -1
- data/app/controllers/jobs_controller.rb +30 -1
- data/app/controllers/oauth/providers_controller.rb +45 -0
- data/app/controllers/project_options_controller.rb +2 -2
- data/app/controllers/projects_controller.rb +3 -3
- data/app/controllers/releases_controller.rb +3 -3
- data/app/controllers/user_options_controller.rb +2 -2
- data/app/controllers/users_controller.rb +1 -2
- data/app/helpers/application_helper.rb +49 -3
- data/app/helpers/email_helper.rb +19 -1
- data/app/helpers/release_helper.rb +1 -1
- data/app/helpers/ticket_helper.rb +0 -32
- data/app/interactors/cache_key_dependencies.rb +3 -8
- data/app/mailers/view_mailer.rb +8 -8
- data/app/models/authorization.rb +54 -0
- data/app/models/commit.rb +1 -1
- data/app/models/error.rb +14 -0
- data/app/models/github/comment_event.rb +4 -4
- data/app/models/github/pull_request.rb +39 -17
- data/app/models/github/pull_request_event.rb +1 -7
- data/app/models/job.rb +81 -0
- data/app/models/measurement.rb +2 -1
- data/app/models/oauth/provider.rb +35 -0
- data/app/models/project.rb +12 -3
- data/app/models/slackdown.rb +1 -1
- data/app/models/user.rb +28 -35
- data/app/presenters/measurements_presenter.rb +26 -0
- data/app/presenters/project_presenter.rb +1 -1
- data/app/views/authorizations/_form.html.erb +33 -0
- data/app/views/authorizations/edit.html.erb +7 -0
- data/app/views/authorizations/granted.html.erb +7 -0
- data/app/views/authorizations/index.html.erb +47 -0
- data/app/views/authorizations/new.html.erb +7 -0
- data/app/views/configuration_error/_no_ticket_tracker.html.erb +1 -1
- data/app/views/github/pulls/index.html.erb +5 -1
- data/app/views/jobs/index.html.erb +72 -0
- data/app/views/jobs/show.html.erb +25 -32
- data/app/views/layouts/_navigation.html.erb +1 -1
- data/app/views/layouts/application.html.erb +14 -15
- data/app/views/layouts/dashboard.html.erb +9 -10
- data/app/views/layouts/minimal.html.erb +14 -15
- data/app/views/layouts/naked.html.erb +52 -0
- data/app/views/layouts/naked_dashboard.html.erb +9 -10
- data/app/views/oauth/providers/_form.html.erb +54 -0
- data/app/views/oauth/providers/edit.html.erb +7 -0
- data/app/views/oauth/providers/index.html.erb +41 -0
- data/app/views/oauth/providers/new.html.erb +7 -0
- data/app/views/projects/_form.html.erb +8 -9
- data/app/views/projects/index.html.erb +1 -1
- data/app/views/users/_form.html.erb +20 -19
- data/bin/rails +1 -1
- data/config/application.rb +11 -10
- data/config/boot.rb +1 -2
- data/config/environments/development.rb +8 -6
- data/config/environments/production.rb +11 -16
- data/config/environments/test.rb +5 -5
- data/config/initializers/assets.rb +17 -7
- data/config/initializers/cookies_serializer.rb +1 -1
- data/config/initializers/houston_async.rb +22 -4
- data/config/initializers/houston_report_exception.rb +16 -11
- data/config/initializers/houston_scheduler.rb +1 -1
- data/config/initializers/houston_try.rb +12 -0
- data/config/routes.rb +29 -19
- data/db/fixtures/projects.yml +2 -2
- data/db/migrate/20160317140151_remove_limit_from_users_invitation_token.rb +9 -0
- data/db/migrate/20160419230411_create_oauth_providers.rb +14 -0
- data/db/migrate/20160420000616_create_authorizations.rb +16 -0
- data/db/migrate/20160507135209_create_jobs.rb +14 -0
- data/db/migrate/20160507135846_create_errors_2.rb +12 -0
- data/db/migrate/20160510233329_add_closed_at_and_merged_at_to_pull_requests.rb +7 -0
- data/db/migrate/20160625203412_convert_user_view_options_to_props.rb +21 -0
- data/db/migrate/20160625221840_convert_project_extended_attributes_to_props.rb +32 -0
- data/db/migrate/20160625230420_move_users_unfuddle_id_to_props.rb +14 -0
- data/db/structure.sql +247 -4
- data/{houston.gemspec → houston-core.gemspec} +8 -9
- data/lib/configuration.rb +15 -43
- data/lib/houston/version.rb +1 -1
- data/lib/houston_observer.rb +2 -7
- data/lib/parallel_enumerable.rb +2 -8
- data/templates/new-instance/app/assets/javascripts/.keep +0 -0
- data/templates/new-instance/app/assets/javascripts/application.js +13 -0
- data/templates/new-instance/app/assets/stylesheets/.keep +0 -0
- data/templates/new-instance/app/assets/stylesheets/application.css +13 -0
- data/templates/new-instance/app/controllers/.keep +0 -0
- data/templates/new-instance/app/models/.keep +0 -0
- data/templates/new-instance/app/views/.keep +0 -0
- data/templates/new-instance/config/alerts/errs.rb +1 -1
- data/templates/new-instance/config/jobs/purge_jobs.rb +3 -0
- data/templates/new-instance/config/main.rb +1 -0
- data/templates/new-instance/config/routes.rb +5 -0
- data/templates/new-instance/config/triggers/github/publish_comments_on_slack.rb +3 -3
- data/templates/new-instance/lib/houston/engine.rb +25 -0
- data/test/acceptance/creating_a_release_test.rb +1 -1
- data/test/integration/ci_integration_test.rb +2 -2
- data/test/integration/commits_api_test.rb +1 -1
- data/test/unit/controllers/hooks_controller_test.rb +1 -6
- data/test/unit/controllers/project_options_controller_test.rb +11 -11
- data/test/unit/controllers/user_options_controller_test.rb +13 -13
- data/test/unit/models/code_climate_coverage_report_test.rb +1 -1
- data/test/unit/models/commit_test.rb +4 -2
- data/test/unit/models/project_test.rb +5 -5
- data/test/unit/models/props_test.rb +57 -0
- data/test/unit/models/pull_request_test.rb +2 -2
- data/test/unit/models/test_run_test.rb +1 -1
- metadata +166 -151
- data/app/assets/javascripts/app/views/reports_view.coffee +0 -51
- data/app/controllers/oauth_consumers_controller.rb +0 -68
- data/app/controllers/reports_controller.rb +0 -215
- data/app/models/consumer_token.rb +0 -13
- data/app/models/github_token.rb +0 -8
- data/app/views/oauth_consumers/error.html.erb +0 -5
- data/app/views/oauth_consumers/index.html.erb +0 -29
- data/app/views/oauth_consumers/show.html.erb +0 -7
- data/app/views/reports/index.html.erb +0 -9
- data/app/views/reports/sprint.html.erb +0 -21
- data/app/views/reports/velocity.html.erb +0 -104
- data/config/initializers/oauth_consumers.rb +0 -18
- data/lib/patches/sprockets_output_path_for_assets.rb +0 -29
data/app/models/commit.rb
CHANGED
@@ -173,7 +173,7 @@ class Commit < ActiveRecord::Base
|
|
173
173
|
|
174
174
|
clean_message.gsub!(TICKET_PATTERN) { tickets << [$1.to_i, $2]; "" }
|
175
175
|
clean_message.gsub!(TIME_PATTERN) { hours = $1.to_f; hours /= 60 if $2.starts_with?("m"); "" }
|
176
|
-
clean_message.gsub!(EXTRA_ATTRIBUTE_PATTERN) { (attributes[$1] ||= []).
|
176
|
+
clean_message.gsub!(EXTRA_ATTRIBUTE_PATTERN) { (attributes[$1] ||= []).concat($2.split(",").map(&:strip).reject(&:blank?)); "" }
|
177
177
|
while clean_message.gsub!(TAG_PATTERN) { tags << $1; "" }; end
|
178
178
|
|
179
179
|
{tags: tags, tickets: tickets, hours_worked: hours, attributes: attributes, clean_message: clean_message.strip}
|
data/app/models/error.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Error < ActiveRecord::Base
|
2
|
+
|
3
|
+
validates :sha, :message, :backtrace, presence: true
|
4
|
+
|
5
|
+
def self.find_or_create_for_exception(exception)
|
6
|
+
message = exception.message
|
7
|
+
backtrace = exception.backtrace.join("\n")
|
8
|
+
sha = Digest::SHA1.hexdigest([message, backtrace].join)
|
9
|
+
create_with(message: message, backtrace: backtrace).find_or_create_by(sha: sha)
|
10
|
+
rescue ActiveRecord::RecordNotUnique
|
11
|
+
find_by(sha: sha)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -2,7 +2,7 @@ require "github/event"
|
|
2
2
|
|
3
3
|
module Github
|
4
4
|
class CommentEvent < Event
|
5
|
-
attr_reader :comment, :project, :user
|
5
|
+
attr_reader :action, :comment, :project, :user
|
6
6
|
|
7
7
|
class << self
|
8
8
|
attr_accessor :type
|
@@ -16,13 +16,13 @@ module Github
|
|
16
16
|
def initialize(payload)
|
17
17
|
super
|
18
18
|
@comment = payload.fetch "comment"
|
19
|
+
@action = payload.fetch "action", "created"
|
19
20
|
comment["project"] = Project.find_by_slug payload["repository"]["name"]
|
20
21
|
end
|
21
22
|
|
22
23
|
def process!
|
23
|
-
|
24
|
-
Houston.observer.fire "github:comment", comment
|
25
|
-
Houston.observer.fire "github:comment:#{type}", comment
|
24
|
+
Houston.observer.fire "github:comment:#{action}", comment
|
25
|
+
Houston.observer.fire "github:comment:#{action}:#{type}", comment
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Github
|
2
2
|
class PullRequest < ActiveRecord::Base
|
3
|
+
include Houston::Props
|
4
|
+
|
3
5
|
self.table_name = "pull_requests"
|
4
6
|
|
5
7
|
attr_readonly :project_id, :user_id, :repo, :number, :username, :base_ref, :base_sha, :url
|
@@ -15,9 +17,15 @@ module Github
|
|
15
17
|
before_save :associate_user_with_self, if: :username_changed?
|
16
18
|
after_commit :associate_commits_with_self
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
after_create do
|
21
|
+
Houston.observer.fire "github:pull:opened", self
|
22
|
+
end
|
23
|
+
|
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
|
28
|
+
end
|
21
29
|
|
22
30
|
validates :project_id, :title, :number, :repo, :url, :base_ref, :base_sha, :head_ref, :head_sha, :username, presence: true
|
23
31
|
validates :number, uniqueness: { scope: :project_id }
|
@@ -36,8 +44,8 @@ module Github
|
|
36
44
|
# requests from 52 repos.
|
37
45
|
def fetch!(projects = Project.unretired)
|
38
46
|
repos = projects
|
39
|
-
.where("
|
40
|
-
.pluck("
|
47
|
+
.where("props->>'git.location' LIKE '%github.com%'")
|
48
|
+
.pluck("props->>'git.location'")
|
41
49
|
.map { |url| _repo_name_from_url(url) }
|
42
50
|
.compact
|
43
51
|
|
@@ -83,12 +91,14 @@ module Github
|
|
83
91
|
Houston.benchmark "Syncing pull requests" do
|
84
92
|
existing_pulls = all.to_a
|
85
93
|
|
86
|
-
#
|
94
|
+
# Fetch unexpected pulls so that we know
|
95
|
+
# when they were closed and whether they
|
96
|
+
# were merged.
|
87
97
|
existing_pulls.each do |existing_pr|
|
88
98
|
unless expected_pulls.detect { |expected_pr|
|
89
99
|
expected_pr["base"]["repo"]["name"] == existing_pr.repo &&
|
90
100
|
expected_pr["number"] == existing_pr.number }
|
91
|
-
existing_pr.
|
101
|
+
expected_pulls << existing_pr.fetch!
|
92
102
|
end
|
93
103
|
end
|
94
104
|
|
@@ -108,16 +118,6 @@ module Github
|
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
111
|
-
def close!(github_pr, options={})
|
112
|
-
pr = find_by(
|
113
|
-
repo: github_pr["base"]["repo"]["name"],
|
114
|
-
number: github_pr["number"])
|
115
|
-
return unless pr
|
116
|
-
|
117
|
-
pr.actor = options[:as]
|
118
|
-
pr.destroy
|
119
|
-
end
|
120
|
-
|
121
121
|
def upsert!(github_pr, options={})
|
122
122
|
retry_count ||= 0
|
123
123
|
upsert(github_pr).tap do |pr|
|
@@ -138,6 +138,18 @@ module Github
|
|
138
138
|
.merge_attributes(github_pr)
|
139
139
|
end
|
140
140
|
|
141
|
+
def open
|
142
|
+
where(closed_at: nil)
|
143
|
+
end
|
144
|
+
|
145
|
+
def closed
|
146
|
+
where.not(closed_at: nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
def merged
|
150
|
+
where.not(merged_at: nil)
|
151
|
+
end
|
152
|
+
|
141
153
|
def labeled(*labels)
|
142
154
|
where(["exists (select 1 from jsonb_array_elements(pull_requests.json_labels) as \"label\" where \"label\"->>'name' IN (?))", labels])
|
143
155
|
end
|
@@ -198,6 +210,14 @@ module Github
|
|
198
210
|
project.repo.create_commit_status(head_sha, status)
|
199
211
|
end
|
200
212
|
|
213
|
+
def full_repo
|
214
|
+
url[/https:\/\/github.com\/(.*)\/pull\/\d+/, 1]
|
215
|
+
end
|
216
|
+
|
217
|
+
def fetch!
|
218
|
+
Houston.github.pull_request(full_repo, number).to_h.with_indifferent_access
|
219
|
+
end
|
220
|
+
|
201
221
|
|
202
222
|
|
203
223
|
def merge_attributes(pr)
|
@@ -214,6 +234,8 @@ module Github
|
|
214
234
|
self.body = pr["body"]
|
215
235
|
self.base_sha = pr["base"]["sha"]
|
216
236
|
self.head_sha = pr["head"]["sha"]
|
237
|
+
self.closed_at = pr["closed_at"]
|
238
|
+
self.merged_at = pr["merged_at"]
|
217
239
|
self.labels = pr["labels"] if pr.key?("labels")
|
218
240
|
|
219
241
|
self
|
@@ -20,14 +20,8 @@ module Github
|
|
20
20
|
return
|
21
21
|
end
|
22
22
|
|
23
|
-
# Delete pull requests when they are closed
|
24
|
-
if action == "closed"
|
25
|
-
PullRequest.close! pull_request, as: actor
|
26
|
-
return
|
27
|
-
end
|
28
|
-
|
29
23
|
# Ensure that we have a record of this open pull request
|
30
|
-
# action: labeled, unlabeled, opened, reopened, or synchronized
|
24
|
+
# action: labeled, unlabeled, opened, closed, reopened, or synchronized
|
31
25
|
pr = PullRequest.upsert! pull_request, as: actor
|
32
26
|
|
33
27
|
# The Pull Request may be invalid if it isn't for a
|
data/app/models/job.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
class Job < ActiveRecord::Base
|
2
|
+
|
3
|
+
validates :name, :started_at, presence: true
|
4
|
+
belongs_to :error
|
5
|
+
|
6
|
+
default_scope -> { order(started_at: :desc) }
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
def self.started_before(time)
|
11
|
+
where arel_table[:started_at].lteq time
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.record(job_name)
|
15
|
+
job = Job.create!(name: job_name, started_at: Time.now)
|
16
|
+
begin
|
17
|
+
exception = nil
|
18
|
+
|
19
|
+
Houston.reconnect do
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
|
23
|
+
rescue SocketError,
|
24
|
+
Errno::ECONNREFUSED,
|
25
|
+
Errno::ETIMEDOUT,
|
26
|
+
Faraday::ConnectionFailed,
|
27
|
+
Faraday::SSLError,
|
28
|
+
Faraday::HTTP::ServerError,
|
29
|
+
Faraday::HTTP::Unauthorized,
|
30
|
+
Faraday::TimeoutError,
|
31
|
+
Rugged::NetworkError,
|
32
|
+
Unfuddle::ConnectionError,
|
33
|
+
Octokit::BadGateway,
|
34
|
+
Octokit::InternalServerError,
|
35
|
+
Net::OpenTimeout,
|
36
|
+
exceptions_wrapping(PG::ConnectionBad)
|
37
|
+
|
38
|
+
# Note that the job failed, but do not report _these_ exceptions
|
39
|
+
exception = $!
|
40
|
+
|
41
|
+
rescue Exception # rescues StandardError by default; but we want to rescue and report all errors
|
42
|
+
|
43
|
+
# Report all other exceptions
|
44
|
+
exception = $!
|
45
|
+
Houston.report_exception($!, parameters: {job_id: job.id, job_name: job_name})
|
46
|
+
|
47
|
+
ensure
|
48
|
+
begin
|
49
|
+
Houston.reconnect do
|
50
|
+
job.finish! exception
|
51
|
+
end
|
52
|
+
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})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def exception=(exception)
|
61
|
+
self.error = Error.find_or_create_for_exception(exception) if exception
|
62
|
+
end
|
63
|
+
|
64
|
+
def finish!(exception)
|
65
|
+
update_attributes! finished_at: Time.now, succeeded: exception.nil?, exception: exception
|
66
|
+
end
|
67
|
+
|
68
|
+
def duration
|
69
|
+
return nil unless finished?
|
70
|
+
finished_at - started_at
|
71
|
+
end
|
72
|
+
|
73
|
+
def finished?
|
74
|
+
finished_at.present?
|
75
|
+
end
|
76
|
+
|
77
|
+
def in_progress?
|
78
|
+
finished_at.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/app/models/measurement.rb
CHANGED
@@ -49,6 +49,7 @@ class Measurement < ActiveRecord::Base
|
|
49
49
|
|
50
50
|
def for(subject)
|
51
51
|
return where(subject_type: nil, subject_id: nil) if subject.nil?
|
52
|
+
return where(subject_type: subject.name) if subject.is_a?(Class)
|
52
53
|
where(subject_type: subject.class.name, subject_id: subject.id)
|
53
54
|
end
|
54
55
|
|
@@ -65,7 +66,7 @@ class Measurement < ActiveRecord::Base
|
|
65
66
|
# - weekly.hours.*.fix
|
66
67
|
def named(*name_patterns)
|
67
68
|
name_patterns = name_patterns.flatten.map { |pattern| pattern
|
68
|
-
.gsub(/\{([\w
|
69
|
+
.gsub(/\{([\w\-,]+)\}/) { "(#{$~.captures[0].gsub(/,/, "|")})" }
|
69
70
|
.gsub(/\*$/, "%") }
|
70
71
|
where(["name SIMILAR TO ?", "(#{name_patterns.join("|")})"])
|
71
72
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Oauth
|
2
|
+
class Provider < ActiveRecord::Base
|
3
|
+
self.table_name = "oauth_providers"
|
4
|
+
|
5
|
+
validates :name, :site, :authorize_path, :token_path, :client_id, :client_secret, presence: true
|
6
|
+
|
7
|
+
def authorize_url(params={})
|
8
|
+
client.auth_code.authorize_url params.merge(redirect_uri: oauth2_callback_url)
|
9
|
+
end
|
10
|
+
|
11
|
+
def redeem_access_token(code, params={})
|
12
|
+
client.auth_code.get_token(code, params.merge(redirect_uri: oauth2_callback_url))
|
13
|
+
end
|
14
|
+
|
15
|
+
def refresh_access_token(authorization)
|
16
|
+
OAuth2::AccessToken.from_hash(client, authorization.attributes).refresh!
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def client
|
22
|
+
@client ||= OAuth2::Client.new(
|
23
|
+
client_id,
|
24
|
+
client_secret,
|
25
|
+
site: site,
|
26
|
+
authorize_url: authorize_path,
|
27
|
+
token_url: token_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def oauth2_callback_url
|
31
|
+
"http://#{Houston.host}/oauth2/callback"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/app/models/project.rb
CHANGED
@@ -2,6 +2,7 @@ class Project < ActiveRecord::Base
|
|
2
2
|
extend ProjectAdapter
|
3
3
|
include Retirement
|
4
4
|
include FeatureState
|
5
|
+
include Houston::Props
|
5
6
|
|
6
7
|
has_many :releases, dependent: :destroy
|
7
8
|
has_many :commits, dependent: :destroy, extend: CommitSynchronizer
|
@@ -59,7 +60,7 @@ class Project < ActiveRecord::Base
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def show_release_notes_for?(environment_name)
|
62
|
-
|
63
|
+
props["releases.ignore.#{environment_name.downcase}"] != "1"
|
63
64
|
end
|
64
65
|
|
65
66
|
def environment(environment_name)
|
@@ -67,11 +68,19 @@ class Project < ActiveRecord::Base
|
|
67
68
|
end
|
68
69
|
|
69
70
|
def extended_attributes
|
70
|
-
|
71
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
72
|
+
end
|
73
|
+
|
74
|
+
def extended_attributes=(value)
|
75
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
71
76
|
end
|
72
77
|
|
73
78
|
def view_options
|
74
|
-
|
79
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
80
|
+
end
|
81
|
+
|
82
|
+
def view_options=(value)
|
83
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
75
84
|
end
|
76
85
|
|
77
86
|
def testers
|
data/app/models/slackdown.rb
CHANGED
data/app/models/user.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
2
|
include Retirement
|
3
|
+
include Houston::Props
|
3
4
|
|
4
5
|
has_many :testing_notes
|
5
6
|
has_many :roles, :dependent => :destroy
|
6
7
|
has_many :credentials, :class_name => "UserCredentials", :dependent => :destroy
|
7
|
-
has_many :consumer_tokens
|
8
8
|
has_many :tickets, foreign_key: "reporter_id"
|
9
9
|
has_and_belongs_to_many :commits
|
10
10
|
belongs_to :current_project, class_name: "Project"
|
@@ -73,10 +73,6 @@ class User < ActiveRecord::Base
|
|
73
73
|
with_email_address(email_address).first
|
74
74
|
end
|
75
75
|
|
76
|
-
def self.with_view_option(option, value)
|
77
|
-
where(["view_options->? = ?", option, value])
|
78
|
-
end
|
79
|
-
|
80
76
|
|
81
77
|
|
82
78
|
def email=(value)
|
@@ -86,7 +82,7 @@ class User < ActiveRecord::Base
|
|
86
82
|
end
|
87
83
|
|
88
84
|
def email_addresses
|
89
|
-
super || []
|
85
|
+
(super || []).reject(&:blank?)
|
90
86
|
end
|
91
87
|
|
92
88
|
def alias_emails
|
@@ -94,7 +90,7 @@ class User < ActiveRecord::Base
|
|
94
90
|
end
|
95
91
|
|
96
92
|
def alias_emails=(value)
|
97
|
-
self.email_addresses = [email] + Array.wrap(value)
|
93
|
+
self.email_addresses = [email] + Array.wrap(value).reject(&:blank?)
|
98
94
|
end
|
99
95
|
|
100
96
|
|
@@ -112,7 +108,19 @@ class User < ActiveRecord::Base
|
|
112
108
|
end
|
113
109
|
|
114
110
|
def view_options
|
115
|
-
|
111
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
112
|
+
end
|
113
|
+
|
114
|
+
def view_options=(value)
|
115
|
+
raise NotImplementedError, "This feature has been deprecated; use props"
|
116
|
+
end
|
117
|
+
|
118
|
+
def unfuddle_id
|
119
|
+
raise NotImplementedError, "This feature has been deprecated; use props[\"unfuddle.id\"]"
|
120
|
+
end
|
121
|
+
|
122
|
+
def unfuddle_id=(value)
|
123
|
+
raise NotImplementedError, "This feature has been deprecated; use props[\"unfuddle.id\"]"
|
116
124
|
end
|
117
125
|
|
118
126
|
|
@@ -121,37 +129,22 @@ class User < ActiveRecord::Base
|
|
121
129
|
# ------------------------------------------------------------------------- #
|
122
130
|
|
123
131
|
def self.find_by_github_username(username)
|
124
|
-
|
125
|
-
user = ::User.where(["view_options->'github_username' = ?", username]).first
|
126
|
-
return user if user
|
127
|
-
|
128
|
-
# Look up the email address of the GitHub user and see if we can
|
129
|
-
# identify the Houston user by the GitHub user's email address.
|
130
|
-
user = Houston.github.user(username)
|
131
|
-
user = find_by_email_address user.email if user
|
132
|
-
|
133
|
-
# We couldn't find the user by their email address, now
|
134
|
-
# we'll look at their nicknames
|
135
|
-
user = find_by_nickname username unless user
|
136
|
-
|
137
|
-
# We've failed to identify this user
|
138
|
-
unless user
|
139
|
-
Rails.logger.warn "\e[31m[pulls] Unable to identify a user for the GitHub username \e[1m#{username}\e[0m"
|
140
|
-
return nil
|
141
|
-
end
|
132
|
+
find_by_prop "github.username", username do |username|
|
142
133
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
134
|
+
# Look up the email address of the GitHub user and see if we can
|
135
|
+
# identify the Houston user by the GitHub user's email address.
|
136
|
+
user = Houston.github.user(username)
|
137
|
+
user = find_by_email_address user.email if user
|
148
138
|
|
149
|
-
|
150
|
-
|
139
|
+
# We couldn't find the user by their email address, now
|
140
|
+
# we'll look at their nicknames
|
141
|
+
user = find_by_nickname username unless user
|
142
|
+
|
143
|
+
end
|
151
144
|
end
|
152
145
|
|
153
|
-
def
|
154
|
-
|
146
|
+
def github_username
|
147
|
+
props["github.username"]
|
155
148
|
end
|
156
149
|
|
157
150
|
# ------------------------------------------------------------------------- #
|