houston-core 0.6.0 → 0.6.1

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +69 -68
  3. data/app/adapters/houston/adapters/deployment/engineyard.rb +1 -1
  4. data/app/adapters/houston/adapters/version_control/git_adapter/github_repo.rb +19 -0
  5. data/app/adapters/houston/adapters/version_control/git_adapter/remote_repo.rb +27 -0
  6. data/app/assets/images/drag-grip.png +0 -0
  7. data/app/assets/javascripts/app/infinite_scroll.coffee +1 -1
  8. data/app/assets/javascripts/app/views/_show_sprint_view.coffee +9 -9
  9. data/app/assets/javascripts/application.js +1 -0
  10. data/app/assets/javascripts/core/app.coffee +5 -0
  11. data/app/assets/javascripts/{app → core}/stacked_area_graph.coffee +0 -0
  12. data/app/assets/javascripts/{app → core}/stacked_bar_graph.coffee +0 -0
  13. data/app/assets/javascripts/dashboard.js +1 -0
  14. data/app/assets/javascripts/vendor.js +0 -1
  15. data/app/assets/stylesheets/application/exceptions.scss +3 -1
  16. data/app/assets/stylesheets/application/navigation.scss +84 -21
  17. data/app/assets/stylesheets/application/releases.scss +32 -2
  18. data/app/assets/stylesheets/application/test.scss +34 -0
  19. data/app/assets/stylesheets/core/colors.scss.erb +33 -3
  20. data/app/assets/stylesheets/dashboard/dashboard.scss +11 -7
  21. data/app/assets/stylesheets/variables.scss +3 -0
  22. data/app/concerns/belongs_to_commit.rb +14 -0
  23. data/app/concerns/project_adapter.rb +24 -6
  24. data/app/controllers/api/v1/projects_controller.rb +18 -0
  25. data/app/controllers/api/v1/sprint_tasks_controller.rb +1 -1
  26. data/app/controllers/deploys_controller.rb +1 -0
  27. data/app/controllers/project_tests_controller.rb +49 -19
  28. data/app/controllers/releases_controller.rb +5 -0
  29. data/app/controllers/test_runs_controller.rb +16 -1
  30. data/app/helpers/test_run_helper.rb +24 -0
  31. data/app/models/deploy.rb +13 -0
  32. data/app/models/github/pull_request.rb +39 -4
  33. data/app/models/release.rb +42 -0
  34. data/app/models/task.rb +3 -2
  35. data/app/models/test_run.rb +4 -0
  36. data/app/presenters/project_presenter.rb +28 -0
  37. data/app/views/deploys/show.html.erb +4 -0
  38. data/app/views/github/pulls/index.html.erb +4 -1
  39. data/app/views/layouts/_mobile_navigation.html.erb +14 -17
  40. data/app/views/layouts/_navigation.html.erb +87 -87
  41. data/app/views/layouts/dashboard.html.erb +2 -2
  42. data/app/views/project_tests/index.html.erb +22 -7
  43. data/app/views/releases/_index.html.erb +65 -0
  44. data/app/views/releases/_results.html.erb +47 -0
  45. data/app/views/releases/index.html.erb +29 -65
  46. data/app/views/sprints/dashboard.html.erb +4 -2
  47. data/config/environments/production.rb +1 -1
  48. data/config/environments/test.rb +4 -1
  49. data/config/initializers/add_navigation_renderers.rb +6 -0
  50. data/config/initializers/requirements.rb +1 -0
  51. data/config/routes.rb +3 -0
  52. data/db/migrate/20151226154901_add_search_vector_to_releases.rb +6 -0
  53. data/db/migrate/20151226155305_generate_index_on_releases.rb +5 -0
  54. data/db/migrate/20151228183704_drop_unused_tables.rb +35 -0
  55. data/db/migrate/20160120145757_add_successful_to_deploys.rb +10 -0
  56. data/db/structure.sql +19 -67
  57. data/houston.gemspec +3 -3
  58. data/lib/configuration.rb +4 -2
  59. data/lib/core_ext/array.rb +37 -0
  60. data/lib/houston/version.rb +1 -1
  61. data/test/integration/ci_integration_test.rb +14 -13
  62. data/test/unit/models/project_test.rb +33 -0
  63. data/test/unit/models/pull_request_test.rb +71 -1
  64. metadata +24 -14
  65. data/app/models/historical_head.rb +0 -5
