houston-core 0.7.0 → 0.8.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +45 -45
  3. data/app/assets/javascripts/houston/app/models/ticket.coffee +7 -5
  4. data/app/assets/javascripts/houston/app/views/new_ticket_view.coffee +1 -21
  5. data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +0 -6
  6. data/app/assets/stylesheets/houston/application/commit.scss +16 -0
  7. data/app/assets/stylesheets/houston/application/navigation.scss +1 -0
  8. data/app/assets/stylesheets/houston/application/new_ticket_view.scss +0 -4
  9. data/app/assets/stylesheets/houston/application/projects.css.scss +0 -14
  10. data/app/assets/stylesheets/houston/application/release_form.scss +1 -1
  11. data/app/assets/stylesheets/houston/application/teams.scss +68 -0
  12. data/app/assets/templates/tickets/index.hbs +0 -1
  13. data/app/controllers/github/pulls_controller.rb +1 -0
  14. data/app/controllers/project_tickets_controller.rb +1 -5
  15. data/app/controllers/projects_controller.rb +10 -12
  16. data/app/controllers/teams_controller.rb +60 -0
  17. data/app/controllers/users_controller.rb +12 -12
  18. data/app/helpers/commit_helper.rb +3 -5
  19. data/app/helpers/exposure_helper.rb +1 -1
  20. data/app/helpers/ticket_helper.rb +0 -13
  21. data/app/interactors/ticket_report.rb +0 -7
  22. data/app/mailers/project_notification.rb +2 -23
  23. data/app/mailers/view_mailer.rb +0 -1
  24. data/app/models/ability.rb +28 -19
  25. data/app/models/commit.rb +0 -4
  26. data/app/models/project.rb +14 -29
  27. data/app/models/release.rb +0 -18
  28. data/app/models/role.rb +0 -22
  29. data/app/models/team.rb +43 -0
  30. data/app/models/team_user.rb +68 -0
  31. data/app/models/ticket.rb +2 -22
  32. data/app/models/user.rb +21 -30
  33. data/app/views/devise/sessions/new.html.erb +9 -7
  34. data/app/views/layouts/_mobile_navigation.html.erb +5 -3
  35. data/app/views/layouts/_navigation.html.erb +11 -10
  36. data/app/views/layouts/_tester_bar.html.erb +1 -1
  37. data/app/views/layouts/application.html.erb +1 -2
  38. data/app/views/project_tickets/_tickets.html.erb +0 -1
  39. data/app/views/project_tickets/index.xls.erb +0 -35
  40. data/app/views/project_tickets/new.html.erb +1 -2
  41. data/app/views/projects/_form.html.erb +7 -12
  42. data/app/views/projects/index.html.erb +10 -17
  43. data/app/views/releases/_changelog.html.erb +11 -14
  44. data/app/views/teams/_form.html.erb +45 -0
  45. data/app/views/teams/edit.html.erb +8 -0
  46. data/app/views/teams/index.html.erb +62 -0
  47. data/app/views/teams/new.html.erb +7 -0
  48. data/app/views/users/_form.html.erb +2 -11
  49. data/app/views/users/index.html.erb +8 -20
  50. data/app/views/users/new.html.erb +1 -1
  51. data/config/initializers/inflections.rb +7 -6
  52. data/config/routes.rb +19 -17
  53. data/db/migrate/20160812233255_repurpose_users_role.rb +16 -0
  54. data/db/migrate/20160813001242_create_teams.rb +42 -0
  55. data/db/structure.sql +110 -116
  56. data/lib/houston/boot.rb +0 -1
  57. data/lib/houston/boot/configuration.rb +26 -11
  58. data/lib/houston/boot/events.rb +0 -4
  59. data/lib/houston/version.rb +1 -1
  60. data/templates/new-instance/config/abilities.rb +68 -51
  61. data/templates/new-instance/config/conversations/mentions/unfurl_tasks.rb +1 -1
  62. data/templates/new-instance/config/events/deploy/notify_deployer_when_finished.rb +24 -16
  63. data/templates/new-instance/config/events/tests/email_when_completed.rb +11 -0
  64. data/templates/new-instance/config/integrations/ldap.rb +4 -0
  65. data/templates/new-instance/config/main.rb +10 -17
  66. data/templates/new-module/test/fixtures/users.yml +1 -2
  67. data/test/acceptance/creating_a_release_test.rb +1 -1
  68. data/test/factories/project_factory.rb +1 -0
  69. data/test/factories/user_factory.rb +3 -1
  70. data/test/fixtures/teams.yml +2 -0
  71. data/test/fixtures/teams_users.yml +5 -0
  72. data/test/fixtures/users.yml +1 -2
  73. data/test/integration/ci_integration_test.rb +2 -2
  74. data/test/support/config.rb +3 -5
  75. data/test/unit/controllers/deploys_controller_test.rb +11 -5
  76. data/test/unit/controllers/users_controller_test.rb +46 -0
  77. data/test/unit/models/release_test.rb +0 -9
  78. data/test/unit/models/serializer_test.rb +0 -8
  79. data/test/unit/models/ticket_test.rb +0 -32
  80. metadata +21 -24
  81. data/app/assets/javascripts/houston/app/table_row_expander.coffee +0 -52
  82. data/app/assets/javascripts/houston/app/views/problems_view.coffee +0 -114
  83. data/app/assets/stylesheets/houston/application/follow_up.scss +0 -44
  84. data/app/controllers/project_exceptions_controller.rb +0 -36
  85. data/app/controllers/project_pretickets_controller.rb +0 -27
  86. data/app/mailers/deploy_notification.rb +0 -33
  87. data/app/models/antecedent.rb +0 -15
  88. data/app/models/ticket_antecedent.rb +0 -39
  89. data/app/models/value_statement.rb +0 -9
  90. data/app/presenters/problem_presenter.rb +0 -49
  91. data/app/presenters/tester_presenter.rb +0 -15
  92. data/app/views/project_notification/follow_up.html.erb +0 -26
  93. data/app/views/project_pretickets/show.html.erb +0 -49
  94. data/app/views/releases/_antecedents.html.erb +0 -12
  95. data/config/initializers/hard_coded_knowledge.rb +0 -141
  96. data/db/migrate/20130427223925_create_project_quotas.rb +0 -14
  97. data/db/migrate/20140506035755_create_value_statements.rb +0 -9
  98. data/lib/houston/boot/ticket_antecedent_serializer.rb +0 -21
  99. data/test/unit/models/ticket_antecedents_test.rb +0 -38
