houston-core 0.7.0 → 0.8.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -10,7 +10,6 @@
10
10
  <!-- TMI: knowledge of roadmap module -->
11
11
  <a href="/roadmap/milestones/{{id}}">{{name}}</a>
12
12
  {{/milestone}}</td>
13
- <td class="ticket-antecedents">{{{summarizeAntecedents antecedents}}}</td>
14
13
  <td class="ticket-opened date">{{{formatDateWithYear openedAt}}}</td>
15
14
  <td class="ticket-closed date">{{{formatDateWithYear closedAt}}}</td>
16
15
  <td class="table-margin"></td>
@@ -2,6 +2,7 @@ class Github::PullsController < ApplicationController
2
2
 
3
3
  def index
4
4
  @pulls = Github::PullRequest.open.order(created_at: :desc).preload(:project, :user)
5
+ .find_all { |pull| can?(:read, pull) }
5
6
  @labels = @pulls.flat_map(&:labels).uniq { |label| label["name"] }.sort_by { |label| label["name"] }
6
7
  @selected_labels = params.fetch(:only, "").split(/,\s*/)
7
8
  @selected_labels = @labels.map { |label| label["name"] } if @selected_labels.none?
@@ -58,9 +58,6 @@ class ProjectTicketsController < ApplicationController
58
58
  return
59
59
  end
60
60
 
61
- @labels = []
62
- @labels = Houston::TMI::TICKET_LABELS_FOR_MEMBERS if @project.slug =~ /^360|members$/
63
- @labels = Houston::TMI::TICKET_LABELS_FOR_UNITE if @project.slug == "unite"
64
61
  Houston.benchmark "Load tickets" do
65
62
  @tickets = @project.tickets
66
63
  .pluck(:id, :summary, :number, :closed_at)
@@ -76,8 +73,7 @@ class ProjectTicketsController < ApplicationController
76
73
  if request.xhr?
77
74
  render json: MultiJson.dump({
78
75
  tickets: @tickets,
79
- project: { slug: @project.slug, ticketTrackerName: @project.ticket_tracker_name },
80
- labels: @labels
76
+ project: { slug: @project.slug, ticketTrackerName: @project.ticket_tracker_name }
81
77
  })
82
78
  else
83
79
  render
@@ -7,8 +7,6 @@ class ProjectsController < ApplicationController
7
7
  def index
8
8
  @title = "Projects"
9
9
  @projects = Project \
10
- .includes(:owners)
11
- .includes(:maintainers)
12
10
  .includes(:head)
13
11
  .unretired
14
12
  @test_runs = TestRun.most_recent.index_by(&:project_id)
@@ -23,13 +21,14 @@ class ProjectsController < ApplicationController
23
21
 
24
22
  def new
25
23
  @title = "New Project"
26
-
27
- @project = Project.new
28
- @project.roles.build(user: current_user) if @project.roles.none?
24
+ @team = Team.find params[:team_id]
25
+ @project = @team.projects.build
26
+ authorize! :create, @project
29
27
  end
30
28
 
31
29
  def new_from_github
32
- authorize! :create, Project
30
+ @team = Team.find params[:team_id]
31
+ authorize! :create, @team.projects.build
33
32
 
34
33
  existing_projects = Project.unscoped.where("props->>'git.location' LIKE '%github.com%'")
35
34
  github_repos = Houston.benchmark "Fetching repos" do
@@ -49,14 +48,15 @@ class ProjectsController < ApplicationController
49
48
 
50
49
 
51
50
  def create_from_github
52
- authorize! :create, Project
51
+ @team = Team.find params[:team_id]
52
+ authorize! :create, @team.projects.build
53
53
 
54
54
  repos = params.fetch(:repos, [])
55
55
  projects = Project.transaction do
56
56
  repos.map do |repo|
57
57
  owner, name = repo.split("/")