@@ -66,8 +66,9 @@ class Task < ActiveRecord::Base
66
66
  joins(:sprint).where("sprints.end_date >= current_date")
67
67
  end
68
68
 
69
- def checked_out_by(user)
70
- where(checked_out_by_id: user.id)
69
+ def checked_out_by(user, during: nil)
70
+ raise ArgumentError, "Please specify :during which Sprint" unless during
71
+ all.merge(SprintTask.where(sprint_id: during.id))
71
72
  end
72
73
 
73
74
  def find_by_project_and_shorthand(project_slug, shorthand)
@@ -36,6 +36,10 @@ class TestRun < ActiveRecord::Base
36
36
  where arel_table[:id].not_in(ids)
37
37
  end
38
38
 
39
+ def pending
40
+ where completed_at: nil
41
+ end
42
+
39
43
  def completed
40
44
  where arel_table[:completed_at].not_eq(nil)
41
45
  end
@@ -0,0 +1,28 @@
1
+ class ProjectPresenter
2
+ include UrlHelper
3
+
4
+ def initialize(projects)
5
+ @projects = OneOrMany.new(projects)
6
+ end
7
+
8
+ def as_json(*args)
9
+ projects = @projects
10
+ projects = Houston.benchmark "[#{self.class.name.underscore}] Load objects" do
11
+ projects.load
12
+ end if projects.is_a?(ActiveRecord::Relation)
13
+ Houston.benchmark "[#{self.class.name.underscore}] Prepare JSON" do
14
+ projects.map(&method(:project_to_json))
15
+ end
16
+ end
17
+
18
+ def project_to_json(project)
19
+ { id: project.id,
20
+ name: project.name,
21
+ slug: project.slug,
22
+ color: {
23
+ name: project.color,
24
+ hex: project.color_value.hex },
25
+ props: project.extended_attributes }
26
+ end
27
+
28
+ end
@@ -20,6 +20,10 @@
20
20
  Completed: <b><%= @deploy.completed_at %></b>
21
21
  </p>
22
22
 
23
+ <p>
24
+ Succeeded: <b><%= @deploy.succeeded? %></b>
25
+ </p>
26
+
23
27
  <p>
24
28
  Duration: <b><%= @deploy.duration %></b> seconds
25
29
  </p>
@@ -37,7 +37,9 @@
37
37
  <%= image_tag pull.avatar_url, size: "32", alt: pull.username, class: "avatar avatar-not-our-user" %>
38
38
  <% end %>
39
39
  </td>
40
- <td class="pull-request-project"><%= pull.project.slug %></td>
40
+ <td class="pull-request-project">
41
+ <%= link_to pull.project.slug, pull.project.repo.pulls_url, class: "label #{pull.project.color}", target: "_blank" %>
42
+ </td>
41
43
  <td class="pull-request-title">
42
44
  <%= link_to emojify(pull.title), pull.url, target: "_blank" %>
43
45
  </td>