@@ -1,114 +0,0 @@
1
- class @ProblemsView extends Backbone.View
2
-
3
- initialize: ->
4
- @project = @options.project
5
- @problems = @options.problems
6
- @template = HandlebarsTemplates['problems/index']
7
- @renderProblem = HandlebarsTemplates['problems/show']
8
- Handlebars.registerPartial 'problem', @renderProblem
9
- $('#show_completed_exceptions').click _.bind(@toggleShowCompleted, @)
10
-
11
- render: ->
12
- @refresh()
13
-
14
- $('#problems').on 'click', 'tr', _.bind(@toggleCheckbox, @)
15
- $('#problems').on 'click', ':checkbox', _.bind(@styleRow, @)
16
-
17
- $('#merge_exceptions').click _.bind(@mergeExceptions, @)
18
- $('#unmerge_exceptions').click _.bind(@unmergeExceptions, @)
19
- $('#delete_exceptions').click _.bind(@deleteExceptions, @)
20
-
21
- $('#exceptions table').tablesorter
22
- headers:
23
- 2: {sorter: 'timestamp'}
24
- 3: {sorter: 'timestamp'}
25
-
26
- $('#exceptions').on 'click', '.btn-new-ticket', (e)=>
27
- $button = $(e.target)
28
- $button.attr('disabled', 'disabled')
29
- $exception = $button.closest('.exception')
30
- token = $exception.attr('data-token')
31
- url = $exception.attr('data-url')
32
- problem = _.find(@problems, (problem)-> problem.url == url)
33
- return unless problem
34
- App.showNewTicket
35
- type: 'bug'
36
- antecedents: ["Errbit: #{token}"]
37
- onClose: ->
38
- $button.removeAttr('disabled')
39
- onCreate: (ticket, modal)=>
40
- modal.modal('hide')
41
- problem.ticketId = ticket.id
42
- problem.ticketUrl = ticket.url
43
- problem.ticketNumber = ticket.number
44
- @refresh()
45
-
46
- refresh: ->
47
- $('#problems').html @template(problems: @problems)
48
- @updateProblemCount()
49
-
50
- updateProblemCount: ->
51
- $('#problem_count').html $('.exception:not(.has-ticket)').length
52
-
53
- toggleCheckbox: (e)->
54
- return if _.include(['A', 'INPUT', 'BUTTON', 'TEXTAREA'], e.target.nodeName)
55
- $exception = $(e.target).closest('.exception')
56
- $checkbox = $exception.find(':checkbox')
57
- $checkbox.prop('checked', !$checkbox.prop('checked'))
58
- $exception.toggleClass('selected', $checkbox.is(':checked'))
59
-
60
- styleRow: (e)->
61
- $checkbox = $(e.target)
62
- $exception = $checkbox.closest('.exception')
63
- $exception.toggleClass('selected', $checkbox.is(':checked'))
64
-
65
-
66
-
67
- mergeExceptions: ->
68
- problems = @selectedProblems()
69
- if problems.length < 2
70
- @alert '#merge_exceptions', 'You must select at least two problems to merge'
71
- else
72
- xhr = $.post "/projects/#{@project}/exceptions/merge_several", problems: problems
73
- xhr.success -> window.location.reload()
74
- xhr.error (response)=> @alert('#merge_exceptions', response.responseText)
75
-
76
- unmergeExceptions: ->
77
- problems = @selectedProblems()
78
- if problems.length < 2
79
- @alert '#unmerge_exceptions', 'You must select at least one problem to unmerge'
80
- else
81
- xhr = $.post "/projects/#{@project}/exceptions/merge_several", problems: problems
82
- xhr.success -> window.location.reload()
83
- xhr.error (response)=> @alert('#unmerge_exceptions', response.responseText)
84
-
85
- deleteExceptions: ->
86
- problems = @selectedProblems()
87
- if problems.length < 2
88
- @alert '#delete_exceptions', 'You must select at least one problem to delete'
89
- else
90
- xhr = $.post "/projects/#{@project}/exceptions/merge_several", problems: problems
91
- xhr.success -> window.location.reload()
92
- xhr.error (response)=> @alert('#delete_exceptions', response.responseText)
93
-
94
- selectedProblems: ->
95
- $('#problems_form').serializeObject()['problems[]'] || []
96
-
97
- alert: (button, message)->
98
- $(button)
99
- .attr('data-content', message)
100
- .attr('data-trigger', 'manual')
101
- .attr('data-placement', 'top')
102
- .popover('show')
103
- .blur -> $(@).popover('hide')
104
-
105
-
106
-
107
- toggleShowCompleted: (e)->
108
- $button = $(e.target)
109
- if $button.hasClass('active')
110
- $button.removeClass('btn-success')
111
- $('#exceptions').addClass('hide-completed')
112
- else
113
- $button.addClass('btn-success')
114
- $('#exceptions').removeClass('hide-completed')
@@ -1,44 +0,0 @@
1
- .followup-greeting {
2
- font-size: 2em;
3
- }
4
-
5
- .followup-narration {
6
- font-style: italic;
7
- margin-top: 2em;
8
- }
9
-
10
- .followup-narration, .followup-history {
11
- .detail { font-style: normal; font-weight: bold; color: #666; }
12
- }
13
-
14
- .followup-customer {
15
- margin-left: 2em;
16
- }
17
-
18
- .followup-customer-info {
19
- overflow: hidden;
20
- line-height: 1.66em;
21
-
22
- dt { float: left; clear: left; font-weight: bold; width: 80px; }
23
- dd { float: left; margin-left: 0; }
24
- }
25
-
26
- .followup-notes {
27
- margin: 1em 0 1em 2em;
28
- padding: 1.33em 2em;
29
- border: 1px solid #ccc;
30
- box-shadow: 0 0 6px 1px #ddd;
31
- font-size: 1.125em;
32
- line-height: 1.66em;
33
- max-width: 60em;
34
- }
35
-
36
- ol.followup-history {
37
- margin: 3em 0 0 0;
38
- padding: 0 0 0 2em;
39
-
40
- li {
41
- display: block;
42
- margin: 1em 0;
43
- }
44
- }
@@ -1,36 +0,0 @@
1
- class ProjectExceptionsController < ApplicationController
2
- before_filter :find_project
3
- attr_reader :project
4
-
5
-
6
- def merge_several
7
- respond_with project.error_tracker.merge_problems(params[:problems])
8
- end
9
-
10
-
11
- def unmerge_several
12
- respond_with project.error_tracker.unmerge_problems(params[:problems])
13
- end
14
-
15
-
16
- def delete_several
17
- respond_with project.error_tracker.delete_problems(params[:problems])
18
- end
19
-
20
-
21
- private
22
-
23
- def respond_with(response)
24
- if response.status == 200
25
- flash[:notice] = response.body
26
- head :ok
27
- else
28
- render text: response.body, status: response.status
29
- end
30
- end
31
-
32
- def find_project
33
- @project = Project.find_by_slug!(params[:slug])
34
- end
35
-
36
- end
@@ -1,27 +0,0 @@
1
- class ProjectPreticketsController < ApplicationController
2
- before_filter :find_project
3
- before_filter :api_authenticate!
4
-
5
-
6
- def show
7
- @problems = @project.error_tracker.open_problems(comments: true).sort_by(&:last_notice_at).reverse
8
- antecedents = @problems.map(&:err_ids).flatten.map { |id| "'Errbit:#{id}'" }
9
- tickets = antecedents.any? ? @project.tickets.where("antecedents && ARRAY[#{antecedents.join(",")}]") : []
10
- tickets.each do |ticket|
11
- ticket.antecedents.each do |antecedent|
12
- next unless antecedent.kind == "Errbit"
13
- err_id = antecedent.id.to_i
14
- problem = @problems.detect { |problem| problem.err_ids.member?(err_id) }
15
- problem.ticket = ticket if problem
16
- end
17
- end
18
- end
19
-
20
-
21
- private
22
-
23
- def find_project
24
- @project = Project.find_by_slug!(params[:slug])
25
- end
26
-
27
- end
@@ -1,33 +0,0 @@
1
- class DeployNotification
2
-
3
- def initialize(deploy)
4
- @deploy = deploy
5
- @deployer = deploy.deployer
6
- @maintainers = deploy.project.maintainers
7
- end
8
-
9
- attr_reader :deploy, :deployer, :maintainers
10
-
11
- def deliver!
12
- messages = maintainers.map do |maintainer|
13
- ProjectNotification.maintainer_of_deploy(maintainer, deploy).deliver!
14
- end
15
-
16
- if we_know_who_triggered_the_deploy and it_wasnt_a_maintainer
17
- messages << ProjectNotification.maintainer_of_deploy(deployer, deploy).deliver!
18
- end
19
-
20
- messages
21
- end
22
-
23
- private
24
-
25
- def we_know_who_triggered_the_deploy
26
- !deployer.blank?
27
- end
28
-
29
- def it_wasnt_a_maintainer
30
- !maintainers.with_email_address(deployer).exists?
31
- end
32
-
33
- end
@@ -1,15 +0,0 @@
1
- require 'ostruct'
2
-
3
- class Antecedent
4
-
5
- def initialize(attributes={})
6
- @ticket = attributes.fetch(:ticket, Ticket.first)
7
- @reporter = attributes.fetch(:reporter, User.first)
8
- @created_at = attributes.fetch(:created_at, 1.week.ago)
9
- @customer = attributes.fetch(:customer, OpenStruct.new(name: "Humphrey Blaughfellow"))
10
- @notes = attributes.fetch(:notes, "Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo volupt")
11
- end
12
-
13
- attr_reader :ticket, :reporter, :created_at, :customer, :notes
14
-
15
- end
@@ -1,39 +0,0 @@
1
- class TicketAntecedent
2
- include Comparable
3
-
4
- def initialize(ticket_or_commit, kind, id)
5
- @ticket_or_commit = ticket_or_commit
6
- @kind = kind
7
- @id = id
8
- end
9
-
10
- attr_reader :ticket_or_commit, :kind, :id
11
- delegate :project, to: :ticket_or_commit
12
-
13
- def self.from_s(ticket, string)
14
- new ticket, *string.split(":")
15
- end
16
-
17
- def to_s
18
- "#{kind}:#{id}"
19
- end
20
-
21
- def <=>(other)
22
- [kind, id] <=> [other.kind, other.id]
23
- end
24
-
25
-
26
-
27
- def released!(release=nil)
28
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:released", antecedent: self
29
- end
30
-
31
- def resolve!
32
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:resolved", antecedent: self
33
- end
34
-
35
- def close!
36
- Houston.observer.fire "antecedent:#{kind.downcase.underscore}:closed", antecedent: self
37
- end
38
-
39
- end
@@ -1,9 +0,0 @@
1
- class ValueStatement < ActiveRecord::Base
2
-
3
- versioned initial_version: true, dependent: :tracking, only: [:text, :weight]
4
-
5
- belongs_to :project
6
- validates :project_id, :weight, presence: true
7
- validates :text, length: 2..36
8
-
9
- end
@@ -1,49 +0,0 @@
1
- class ProblemPresenter
2
- include ActionView::Helpers::DateHelper
3
- include CommitHelper
4
-
5
- attr_reader :project, :problems
6
-
7
- def initialize(project, problems)
8
- @project = project
9
- @problems = problems
10
- end
11
-
12
- def as_json(*args)
13
- Houston.benchmark "[problem_presenter] Prepare JSON" do
14
- @problems.map(&method(:problem_to_json))
15
- end
16
- end
17
-
18
- def problem_to_json(problem)
19
- { id: problem.id,
20
- ticketId: problem.ticket.try(:id),
21
- ticketUrl: (@project.ticket_tracker.ticket_url(problem.ticket) if problem.ticket),
22
- ticketNumber: problem.ticket.try(:number),
23
- token: problem.err_ids.first,
24
- url: problem.url,
25
- message: problem.message,
26
- where: problem.where,
27
- noticesCount: problem.notices_count,
28
- comments: problem.comments,
29
-
30
- firstNotice: present_notice(problem.first_notice_at, problem.first_notice_commit, problem.first_notice_environment),
31
- lastNotice: present_notice( problem.last_notice_at, problem.last_notice_commit, problem.last_notice_environment) }
32
- end
33
-
34
- def present_notice(time, sha, environment_name)
35
- { at: time,
36
- ago: distance_of_time_in_words(time, Time.now).gsub("about ", "") + " ago",
37
- commit: (format_sha(sha) unless sha.blank?),
38
- commitUrl: (project.repo.commit_url(sha) if project.repo.respond_to?(:commit_url)),
39
- release: present_release(sha, environment_name) }
40
- end
41
-
42
- def present_release(sha, environment_name)
43
- release = @project.releases.where(["LOWER(environment_name) = ?", environment_name.downcase]).find_by_commit1(sha) if environment_name && !sha.blank?
44
- { url: "/projects/#{@project.slug}/environments/#{environment_name}/releases/#{release.id}",
45
- at: release.created_at.strftime("%b %d"),
46
- environment: environment_name.humanize } if release
47
- end
48
-
49
- end
@@ -1,15 +0,0 @@
1
- class TesterPresenter
2
-
3
- def initialize(testers)
4
- @testers = testers
5
- end
6
-
7
- def as_json(*args)
8
- @testers.map do |tester|
9
- { id: tester.id,
10
- name: tester.name,
11
- email: tester.email }
12
- end
13
- end
14
-
15
- end
@@ -1,26 +0,0 @@
1
- <h1 class="project-banner <%= @project.color %>">
2
- <small>Follow-up on</small> <%= @project.name %>
3
- </h1>
4
-
5
- <p class="followup-greeting"><%= @reporter.name %>,</p>
6
-
7
- <p class="followup-narration followup-narration-customer">on <span class="detail date"><%= @antecedent.created_at %></span>, you took a call from</p>
8
-
9
- <div class="followup-customer">
10
- <h3 class="followup-customer-name"><%= @customer.name %></h3>
11
- <dl class="followup-customer-info">
12
- <dt>Customer</dt><dd>1005783</dd>
13
- <dt>Email</dt><dd><%= mail_to "h.blaugh@juno.net" %></dd>
14
- </dl>
15
- </div>
16
-
17
- <p class="followup-narration followup-narration-notes">You recorded</p>
18
-
19
- <div class="followup-notes">
20
- <%= @antecedent.notes %>
21
- </div>
22
-
23
- <ol class="followup-history">
24
- <li>&#9658; A ticket <%= link_to "[##{@ticket.number}]", @ticket.ticket_tracker_ticket_url %> was created for this on <span class="detail date"><%= @ticket.created_at %></span></li>
25
- <li>&#9658; The ticket was deployed today at 2:37pm</li>
26
- </ol>
@@ -1,49 +0,0 @@
1
- <%= render partial: "projects/header", locals: {project: @project, subtitle: "Pretickets for"} %>
2
-
3
- <ul class="nav nav-tabs">
4
- <li class="active"><a href="#exceptions" data-toggle="tab">
5
- Exceptions <span id="problem_count" class="badge badge-inverse zero">0</span>
6
- </a></li>
7
- </ul>
8
-
9
- <div class="tab-content">
10
- <div class="tab-pane active hide-completed" id="exceptions">
11
- <a class="btn" id="show_completed_exceptions" data-toggle="button">Show Completed</a>
12
-
13
- <form id="problems_form">
14
- <table class="table table-sortable table-striped">
15
- <thead>
16
- <tr>
17
- <td class="expcetion-checkbox"></td>
18
- <th class="exception-summary">Summary</th>
19
- <th class="exception-first">First Notice</th>
20
- <th class="exception-last sort-asc">Last Notice</th>
21
- <th class="exception-count">Count</th>
22
- <td class="exception-ticket"></td>
23
- </tr>
24
- </thead>
25
- <tbody id="problems"></tbody>
26
- </table>
27
- </form>
28
-
29
- <% if @project.error_tracker_name == "Errbit" %>
30
- <div class="buttons">
31
- <button id="merge_exceptions" class="btn btn-default">Merge</button>
32
- <button id="unmerge_exceptions" class="btn btn-default">Unmerge</button>
33
- <button id="delete_exceptions" class="btn btn-danger">Delete</button>
34
- </div>
35
- <% end %>
36
- </div>
37
- </div>
38
-
39
- <% content_for :javascripts do %>
40
- <script type="text/javascript">
41
- $(function() {
42
- var problems = <%= raw ProblemPresenter.new(@project, @problems).to_json %>;
43
- new ProblemsView({
44
- project: <%= raw @project.slug.to_json %>,
45
- problems: problems
46
- }).render();
47
- });
48
- </script>
49
- <% end %>