58
58
  title = name.humanize.gsub(/\b(?<!['’.`])[a-z]/) { $&.capitalize }.gsub("-", "::")
59
- Project.create!(
59
+ @team.projects.create!(
60
60
  name: title,
61
61
  slug: name,
62
62
  version_control_name: "Git",
@@ -65,7 +65,7 @@ class ProjectsController < ApplicationController
65
65
  end
66
66
 
67
67
  flash[:notice] = "#{projects.count} projects added"
68
- redirect_to projects_path
68
+ redirect_to teams_path
69
69
 
70
70
  rescue ActiveRecord::RecordInvalid
71
71
  flash[:error] = $!.message
@@ -75,8 +75,6 @@ class ProjectsController < ApplicationController
75
75
 
76
76
  def edit
77
77
  @project = Project.find_by_slug!(params[:id])
78
- @project.roles.build(user: current_user) if @project.roles.none?
79
-
80
78
  @title = "Edit #{@project.name}"
81
79
  end
82
80
 
@@ -85,7 +83,7 @@ class ProjectsController < ApplicationController
85
83
  @project = Project.new(project_attributes)
86
84
 
87
85
  if @project.save
88
- redirect_to projects_path, notice: 'Project was successfully created.'
86
+ redirect_to teams_path, notice: 'Project was successfully created.'
89
87
  else
90
88
  flash.now[:error] = @project.errors[:base].join("\n")
91
89
  render action: "new"
@@ -0,0 +1,60 @@
1
+ class TeamsController < ApplicationController
2
+ before_action :find_team, only: [:edit, :update]
3
+ load_and_authorize_resource
4
+
5
+
6
+ def index
7
+ @title = "Teams"
8
+ @teams = Team.all
9
+ end
10
+
11
+
12
+ def new
13
+ @title = "New Team"
14
+ @team = Team.new
15
+ @team.roles.build(user: current_user, roles: ["Team Owner"]) if @team.roles.none?
16
+ end
17
+
18
+
19
+ def create
20
+ @team = Team.new(team_attributes)
21
+
22
+ if @team.save
23
+ redirect_to teams_path, notice: "Team was successfully created."
24
+ else
25
+ flash.now[:error] = @team.errors[:base].join("\n")
26
+ render action: "new"
27
+ end
28
+ end
29
+
30
+
31
+ def edit
32
+ @title = "Edit #{@team.name}"
33
+ @team.roles.build(user: current_user, roles: ["Team Owner"]) if @team.roles.none?
34
+ end
35
+
36
+
37
+ def update
38
+ @team.props.merge! team_attributes.delete(:props) if team_attributes.key?(:props)
39
+
40
+ if @team.update_attributes(team_attributes)
41
+ redirect_to teams_path, notice: "Team was successfully updated."
42
+ else
43
+ flash.now[:error] = @team.errors[:base].join("\n")
44
+ render action: "edit"
45
+ end
46
+ end
47
+
48
+
49
+ private
50
+
51
+ def find_team
52
+ @team = Team.find(params[:id])
53
+ end
54
+
55
+ def team_attributes
56
+ params.fetch(:team)
57
+ # params.require(:team).permit(:name, :roles_attributes)
58
+ end
59
+
60
+ end
@@ -1,15 +1,11 @@
1
1
  class UsersController < ApplicationController
2
- before_filter :extract_administrator, :only => [:update, :create]
2
+ before_filter :extract_role, :only => [:update, :create]
3
3
  load_and_authorize_resource
4
4
 
5
5
 
6
6
  def index
7
- @title = "Team"
7
+ @title = "Users"
8
8
  @users = User.unretired
9
-
10
- @ticket_stats_by_user = @users.each_with_object({}) do |user, stats|
11
- stats[user] = stats_for_user(user)
12
- end
13
9
  end
14
10
 
15
11
 
@@ -43,7 +39,7 @@ class UsersController < ApplicationController
43
39
  if params[:send_invitation]
44
40
  User.invite!(params[:user])
45
41
  else
46
- @user.administrator = @administrator
42
+ @user.role = @role
47
43
  @user.save!
48
44
  end
49
45
 
@@ -57,7 +53,7 @@ class UsersController < ApplicationController
57
53
 
58
54
  def update
59
55
  @user = User.find(params[:id])
60
- @user.administrator = @administrator
56
+ @user.role = @role
61
57
 
62
58
  attributes = params[:user]
63
59
  attributes[:alias_emails] = attributes.fetch(:alias_emails, "").split.map(&:strip)
@@ -83,9 +79,13 @@ class UsersController < ApplicationController
83
79
  private
84
80
 
85
81
 
86
- def extract_administrator
87
- @administrator = params[:user].delete(:administrator) == "1"
88
- @administrator = false unless current_user.administrator?
82
+ def extract_role
83
+ @role = params[:user].delete(:role)
84
+ if current_user.owner?
85
+ @role = "Owner" if current_user.id == params[:id].to_i # Owners can't demote themselves
86
+ else
87
+ @role = "Member" # Others can't promote themselves
88
+ end
89
89
  end
90
90
 
91
91
 
@@ -106,7 +106,7 @@ private
106
106
 
107
107
  def user_params
108
108
  params.require(:user).permit(:first_name, :last_name, :email,
109
- :role, :password, :password_confirmation, :remember_me,
109
+ :password, :password_confirmation, :remember_me,
110
110
  :environments_subscribed_to, :view_options, :alias_emails)
111
111
  end
112
112
 
@@ -49,16 +49,14 @@ module CommitHelper
49
49
 
50
50
  message.gsub! Commit::EXTRA_ATTRIBUTE_PATTERN do |match|
51
51
  key, value = match.scan(Commit::EXTRA_ATTRIBUTE_PATTERN).first
52
- link_to_err(project, value) if key == "err"
52
+ format_extra_attribute(key, value)
53
53
  end
54
54
 
55
55
  message.html_safe
56
56
  end
57
57
 
58
- def link_to_err(project, err)
59
- link_to project.error_tracker_error_url(err), "target" => "_blank" do
60
- (image_tag(image_url("bug-fixed-32.png"), "data-tooltip-placement" => "right", rel: "tooltip", title: "View Exception in Errbit", width: 16, height: 16) + err).html_safe
61
- end
58
+ def format_extra_attribute(key, value)
59
+ "<span class=\"commit-extra-attribute\"><span class=\"commit-extra-attribute-key\">#{key}</span><span class=\"commit-extra-attribute-value\">#{value}</span></span>"
62
60
  end
63
61
 
64
62
  def commit_test_message(commit)
@@ -5,7 +5,7 @@ module ExposureHelper
5
5
  end
6
6
 
7
7
  def beta
8
- yield if current_user && current_user.administrator?
8
+ yield if current_user && current_user.owner?
9
9
  end
10
10
 
11
11
  end
@@ -22,17 +22,4 @@ module TicketHelper
22
22
  "#{feature}#{message}".html_safe
23
23
  end
24
24
 
25
-
26
-
27
- def format_antecedent(antecedent)
28
- case antecedent.kind
29
- when "Goldmine"; "Goldmine #{link_to_goldmine_case(antecedent.id)}".html_safe
30
- when "Errbit"; "Errbit #{link_to_err(antecedent.project, antecedent.id)}".html_safe
31
- end
32
- end
33
-
34
- def link_to_goldmine_case(number)
35
- link_to "##{number}", goldmine_case_number_url(number), target: "_blank"
36
- end
37
-
38
25
  end
@@ -8,16 +8,11 @@ class TicketReport
8
8
  :reporter_email,
9
9
  :reporter_first_name,
10
10
  :reporter_last_name,
11
- :antecedents,
12
11
  :opened_at,
13
12
  :closed_at,
14
13
  :milestone_id,
15
14
  :milestone_name)
16
15
 
17
- def antecedents
18
- (super || []).map { |s| TicketAntecedent.from_s(self, s) }
19
- end
20
-
21
16
  def reporter_name
22
17
  "#{reporter_first_name} #{reporter_last_name}"
23
18
  end
@@ -33,7 +28,6 @@ class TicketReport
33
28
  milestone: milestone_id && {
34
29
  id: milestone_id,
35
30
  name: milestone_name },
36
- antecedents: antecedents.map { |antecedent| { id: antecedent.id, kind: antecedent.kind } },
37
31
  openedAt: opened_at,
38
32
  closedAt: closed_at }
39
33
  end
@@ -55,7 +49,6 @@ class TicketReport
55
49
  "users.email",
56
50
  "users.first_name",
57
51
  "users.last_name",
58
- :antecedents,
59
52
  :created_at,
60
53
  :closed_at,
61
54
  "milestones.id",
@@ -10,22 +10,16 @@ class ProjectNotification < ViewMailer
10
10
  mail({
11
11
  from: release.user,
12
12
  to: options.fetch(:to, @release.notification_recipients),
13
- cc: options.fetch(:cc, @project.maintainers),
14
13
  subject: "new release to #{release.environment_name}",
15
14
  template: "new_release"
16
15
  })
17
16
  end
18
17
 
19
18
 
20
- def test_results(test_run, options={})
19
+ def test_results(test_run, recipients, options={})
21
20
  @test_run = test_run
22
21
  @project = test_run.project
23
22
 
24
- committers = test_run.commits_since_last_test_run.map { |commit| commit.author_email.downcase }
25
- recipients = (committers + Array(test_run.agent_email)).uniq \
26
- - @project.maintainers.map(&:email) \
27
- + @project.maintainers
28
-
29
23
  mail({
30
24
  to: recipients,
31
25
  subject: test_run_summary(test_run),
@@ -65,28 +59,13 @@ class ProjectNotification < ViewMailer
65
59
  @additional_info = options[:additional_info]
66
60
 
67
61
  mail({
68
- to: options.fetch(:to, @project.maintainers),
62
+ to: options.fetch(:to, @project.team_owners),
69
63
  subject: "configuration error",
70
64
  template: "ci_configuration_error"
71
65
  })
72
66
  end
73
67
 
74
68
 
75
- def follow_up(antecedent)
76
- @antecedent = antecedent
77
- @ticket = antecedent.ticket
78
- @project = @ticket.project
79
- @reporter = antecedent.reporter
80
- @customer = @antecedent.customer
81
-
82
- mail({
83
- to: @reporter,
84
- subject: "Sample Ticket follow-up",
85
- template: "follow_up"
86
- })
87
- end
88
-
89
-
90
69
  protected
91
70
 
92
71
 
@@ -23,7 +23,6 @@ class ViewMailer < ActionMailer::Base
23
23
  houston/application/markdown.scss
24
24
  houston/application/test_run.scss
25
25
  houston/application/releases.scss
26
- houston/application/follow_up.scss
27
26
  }
28
27
 
29
28
  helper_method :can?, :cannot?, :current_ability, :stylesheets
@@ -4,9 +4,30 @@ class Ability
4
4
 
5
5
 
6
6
  def initialize(user)
7
- if user && user.administrator?
8
- can :manage, :all
9
- elsif Houston.config.defines_abilities?
7
+ if user
8
+
9
+ # Owners can do everything
10
+
11
+ if user.owner?
12
+ can :manage, :all
13
+ return
14
+ end
15
+
16
+ # Admins can create teams
17
+
18
+ if user.admin?
19
+ can [:read, :create], Team
20
+ end
21
+
22
+ # Users get abilities based on their role
23
+ # in any teams they are members of
24
+
25
+ user.roles.each do |role|
26
+ Houston.config.configure_team_abilities(self, role)
27
+ end
28
+ end
29
+
30
+ if Houston.config.defines_abilities?
10
31
  Houston.config.configure_abilities(self, user)
11
32
  else
12
33
  default_abilities_for(user)
@@ -16,25 +37,13 @@ class Ability
16
37
 
17
38
 
18
39
  def default_abilities_for(user)
40
+ return unless user
19
41
 
20
- # Anyone can see everything
42
+ # If you're logged in, you can see everything
21
43
  can :read, :all
22
44
 
23
- if user
24
-
25
- # If you're logged in, you can update yourself
26
- can :update, user
27
-
28
- if user.developer?
29
-
30
- # Developers can manage projects and releases
31
- can :manage, Project
32
- can :manage, Release
33
- can :manage, Sprint
34
-
35
- end
36
- end
37
-
45
+ # If you're logged in, you can update yourself
46
+ can :update, user
38
47
  end
39
48
 
40
49
 
@@ -145,10 +145,6 @@ class Commit < ActiveRecord::Base
145
145
  parsed_message[:attributes]
146
146
  end
147
147
 
148
- def antecedents
149
- extra_attributes.fetch("err", []).map { |id| TicketAntecedent.new(self, "Errbit", id) }
150
- end
151
-
152
148
 
153
149
 
154
150
  def committer_hours