@@ -85,6 +87,7 @@
85
87
  $('.pull-request').each(function() {
86
88
  var $pull = $(this),
87
89
  classes = $pull.attr('class').split(' '); classes.shift();
90
+ classes = _.filter(classes, function(str) { return str; });
88
91
  $pull.toggle(_.all(classes, function(cssClass) {
89
92
  return _.contains(visibleClasses, cssClass);
90
93
  }));
@@ -1,23 +1,20 @@
1
1
  <div class="navbar navbar-fixed-top navbar-inverse">
2
2
  <div class="navbar-inner">
3
- <div class="container-fluid">
4
- <%= link_to Houston.config.title, main_app.root_url, class: "brand" %>
3
+ <%= link_to Houston.config.title, main_app.root_url, class: "brand" %>
5
4
 
6
- <ul class="nav pull-right nav-inline">
7
- <% if current_user -%>
8
- <li class="current-user dropdown">
9
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= avatar_for(current_user, size: 30) %> <b class="caret"></b></a>
10
- <ul class="dropdown-menu">
11
- <li><%= link_to "Settings", main_app.edit_user_path(current_user) %></li>
12
- <li><%= link_to "Sign out", main_app.destroy_user_session_path %></li>
13
- </ul>
14
- </li>
15
- <% else -%>
16
- <li><%= link_to "Sign in", main_app.new_user_session_path %></li>
17
- <% end -%>
18
- </ul>
19
-
20
- </div>
5
+ <ul class="nav pull-right nav-inline">
6
+ <% if current_user -%>
7
+ <li class="current-user dropdown">
8
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= avatar_for(current_user, size: 30) %> <b class="caret"></b></a>
9
+ <ul class="dropdown-menu">
10
+ <li><%= link_to "Settings", main_app.edit_user_path(current_user) %></li>
11
+ <li><%= link_to "Sign out", main_app.destroy_user_session_path %></li>
12
+ </ul>
13
+ </li>
14
+ <% else -%>
15
+ <li><%= link_to "Sign in", main_app.new_user_session_path %></li>
16
+ <% end -%>
17
+ </ul>
21
18
  </div>
22
19
  </div>
23
20
 
@@ -1,96 +1,96 @@
1
1
  <div class="navbar navbar-fixed-top navbar-inverse">
2
2
  <div class="navbar-inner">
3
- <div class="container-fluid">
4
- <%= link_to Houston.config.title, main_app.root_url, class: "brand" %>
5
-
6
- <ul class="nav pull-right">
7
- <% if current_user -%>
8
- <li class="current-user dropdown">
9
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= avatar_for(current_user, size: 30) %> <b class="caret"></b></a>
10
- <ul class="dropdown-menu">
11
- <li><%= link_to "Settings", main_app.edit_user_path(current_user) %></li>
12
- <li><%= link_to "Sign out", main_app.destroy_user_session_path %></li>
13
- </ul>
14
- </li>
15
- <% else -%>
16
- <li><%= link_to "Sign in", main_app.new_user_session_path %></li>
17
- <% end -%>
18
- </ul>
19
- <ul class="nav">
20
-
21
- <% if current_user -%>
22
- <li class="dropdown current-project <%= current_project && current_project.color %>">
23
- <a href="#" title="Feedback" class="dropdown-toggle" data-toggle="dropdown">
24
- <%= current_project ? current_project.name : "Select Project" %>
25
- </a>
26
- <ul class="dropdown-menu">
27
- <% followed_projects.each do |project| %>
28
- <% if project == current_project %>
29
- <li class="current">
30
- <b class="bubble <%= project.color %>"></b> <%= project.name %></a>
31
- </li>
32
- <% else %>
33
- <li>
34
- <% path = if !current_feature
35
- # we're not on a project page,
36
- # just refresh the page and set the project
37
- "?project=#{project.slug}"
38
- elsif !project.features.include?(current_feature)
39
- # we're using a feature that this project
40
- # doesn't support. Navigate to the root URL
41
- # and set the project
42
- main_app.root_path(project: project.slug)
43
- else
44
- feature_path(project, current_feature)
45
- end %>
46
- <%= link_to path do %>
47
- <b class="bubble <%= project.color %>"></b> <%= project.name %></a>
48
- <% end %>
49
- </li>
50
- <% end %>
3
+ <%= link_to Houston.config.title, main_app.root_url, class: "brand" %>
4
+
5
+ <ul class="nav pull-right">
6
+ <% if current_user -%>
7
+ <li class="current-user dropdown">
8
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= avatar_for(current_user, size: 30) %> <b class="caret"></b></a>
9
+ <ul class="dropdown-menu">
10
+ <li><%= link_to "Settings", main_app.edit_user_path(current_user) %></li>
11
+ <li><%= link_to "Sign out", main_app.destroy_user_session_path %></li>
12
+ </ul>
13
+ </li>
14
+ <% else -%>
15
+ <li><%= link_to "Sign in", main_app.new_user_session_path %></li>
16
+ <% end -%>
17
+ </ul>
18
+ <ul class="nav">
19
+
20
+ <% Houston.config.navigation.each do |navigation| %><%= render_navigation navigation %><% end %>
21
+
22
+ <li class="divider-vertical"></li>
23
+
24
+ <% if can?(:read, Project) -%>
25
+ <%= render_nav_link "Projects", main_app.projects_path, icon: "fa-database" %>
26
+ <% end -%>
27
+
28
+ <% if can?(:read, User) -%>
29
+ <%= render_nav_link "Team", main_app.users_path, icon: "fa-user" %>
30
+ <% end -%>
31
+
32
+ <% if can?(:read, :job) -%>
33
+ <%= render_nav_link "Jobs", main_app.jobs_path, icon: "fa-user" %>
34
+ <% end -%>
35
+
36
+ </ul>
37
+ </div>
38
+ </div>
39
+
40
+ <% if current_user -%>
41
+ <div class="navbar project-navbar <%= current_project.color %>">
42
+ <ul class="nav">
43
+
44
+ <li class="dropdown current-project <%= current_project && current_project.color %>">
45
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
46
+ <%= current_project ? current_project.name : "Select Project" %>
47
+ </a>
48
+ <ul class="dropdown-menu">
49
+ <% followed_projects.each do |project| %>
50
+ <% if project == current_project %>
51
+ <li class="current">
52
+ <b class="bubble <%= project.color %>"></b> <%= project.name %></a>
53
+ </li>
54
+ <% else %>
55
+ <li>
56
+ <% path = if !current_feature
57
+ # we're not on a project page,
58
+ # just refresh the page and set the project
59
+ "?project=#{project.slug}"
60
+ elsif !project.features.include?(current_feature)
61
+ # we're using a feature that this project
62
+ # doesn't support. Navigate to the root URL
63
+ # and set the project
64
+ main_app.root_path(project: project.slug)
65
+ else
66
+ feature_path(project, current_feature)
67
+ end %>
68
+ <%= link_to path do %>
69
+ <b class="bubble <%= project.color %>"></b> <%= project.name %></a>
51
70
  <% end %>
52
- </ul>
53
- </li>
71
+ </li>
72
+ <% end %>
54
73
  <% end %>
55
-
56
-
57
-
58
- <% Houston.config.navigation.each do |navigation| %><%= render_navigation navigation %><% end %>
59
-
60
- <li class="divider-vertical"></li>
61
-
62
- <% if can?(:read, Project) -%>
63
- <%= render_nav_link "Projects", main_app.projects_path, icon: "fa-database" %>
64
- <% end -%>
65
-
66
- <% if can?(:read, User) -%>
67
- <%= render_nav_link "Team", main_app.users_path, icon: "fa-user" %>
68
- <% end -%>
69
-
70
- <% if can?(:read, :job) -%>
71
- <%= render_nav_link "Jobs", main_app.jobs_path, icon: "fa-user" %>
72
- <% end -%>
73
-
74
74
  </ul>
75
- </div>
76
- </div>
77
- </div>
75
+ </li>
78
76
 
79
- <% if current_project && current_project.persisted? %>
80
- <div class="project-navbar <%= current_project.color %>">
81
- <% if current_project.features.any? %>
82
- <ul class="nav">
83
- <% current_project.features.each do |feature| %>
84
- <%= render_nav_for_feature(feature) %>
85
- <% end %>
86
- </ul>
87
- <% else %>
88
- <div class="project-no-features">
89
- No features are enabled for <%= current_project.name %>.
90
- <% if can?(:update, current_project) %>
91
- You can enable features in <%= link_to "Project Settings", main_app.edit_project_path(current_project) %>.
77
+ <% if current_project && current_project.persisted? %>
78
+ <% if current_project.features.any? %>
79
+ <% current_project.features.each do |feature| %>
80
+ <% if feature == :settings %>
81
+ <li class="divider-vertical"></li>
82
+ <% end %>
83
+ <%= render_nav_for_feature(feature) %>
84
+ <% end %>
85
+ <% else %>
86
+ <li class="project-no-features">
87
+ No features are enabled for <%= current_project.name %>.
88
+ <% if can?(:update, current_project) %>
89
+ You can enable features in <%= link_to "Project Settings", main_app.edit_project_path(current_project) %>.
90
+ <% end %>
91
+ </li>
92
92
  <% end %>
93
- </div>
94
- <% end %>
93
+ <% end %>
94
+ </ul>
95
95
  </div>
96
96
  <% end %>
@@ -27,10 +27,10 @@
27
27
  <link href="images/apple-touch-icon-114x114.png" rel="apple-touch-icon" sizes="114x114">
28
28
  </head>
29
29
  <body class="dashboard">
30
- <div id="container" <% if params[:zoom].to_f > 0 %> style="transform: scale(<%= params[:zoom].to_f %>); transform-origin: 50% 0; -webkit-transform: scale(<%= params[:zoom].to_f %>); -webkit-transform-origin: 50% 0; -moz-transform: scale(<%= params[:zoom].to_f %>); -moz-transform-origin: 50% 0;" <% end %>>
30
+ <div id="container" <% if params[:zoom].to_f > 0 %> style="transform: scale(<%= params[:zoom].to_f %>); transform-origin: 50% 0; -webkit-transform: scale(<%= params[:zoom].to_f %>); -webkit-transform-origin: 50% 0; -moz-transform: scale(<%= params[:zoom].to_f %>); -moz-transform-origin: 50% 0; width: <%= (1 / params[:zoom].to_f) * 100 %>%; height: <%= (1 / params[:zoom].to_f) * 100 %>%;" <% end %>>
31
31
  <%= yield -%>
32
32
  </div>
33
-
33
+
34
34
  <!-- Le javascript
35
35
  ================================================== -->
36
36
  <!-- Placed at the end of the document so the pages load faster -->
@@ -10,21 +10,31 @@
10
10
  <th class="test-name sort-asc">Name</th>
11
11
  <th class="test-passes">Passes</th>
12
12
  <th class="test-fails">Fails</th>
13
+ <th class="test-graph">Graph</th>
14
+ <th class="test-duration">Duration</th>
13
15
  <td class="table-margin"></td>
14
16
  </tr>
15
17
  </thead>
16
18
  <tbody>
17
- <% @tests.each do |(id, suite, name, passes, fails)| %>
19
+ <% @tests.each do |test| %>
18
20
  <tr class="test">
19
21
  <td class="table-margin"></td>
20
22
  <td class="test-name">
21
- <%= link_to project_test_url(slug: @project.slug, id: id) do %>
22
- <span class="test-suite-name"><%= suite.gsub("__", "::") %></span>
23
- <span class="test-name"><%= name.to_s.gsub(/^(test :|: )/, "") %></span>
23
+ <%= link_to project_test_url(slug: @project.slug, id: test[:id]) do %>
24
+ <span class="test-suite-name"><%= test[:suite].gsub("__", "::") %></span>
25
+ <span class="test-name"><%= test[:name].to_s.gsub(/^(test :|: )/, "") %></span>
24
26
  <% end %>
25
27
  </td>
26
- <td class="test-passes <%= "zero" if passes.zero? %>"><%= passes %></td>
27
- <td class="test-fails <%= "zero" if fails.zero? %>"><%= fails %></td>
28
+ <td class="test-passes"><%= test_results_pass_count(test)%></td>
29
+ <td class="test-fails"><%= test_results_fail_count(test)%></td>
30
+ <td class="test-graph" data-position="<%= test_results_count(test) %>"><%= test_results_graph(test) %></td>
31
+ <td class="test-duration">
32
+ <span class="test-duration-average"><%= test[:duration_avg].to_i %>ms</span>
33
+ <span class="test-duration-range">
34
+ <%= test[:duration5].to_i %>ms &ndash; <%= test[:duration95].to_i %>ms
35
+ </span>
36
+ </td>
37
+ <td class="table-margin"></td>
28
38
  </tr>
29
39
  <% end %>
30
40
  </tbody>
@@ -34,7 +44,12 @@
34
44
  <% content_for :javascripts do %>
35
45
  <script type="text/javascript">
36
46
  $(function() {
37
- $('#project_tests').tablesorter();
47
+ $('#project_tests').tablesorter({
48
+ headers: {
49
+ 4: {sorter: 'property'},
50
+ 5: {sorter: 'digit'}
51
+ }
52
+ });
38
53
  });
39
54
  </script>
40
55
  <% end %>
@@ -0,0 +1,65 @@
1
+ <% if @deploys.none? %>
2
+
3
+ <div class="alert alert-info">
4
+ There have been no deploys of <b><%= @project.name %></b> to <b><%= @environment %></b> recorded.
5
+ </div>
6
+
7
+ <% else %>
8
+
9
+ <% date = nil %>
10
+ <div id="<%= @project.slug %>_changelog" class="-houston-changelog">
11
+ <% @deploys.each do |deploy| %>
12
+ <% deploy.project = @project; release = deploy.release %>
13
+ <% next if release.nil? && deploy.commit.nil? %>
14
+
15
+ <% if date.nil? || date != deploy.date %>
16
+ <% if date %></div><% end %><%# end .-houston-changelog-day %>
17
+ <div class="-houston-changelog-day">
18
+ <h4><%= format_release_date(date = deploy.date) %></h4>
19
+ <% end %>
20
+
21
+ <% unless release %>
22
+ <div class="release release-deploy">
23
+ <p class="release-header">
24
+ <%= deploy.completed_at.strftime("%l:%M %p") %>&nbsp;&nbsp;
25
+ <% deploy.commit.project = @project %>
26
+ Deploy to <%= link_to_commit deploy.commit, style: "float: none;" %>
27
+
28
+ <span style="float: right;">
29
+ <%= link_to "New Release", new_release_path(slug: @project.slug, environment: @environment, deploy_id: deploy.id), class: "btn btn-mini btn-default" %>
30
+ </span>
31
+ </div>
32
+ <% else %>
33
+ <%= div_for(release) do %>
34
+ <% release.project = @project %>
35
+ <p class="release-header">
36
+ <%= release.released_at.strftime("%l:%M %p") %>&nbsp;&nbsp;
37
+ <%= link_to "details &rarr;".html_safe, release_url(release) %>
38
+
39
+ <% if can?(:read, @project.commits.build) %>
40
+ <span class="commit-range"><%= link_to_release_commit_range(release) %></span>
41
+ <% end %>
42
+ </p>
43
+
44
+ <% if release.release_changes.any? %>
45
+ <div class="release-changes">
46
+ <% ordered_by_tag(release.release_changes).each do |change| %>
47
+ <% if can?(:read, change) %>
48
+ <div class="change">
49
+ <%= format_change_tag change.tag %>
50
+ <div class="change-summary"><%= format_change(change) %></div>
51
+ </div>
52
+ <% end %>
53
+ <% end %>
54
+ </div>
55
+ <% else %>
56
+ <div class="release-no-changes">No changes</div>
57
+ <% end %>
58
+ <% end %>
59
+ <% end %>
60
+
61
+ <% end %>
62
+ <% if date %></div><% end %><%# end .-houston-changelog-day %>
63
+ </div>
64
+
65
+ <% end %>
@@ -0,0 +1,47 @@
1
+ <% if @releases.none? %>
2
+
3
+ <div class="alert alert-info">
4
+ No results found.
5
+ </div>
6
+
7
+ <% else %>
8
+
9
+ <% date = nil %>
10
+ <div id="<%= @project.slug %>_changelog" class="-houston-changelog release-search-result">
11
+ <% @releases.each do |release| %>
12
+ <% release.project = @project %>
13
+
14
+ <% if date.nil? || date != release.date %>
15
+ <% if date %></div><% end %><%# end .-houston-changelog-day %>
16
+ <div class="-houston-changelog-day">
17
+ <h4><%= format_release_date(date = release.date) %></h4>
18
+ <% end %>
19
+
20
+ <%= div_for(release) do %>
21
+ <% release.project = @project %>
22
+ <p class="release-header">
23
+ <%= release.released_at.strftime("%l:%M %p") %>&nbsp;&nbsp;
24
+ <%= link_to "details &rarr;".html_safe, release_url(release) %>
25
+
26
+ <% if can?(:read, @project.commits.build) %>
27
+ <span class="commit-range"><%= link_to_release_commit_range(release) %></span>
28
+ <% end %>
29
+ </p>
30
+
31
+ <div class="release-changes">
32
+ <% ordered_by_tag(release.release_changes).each do |change| %>
33
+ <% if can?(:read, change) %>
34
+ <div class="change">
35
+ <%= format_change_tag change.tag %>
36
+ <div class="change-summary"><%= format_change(change) %></div>
37
+ </div>
38
+ <% end %>
39
+ <% end %>
40
+ </div>
41
+ <% end %>
42
+
43
+ <% end %>
44
+ <% if date %></div><% end %><%# end .-houston-changelog-day %>
45
+ </div>
46
+
47
+ <% end %>