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.
- checksums.yaml +4 -4
- data/Gemfile.lock +45 -45
- data/app/assets/javascripts/houston/app/models/ticket.coffee +7 -5
- data/app/assets/javascripts/houston/app/views/new_ticket_view.coffee +1 -21
- data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +0 -6
- data/app/assets/stylesheets/houston/application/commit.scss +16 -0
- data/app/assets/stylesheets/houston/application/navigation.scss +1 -0
- data/app/assets/stylesheets/houston/application/new_ticket_view.scss +0 -4
- data/app/assets/stylesheets/houston/application/projects.css.scss +0 -14
- data/app/assets/stylesheets/houston/application/release_form.scss +1 -1
- data/app/assets/stylesheets/houston/application/teams.scss +68 -0
- data/app/assets/templates/tickets/index.hbs +0 -1
- data/app/controllers/github/pulls_controller.rb +1 -0
- data/app/controllers/project_tickets_controller.rb +1 -5
- data/app/controllers/projects_controller.rb +10 -12
- data/app/controllers/teams_controller.rb +60 -0
- data/app/controllers/users_controller.rb +12 -12
- data/app/helpers/commit_helper.rb +3 -5
- data/app/helpers/exposure_helper.rb +1 -1
- data/app/helpers/ticket_helper.rb +0 -13
- data/app/interactors/ticket_report.rb +0 -7
- data/app/mailers/project_notification.rb +2 -23
- data/app/mailers/view_mailer.rb +0 -1
- data/app/models/ability.rb +28 -19
- data/app/models/commit.rb +0 -4
- data/app/models/project.rb +14 -29
- data/app/models/release.rb +0 -18
- data/app/models/role.rb +0 -22
- data/app/models/team.rb +43 -0
- data/app/models/team_user.rb +68 -0
- data/app/models/ticket.rb +2 -22
- data/app/models/user.rb +21 -30
- data/app/views/devise/sessions/new.html.erb +9 -7
- data/app/views/layouts/_mobile_navigation.html.erb +5 -3
- data/app/views/layouts/_navigation.html.erb +11 -10
- data/app/views/layouts/_tester_bar.html.erb +1 -1
- data/app/views/layouts/application.html.erb +1 -2
- data/app/views/project_tickets/_tickets.html.erb +0 -1
- data/app/views/project_tickets/index.xls.erb +0 -35
- data/app/views/project_tickets/new.html.erb +1 -2
- data/app/views/projects/_form.html.erb +7 -12
- data/app/views/projects/index.html.erb +10 -17
- data/app/views/releases/_changelog.html.erb +11 -14
- data/app/views/teams/_form.html.erb +45 -0
- data/app/views/teams/edit.html.erb +8 -0
- data/app/views/teams/index.html.erb +62 -0
- data/app/views/teams/new.html.erb +7 -0
- data/app/views/users/_form.html.erb +2 -11
- data/app/views/users/index.html.erb +8 -20
- data/app/views/users/new.html.erb +1 -1
- data/config/initializers/inflections.rb +7 -6
- data/config/routes.rb +19 -17
- data/db/migrate/20160812233255_repurpose_users_role.rb +16 -0
- data/db/migrate/20160813001242_create_teams.rb +42 -0
- data/db/structure.sql +110 -116
- data/lib/houston/boot.rb +0 -1
- data/lib/houston/boot/configuration.rb +26 -11
- data/lib/houston/boot/events.rb +0 -4
- data/lib/houston/version.rb +1 -1
- data/templates/new-instance/config/abilities.rb +68 -51
- data/templates/new-instance/config/conversations/mentions/unfurl_tasks.rb +1 -1
- data/templates/new-instance/config/events/deploy/notify_deployer_when_finished.rb +24 -16
- data/templates/new-instance/config/events/tests/email_when_completed.rb +11 -0
- data/templates/new-instance/config/integrations/ldap.rb +4 -0
- data/templates/new-instance/config/main.rb +10 -17
- data/templates/new-module/test/fixtures/users.yml +1 -2
- data/test/acceptance/creating_a_release_test.rb +1 -1
- data/test/factories/project_factory.rb +1 -0
- data/test/factories/user_factory.rb +3 -1
- data/test/fixtures/teams.yml +2 -0
- data/test/fixtures/teams_users.yml +5 -0
- data/test/fixtures/users.yml +1 -2
- data/test/integration/ci_integration_test.rb +2 -2
- data/test/support/config.rb +3 -5
- data/test/unit/controllers/deploys_controller_test.rb +11 -5
- data/test/unit/controllers/users_controller_test.rb +46 -0
- data/test/unit/models/release_test.rb +0 -9
- data/test/unit/models/serializer_test.rb +0 -8
- data/test/unit/models/ticket_test.rb +0 -32
- metadata +21 -24
- data/app/assets/javascripts/houston/app/table_row_expander.coffee +0 -52
- data/app/assets/javascripts/houston/app/views/problems_view.coffee +0 -114
- data/app/assets/stylesheets/houston/application/follow_up.scss +0 -44
- data/app/controllers/project_exceptions_controller.rb +0 -36
- data/app/controllers/project_pretickets_controller.rb +0 -27
- data/app/mailers/deploy_notification.rb +0 -33
- data/app/models/antecedent.rb +0 -15
- data/app/models/ticket_antecedent.rb +0 -39
- data/app/models/value_statement.rb +0 -9
- data/app/presenters/problem_presenter.rb +0 -49
- data/app/presenters/tester_presenter.rb +0 -15
- data/app/views/project_notification/follow_up.html.erb +0 -26
- data/app/views/project_pretickets/show.html.erb +0 -49
- data/app/views/releases/_antecedents.html.erb +0 -12
- data/config/initializers/hard_coded_knowledge.rb +0 -141
- data/db/migrate/20130427223925_create_project_quotas.rb +0 -14
- data/db/migrate/20140506035755_create_value_statements.rb +0 -9
- data/lib/houston/boot/ticket_antecedent_serializer.rb +0 -21
- 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 =
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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 :
|
2
|
+
before_filter :extract_role, :only => [:update, :create]
|
3
3
|
load_and_authorize_resource
|
4
4
|
|
5
5
|
|
6
6
|
def index
|
7
|
-
@title = "
|
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.
|
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.
|
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
|
87
|
-
@
|
88
|
-
|
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
|
-
:
|
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
|
-
|
52
|
+
format_extra_attribute(key, value)
|
53
53
|
end
|
54
54
|
|
55
55
|
message.html_safe
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
59
|
-
|
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)
|
@@ -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.
|
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
|
|
data/app/mailers/view_mailer.rb
CHANGED
data/app/models/ability.rb
CHANGED
@@ -4,9 +4,30 @@ class Ability
|
|
4
4
|
|
5
5
|
|
6
6
|
def initialize(user)
|
7
|
-
if user
|
8
|
-
|
9
|
-
|
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
|
-
#
|
42
|
+
# If you're logged in, you can see everything
|
21
43
|
can :read, :all
|
22
44
|
|
23
|
-
|
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
|
|
data/app/models/commit.rb
CHANGED