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
@@ -1,7 +1,7 @@
|
|
1
1
|
class Github::PullsController < ApplicationController
|
2
2
|
|
3
3
|
def index
|
4
|
-
@pulls = Github::PullRequest.order(created_at: :desc).preload(:project, :user)
|
4
|
+
@pulls = Github::PullRequest.open.order(created_at: :desc).preload(:project, :user)
|
5
5
|
@labels = @pulls.flat_map(&:labels).uniq { |label| label["name"] }.sort_by { |label| label["name"] }
|
6
6
|
@selected_labels = params.fetch(:only, "").split(/,\s*/)
|
7
7
|
@selected_labels = @labels.map { |label| label["name"] } if @selected_labels.none?
|
@@ -1,12 +1,41 @@
|
|
1
1
|
class JobsController < ApplicationController
|
2
2
|
|
3
|
+
def index
|
4
|
+
authorize! :show, :jobs
|
5
|
+
jobs_by_name = $scheduler.jobs.each_with_object({}) { |job, map|
|
6
|
+
map[job.tags.first] = {
|
7
|
+
name: job.tags.first,
|
8
|
+
schedule: job.original } }
|
9
|
+
|
10
|
+
jobs = Job.where(name: jobs_by_name.keys)
|
11
|
+
|
12
|
+
most_recent_jobs = jobs.joins(<<-SQL)
|
13
|
+
inner join (select name, max(started_at) "started_at" from jobs group by name) "most_recent"
|
14
|
+
on jobs.name=most_recent.name and jobs.started_at=most_recent.started_at
|
15
|
+
SQL
|
16
|
+
most_recent_jobs.each do |job|
|
17
|
+
jobs_by_name[job.name][:last] = job
|
18
|
+
end
|
19
|
+
|
20
|
+
jobs.group(:name).unscope(:order).pluck(:name, "COUNT(id)", "COUNT(CASE WHEN succeeded THEN 1 ELSE NULL END)", "AVG(EXTRACT(epoch from finished_at - started_at))").each do |name, runs, successful_runs, avg_duration|
|
21
|
+
jobs_by_name[name].merge!(
|
22
|
+
runs: runs,
|
23
|
+
successful_runs: successful_runs,
|
24
|
+
avg_duration: avg_duration )
|
25
|
+
end
|
26
|
+
|
27
|
+
@jobs = jobs_by_name.values
|
28
|
+
end
|
29
|
+
|
3
30
|
def show
|
4
31
|
authorize! :show, :jobs
|
32
|
+
@job_name = params[:slug]
|
33
|
+
@jobs = Job.where(name: @job_name).preload(:error)
|
5
34
|
end
|
6
35
|
|
7
36
|
def run
|
8
37
|
authorize! :run, :jobs
|
9
|
-
Houston.jobs.
|
38
|
+
Houston.jobs.run params[:slug]
|
10
39
|
redirect_to "/jobs", notice: "#{params[:slug]} is running"
|
11
40
|
end
|
12
41
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Oauth
|
2
|
+
class ProvidersController < ApplicationController
|
3
|
+
|
4
|
+
def index
|
5
|
+
@title = "Providers"
|
6
|
+
authorize! :read, Oauth::Provider
|
7
|
+
@providers = Oauth::Provider.all
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
@title = "New Provider"
|
12
|
+
authorize! :create, Oauth::Provider
|
13
|
+
@provider = Oauth::Provider.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
@provider = Oauth::Provider.new(params[:oauth_provider])
|
18
|
+
authorize! :create, @provider
|
19
|
+
|
20
|
+
if @provider.save
|
21
|
+
redirect_to oauth_providers_path
|
22
|
+
else
|
23
|
+
render action: :new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@title = "Edit Provider"
|
29
|
+
@provider = Oauth::Provider.find(params[:id])
|
30
|
+
authorize! :update, @provider
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
@provider = Oauth::Provider.find(params[:id])
|
35
|
+
authorize! :update, @provider
|
36
|
+
|
37
|
+
if @provider.update_attributes(params[:oauth_provider])
|
38
|
+
redirect_to oauth_providers_path
|
39
|
+
else
|
40
|
+
render action: :edit
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -4,14 +4,14 @@ class ProjectOptionsController < ApplicationController
|
|
4
4
|
|
5
5
|
|
6
6
|
def update
|
7
|
-
project.
|
7
|
+
project.props.merge! params[:options]
|
8
8
|
project.save!
|
9
9
|
head :ok
|
10
10
|
end
|
11
11
|
|
12
12
|
|
13
13
|
def destroy
|
14
|
-
project.
|
14
|
+
project.props.delete! params[:key]
|
15
15
|
project.save!
|
16
16
|
head :ok
|
17
17
|
end
|
@@ -31,13 +31,13 @@ class ProjectsController < ApplicationController
|
|
31
31
|
def new_from_github
|
32
32
|
authorize! :create, Project
|
33
33
|
|
34
|
-
existing_projects = Project.unscoped.where("
|
34
|
+
existing_projects = Project.unscoped.where("props->>'git.location' LIKE '%github.com%'")
|
35
35
|
github_repos = Houston.benchmark "Fetching repos" do
|
36
36
|
Houston.github.repos
|
37
37
|
end
|
38
38
|
@repos = github_repos.map do |repo|
|
39
39
|
project = existing_projects.detect { |project|
|
40
|
-
[repo.git_url, repo.ssh_url, repo.clone_url].member?(project.
|
40
|
+
[repo.git_url, repo.ssh_url, repo.clone_url].member?(project.props["git.location"]) }
|
41
41
|
{ name: repo.name,
|
42
42
|
owner: repo.owner.login,
|
43
43
|
full_name: repo.full_name,
|
@@ -60,7 +60,7 @@ class ProjectsController < ApplicationController
|
|
60
60
|
name: title,
|
61
61
|
slug: name,
|
62
62
|
version_control_name: "Git",
|
63
|
-
|
63
|
+
props: {"git.location" => "git@github.com:#{repo}.git"})
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -75,12 +75,12 @@ class ReleasesController < ApplicationController
|
|
75
75
|
@title = "Release #{@release.release_date.strftime("%b %-d")} • #{@project.name}"
|
76
76
|
|
77
77
|
if request.format.oembed?
|
78
|
-
render json: {
|
78
|
+
render json: MultiJson.dump({
|
79
79
|
version: "1.0",
|
80
80
|
type: "link",
|
81
|
-
|
81
|
+
provider_name: "#{@project.slug} / #{@release.environment_name}",
|
82
82
|
title: format_release_subject(@release),
|
83
|
-
html: format_release_description(@release) }
|
83
|
+
html: format_release_description(@release) })
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -3,14 +3,14 @@ class UserOptionsController < ApplicationController
|
|
3
3
|
|
4
4
|
|
5
5
|
def update
|
6
|
-
current_user.
|
6
|
+
current_user.props.merge! params[:options]
|
7
7
|
current_user.save!
|
8
8
|
head :ok
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
12
|
def destroy
|
13
|
-
current_user.
|
13
|
+
current_user.props.delete! params[:key]
|
14
14
|
current_user.save!
|
15
15
|
head :ok
|
16
16
|
end
|
@@ -44,7 +44,6 @@ class UsersController < ApplicationController
|
|
44
44
|
User.invite!(params[:user])
|
45
45
|
else
|
46
46
|
@user.administrator = @administrator
|
47
|
-
@user.skip_password = true
|
48
47
|
@user.save!
|
49
48
|
end
|
50
49
|
|
@@ -62,7 +61,7 @@ class UsersController < ApplicationController
|
|
62
61
|
|
63
62
|
attributes = params[:user]
|
64
63
|
attributes[:alias_emails] = attributes.fetch(:alias_emails, "").split.map(&:strip)
|
65
|
-
|
64
|
+
@user.props.merge! attributes.delete(:props) if attributes.key?(:props)
|
66
65
|
|
67
66
|
if @user.update_attributes(attributes)
|
68
67
|
redirect_to @user, notice: 'User was successfully updated.'
|
@@ -45,23 +45,69 @@ module ApplicationHelper
|
|
45
45
|
|
46
46
|
|
47
47
|
|
48
|
-
def format_time(time)
|
48
|
+
def format_time(time, options={})
|
49
49
|
if time.nil?
|
50
50
|
date, time = ["", "Never"]
|
51
51
|
elsif time.to_date == Date.today
|
52
|
-
date, time = ["Today", time.strftime("%l:%M %p")]
|
52
|
+
date, time = [options[:today] ? "Today" : "", time.strftime("%l:%M %p")]
|
53
53
|
elsif time.to_date == Date.today - 1
|
54
54
|
date, time = ["Yesterday", time.strftime("%l:%M %p")]
|
55
55
|
else
|
56
56
|
date, time = [time.strftime("%b %e"), time.strftime("%l:%M %p")]
|
57
57
|
end
|
58
58
|
|
59
|
-
<<-HTML.html_safe
|
59
|
+
<<-HTML.strip.html_safe
|
60
60
|
<span class="time-date">#{date}</span>
|
61
61
|
<span class="time-time">#{time.gsub(" AM", "a").gsub(" PM", "p")}</span>
|
62
62
|
HTML
|
63
63
|
end
|
64
64
|
|
65
|
+
def format_boolean(boolean)
|
66
|
+
if boolean
|
67
|
+
'<i class="fa fa-check success"></i>'.html_safe
|
68
|
+
else
|
69
|
+
'<i class="fa fa-times failure"></i>'.html_safe
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def format_job_state(job)
|
74
|
+
if job.in_progress?
|
75
|
+
'<i class="fa fa-spinner fa-pulse"></i>'.html_safe
|
76
|
+
elsif job.succeeded?
|
77
|
+
'<i class="fa fa-check success"></i>'.html_safe
|
78
|
+
else
|
79
|
+
'<i class="fa fa-times failure"></i>'.html_safe
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
MINUTE = 60
|
84
|
+
HOUR = MINUTE * 60
|
85
|
+
DAY = HOUR * 24
|
86
|
+
|
87
|
+
def format_duration(seconds)
|
88
|
+
if seconds.nil?
|
89
|
+
return "—".html_safe
|
90
|
+
elsif seconds < 1
|
91
|
+
"#{(seconds * 1000).floor}ms"
|
92
|
+
elsif seconds < MINUTE
|
93
|
+
"%.2f seconds" % seconds
|
94
|
+
elsif seconds < HOUR
|
95
|
+
format_duration_with_units(seconds / MINUTE, 'minute')
|
96
|
+
elsif seconds < DAY
|
97
|
+
format_duration_with_units(seconds / HOUR, 'hour')
|
98
|
+
else
|
99
|
+
format_duration_with_units(seconds / DAY, 'day')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def format_duration_with_units(quantity, unit)
|
104
|
+
quantity = quantity.floor
|
105
|
+
unit << 's' unless quantity == 1
|
106
|
+
"#{quantity} #{unit}"
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
65
111
|
def format_date_with_year(date)
|
66
112
|
return "" if date.nil?
|
67
113
|
"#{date.strftime("%b %d")}<span class=\"year\">#{date.strftime("%Y")}</span>".html_safe
|
data/app/helpers/email_helper.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module EmailHelper
|
2
2
|
|
3
3
|
def render_scss(relative_path)
|
4
|
-
asset =
|
4
|
+
asset = sprockets_env.find_asset(relative_path)
|
5
5
|
raise "Asset not found #{relative_path.inspect}" unless asset
|
6
6
|
asset.to_s.html_safe
|
7
7
|
end
|
@@ -10,4 +10,22 @@ module EmailHelper
|
|
10
10
|
@for_email == true
|
11
11
|
end
|
12
12
|
|
13
|
+
def sprockets_env
|
14
|
+
# In environments where assets.compile = false, Sprockets will no longer
|
15
|
+
# instantiate the Sprockets environment at Rails.application.assets.
|
16
|
+
#
|
17
|
+
# See how different gems worked around this change:
|
18
|
+
# https://github.com/Compass/compass-rails/issues/257#issuecomment-174819398
|
19
|
+
# https://github.com/wwidea/font-awesome-rails/pull/2
|
20
|
+
# https://github.com/rails/sprockets-rails/issues/311#issuecomment-172395232
|
21
|
+
#
|
22
|
+
# The last seems to be the recommended solution; but not all assets show up
|
23
|
+
# in the manifest; and it will still give an error ("manifest requires
|
24
|
+
# environment for compilation"). Therefore, we'll create the compilation
|
25
|
+
# environment for the sake of the mailer.
|
26
|
+
return Rails.application.assets if Rails.application.assets
|
27
|
+
return @sprockets_env if defined?(@sprockets_env)
|
28
|
+
@sprockets_env = Sprockets::Railtie.build_environment(Rails.application)
|
29
|
+
end
|
30
|
+
|
13
31
|
end
|
@@ -10,7 +10,7 @@ module ReleaseHelper
|
|
10
10
|
|
11
11
|
def format_release_description(release)
|
12
12
|
ordered_by_tag(release.release_changes)
|
13
|
-
.map { |change| "#{change.tag.name.upcase}
|
13
|
+
.map { |change| "#{change.tag.name.upcase}\t#{change.description}" }
|
14
14
|
.join("\r\n")
|
15
15
|
.html_safe
|
16
16
|
end
|
@@ -35,36 +35,4 @@ module TicketHelper
|
|
35
35
|
link_to "##{number}", goldmine_case_number_url(number), target: "_blank"
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
MINUTE = 60
|
41
|
-
HOUR = MINUTE * 60
|
42
|
-
DAY = HOUR * 24
|
43
|
-
|
44
|
-
def format_duration(seconds)
|
45
|
-
if seconds < HOUR
|
46
|
-
format_duration_with_units(seconds / MINUTE, 'minute')
|
47
|
-
elsif seconds < DAY
|
48
|
-
format_duration_with_units(seconds / HOUR, 'hour')
|
49
|
-
else
|
50
|
-
format_duration_with_units(seconds / DAY, 'day')
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def format_duration_with_units(quantity, unit)
|
55
|
-
quantity = quantity.floor
|
56
|
-
unit << 's' unless quantity == 1
|
57
|
-
"#{quantity} #{unit}"
|
58
|
-
end
|
59
|
-
|
60
|
-
def class_for_age(seconds)
|
61
|
-
if seconds < 6.hours; 'infant'
|
62
|
-
elsif seconds < 2.days; 'child'
|
63
|
-
elsif seconds < 7.days; 'adult'
|
64
|
-
elsif seconds < 4.weeks; 'senior'
|
65
|
-
elsif seconds < 26.weeks; 'old'
|
66
|
-
else 'ancient'
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
38
|
end
|
@@ -4,11 +4,7 @@ class CacheKeyDependencies
|
|
4
4
|
def self.for(*projects)
|
5
5
|
projects = projects[0] if projects.length == 1 && projects[0].respond_to?(:each)
|
6
6
|
projects.each do |project|
|
7
|
-
|
8
|
-
self.new(project).perform!
|
9
|
-
rescue StandardError => e
|
10
|
-
Houston.report_exception(e)
|
11
|
-
end
|
7
|
+
self.new(project).perform!
|
12
8
|
end
|
13
9
|
end
|
14
10
|
|
@@ -19,10 +15,9 @@ class CacheKeyDependencies
|
|
19
15
|
def perform!
|
20
16
|
KeyDependency.all.each do |dependency|
|
21
17
|
version = ProjectDependency.new(project, dependency).version
|
22
|
-
project.
|
23
|
-
"key_dependency.#{dependency.slug}" => version)
|
18
|
+
project.props["keyDependency.#{dependency.slug}"] = version
|
24
19
|
end
|
25
|
-
project.update_column :
|
20
|
+
project.update_column :props, project.props.to_h
|
26
21
|
end
|
27
22
|
|
28
23
|
end
|
data/app/mailers/view_mailer.rb
CHANGED
@@ -16,14 +16,14 @@ class ViewMailer < ActionMailer::Base
|
|
16
16
|
|
17
17
|
class_attribute :stylesheets
|
18
18
|
self.stylesheets = %w{
|
19
|
-
core/colors.scss.erb
|
20
|
-
core/avatars.scss
|
21
|
-
core/scores.scss
|
22
|
-
application/emoji.scss
|
23
|
-
application/markdown.scss
|
24
|
-
application/test_run.scss
|
25
|
-
application/releases.scss
|
26
|
-
application/follow_up.scss
|
19
|
+
houston/core/colors.scss.erb
|
20
|
+
houston/core/avatars.scss
|
21
|
+
houston/core/scores.scss
|
22
|
+
houston/application/emoji.scss
|
23
|
+
houston/application/markdown.scss
|
24
|
+
houston/application/test_run.scss
|
25
|
+
houston/application/releases.scss
|
26
|
+
houston/application/follow_up.scss
|
27
27
|
}
|
28
28
|
|
29
29
|
helper_method :can?, :cannot?, :current_ability, :stylesheets
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Authorization < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :provider, class_name: "Oauth::Provider"
|
4
|
+
|
5
|
+
validates :name, :provider_id, presence: true
|
6
|
+
|
7
|
+
def self.[](name)
|
8
|
+
find_by(name: name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.set_access_token!(params)
|
12
|
+
Authorization.find(params.fetch(:state)).tap do |authorization|
|
13
|
+
authorization.get_access_token! params.fetch(:code)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def granted?
|
18
|
+
expires_in.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def authorize_url(params={})
|
22
|
+
provider.authorize_url params.merge(scope: scope, state: id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def refresh!
|
26
|
+
merge! provider.refresh_access_token(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_access_token!(code)
|
30
|
+
merge! provider.redeem_access_token(code)
|
31
|
+
end
|
32
|
+
|
33
|
+
def access_token
|
34
|
+
refresh! if expired?
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def expired?
|
39
|
+
return false unless granted?
|
40
|
+
Time.now >= expires_at
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def merge!(new_token)
|
46
|
+
self.access_token = new_token.token
|
47
|
+
self.expires_in = new_token.expires_in
|
48
|
+
self.expires_at = expires_in.seconds.from_now
|
49
|
+
self.refresh_token = new_token.refresh_token if new_token.respond_to?(:refresh_token)
|
50
|
+
self.secret = new_token.secret if new_token.respond_to?(:secret)
|
51
|
+
save!
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|