houston-core 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +94 -69
  3. data/app/adapters/houston/adapters/deployment/engineyard.rb +4 -3
  4. data/app/adapters/houston/adapters/version_control/git_adapter.rb +36 -42
  5. data/app/adapters/houston/adapters/version_control/git_adapter/github_repo.rb +2 -2
  6. data/app/adapters/houston/adapters/version_control/git_adapter/remote_repo.rb +23 -11
  7. data/app/adapters/houston/adapters/version_control/git_adapter/repo.rb +18 -8
  8. data/app/adapters/houston/adapters/version_control/null_repo.rb +8 -0
  9. data/app/assets/javascripts/core/handlebars_helpers.coffee +3 -3
  10. data/app/assets/stylesheets/application/github_repos.scss +77 -0
  11. data/app/assets/stylesheets/application/navigation.scss +2 -0
  12. data/app/assets/stylesheets/application/pull_requests.scss +44 -58
  13. data/app/assets/stylesheets/core/avatars.scss +5 -0
  14. data/app/assets/stylesheets/core/colors.scss.erb +10 -7
  15. data/app/concerns/commit_synchronizer.rb +3 -0
  16. data/app/controllers/github/pulls_controller.rb +12 -0
  17. data/app/controllers/project_tests_controller.rb +3 -3
  18. data/app/controllers/projects_controller.rb +45 -1
  19. data/app/controllers/releases_controller.rb +42 -26
  20. data/app/helpers/application_helper.rb +8 -0
  21. data/app/helpers/avatar_helper.rb +2 -2
  22. data/app/helpers/commit_helper.rb +2 -2
  23. data/app/helpers/oembed_helper.rb +8 -0
  24. data/app/helpers/project_helper.rb +4 -5
  25. data/app/helpers/release_helper.rb +11 -0
  26. data/app/helpers/timeline_helper.rb +1 -1
  27. data/app/helpers/url_helper.rb +0 -18
  28. data/app/interactors/cache_key_dependencies.rb +28 -0
  29. data/app/jobs/sync_all_tickets_job.rb +1 -0
  30. data/app/mailers/view_mailer.rb +0 -1
  31. data/app/models/commit.rb +1 -1
  32. data/app/models/github/pull_request.rb +82 -26
  33. data/app/models/github/pull_request_event.rb +2 -2
  34. data/app/models/milestone.rb +1 -0
  35. data/app/models/project.rb +14 -0
  36. data/app/models/project_dependencies.rb +5 -3
  37. data/app/models/task.rb +1 -1
  38. data/app/models/user.rb +41 -0
  39. data/app/views/commits/show.html.erb +9 -1
  40. data/app/views/github/pulls/index.html.erb +102 -0
  41. data/app/views/project_notification/new_release.html.erb +6 -0
  42. data/app/views/project_tickets/index.xls.erb +0 -7
  43. data/app/views/projects/_form.html.erb +29 -17
  44. data/app/views/projects/index.html.erb +3 -3
  45. data/app/views/projects/new_from_github.html.erb +67 -0
  46. data/app/views/releases/_commits.html.erb +1 -1
  47. data/app/views/releases/show.html.erb +9 -0
  48. data/app/views/users/_form.html.erb +35 -19
  49. data/config/application.rb +12 -0
  50. data/config/initializers/mime_types.rb +1 -0
  51. data/config/routes.rb +17 -3
  52. data/db/migrate/20151201042126_require_projects_to_have_name_and_slug.rb +6 -0
  53. data/db/migrate/20151202005557_add_head_sha_to_projects.rb +24 -0
  54. data/db/migrate/20151202011812_require_projects_to_have_color.rb +13 -0
  55. data/db/migrate/20151205204922_require_project_slugs_to_be_unique.rb +5 -0
  56. data/db/migrate/20151205214647_add_avatar_url_to_pull_requests.rb +5 -0
  57. data/db/migrate/20151209004458_add_json_labels_to_pull_requests.rb +5 -0
  58. data/db/migrate/20151209030113_add_timestamps_to_pull_requests.rb +6 -0
  59. data/db/structure.sql +31 -5
  60. data/houston.gemspec +7 -7
  61. data/lib/configuration.rb +3 -2
  62. data/lib/houston/version.rb +1 -1
  63. data/lib/rack/oembed.rb +23 -0
  64. data/templates/new-instance/config/jobs/cache_key_dependencies.rb +3 -0
  65. data/templates/new-instance/config/triggers/tests/slack_when_analyzed.rb +1 -4
  66. data/templates/new-instance/config/triggers/tests/slack_when_completed.rb +1 -1
  67. data/templates/new-instance/lib/slack_helpers.rb +1 -1
  68. data/test/integration/ticket_tasks_api_test.rb +1 -1
  69. data/test/unit/adapters/git_adapter_test.rb +29 -8
  70. data/test/unit/adapters/version_control_adapters_api_test.rb +2 -0
  71. data/test/unit/controllers/hooks_controller_test.rb +4 -4
  72. data/test/unit/models/commit_test.rb +2 -2
  73. data/test/unit/models/project_test.rb +2 -2
  74. data/test/unit/models/pull_request_test.rb +9 -4
  75. data/test/unit/models/task_test.rb +1 -1
  76. data/test/unit/models/ticket_test.rb +1 -1
  77. metadata +31 -16
@@ -6,7 +6,7 @@ module Houston
6
6
 
7
7
 
8
8
  def project_url
9
- location.to_s
9
+ location
10
10
  .gsub(/^git@(?:www\.)?github.com:/, "https://github.com/")
11
11
  .gsub(/^git:/, "https:")
12
12
  .gsub(/\.git$/, "")
@@ -28,7 +28,7 @@ module Houston
28
28
  end
29
29
 
30
30
  def repo_name
31
- location.path[0...-4]
31
+ Addressable::URI.parse(location).path[0...-4].gsub(/^\//, "")
32
32
  end
33
33
 
34
34
 
@@ -6,9 +6,10 @@ module Houston
6
6
  RETRY_COOLDOWN = 4 # seconds
7
7
 
8
8
 
9
- def initialize(connection, location)
10
- super(connection)
11
- @location = location
9
+
10
+ def initialize(git_path, location)
11
+ super location
12
+ @git_path = git_path.to_s
12
13
  @branch_location = :remote
13
14
  end
14
15
 
@@ -17,8 +18,6 @@ module Houston
17
18
  # Public API for a VersionControl::Adapter Repo
18
19
  # ------------------------------------------------------------------------- #
19
20
 
20
- attr_reader :location
21
-
22
21
  def refresh!(async: false)
23
22
  return clone!(async: async) unless exists?
24
23
  pull!(async: async)
@@ -26,14 +25,14 @@ module Houston
26
25
 
27
26
  # ------------------------------------------------------------------------- #
28
27
 
29
- def to_s
30
- location.to_s
31
- end
32
28
 
33
29
 
30
+ def git_path
31
+ @git_path
32
+ end
34
33
 
35
34
  def clone!(async: false)
36
- GitAdapter.clone!(location, connection.path, async: false)
35
+ async ? Houston.async { _clone!(true) } : _clone!(false)
37
36
  end
38
37
 
39
38
  def pull!(async: false)
@@ -48,6 +47,11 @@ module Houston
48
47
 
49
48
  protected
50
49
 
50
+ def connect!
51
+ clone! unless exists?
52
+ super
53
+ end
54
+
51
55
  def find_commit(sha)
52
56
  pull_and_retry { super(sha) }
53
57
  end
@@ -71,8 +75,16 @@ module Houston
71
75
  end
72
76
  end
73
77
 
78
+ def _clone!(async)
79
+ Houston.benchmark("[git:clone#{":async" if async}] #{location} => #{git_path}") do
80
+ Rugged::Repository.clone_at location, git_path,
81
+ credentials: GitAdapter.credentials,
82
+ bare: true
83
+ end
84
+ end
85
+
74
86
  def _pull!(async)
75
- Houston.benchmark("[git:pull#{":async" if async}] #{connection.path}") do
87
+ Houston.benchmark("[git:pull#{":async" if async}] #{location} => #{git_path}") do
76
88
  options = {credentials: GitAdapter.credentials}
77
89
 
78
90
  # Fetch
@@ -114,7 +126,7 @@ module Houston
114
126
  end
115
127
  rescue
116
128
  $!.additional_information[:repo] = to_s
117
- $!.additional_information[:path] = connection.path
129
+ $!.additional_information[:path] = git_dir
118
130
  raise
119
131
  ensure
120
132
  close
@@ -5,10 +5,12 @@ module Houston
5
5
  module VersionControl
6
6
  class GitAdapter
7
7
  class Repo
8
+ attr_reader :location
8
9
 
9
10
 
10
- def initialize(connection)
11
- @connection = connection
11
+
12
+ def initialize(location)
13
+ @location = location.to_s
12
14
  @branch_location = :local
13
15
  end
14
16
 
@@ -70,10 +72,6 @@ module Houston
70
72
  raise
71
73
  end
72
74
 
73
- def location
74
- connection.path
75
- end
76
-
77
75
  def native_commit(sha)
78
76
  return NullCommit.new if sha == Houston::NULL_GIT_COMMIT
79
77
  to_commit find_commit(sha)
@@ -92,7 +90,7 @@ module Houston
92
90
  end
93
91
 
94
92
  def exists?
95
- File.exists?(connection.path)
93
+ File.exists?(git_path)
96
94
  end
97
95
 
98
96
  # ------------------------------------------------------------------------- #
@@ -130,6 +128,10 @@ module Houston
130
128
  DiffChanges.new `git --git-dir=#{git_dir} diff --name-status #{old_sha} #{new_sha}`
131
129
  end
132
130
 
131
+ def git_path
132
+ location
133
+ end
134
+
133
135
  def to_s
134
136
  location
135
137
  end
@@ -164,7 +166,15 @@ module Houston
164
166
 
165
167
  protected
166
168
 
167
- attr_reader :connection, :branch_location
169
+ attr_reader :branch_location
170
+
171
+ def connection
172
+ @connection ||= connect!
173
+ end
174
+
175
+ def connect!
176
+ Rugged::Repository.new(git_path)
177
+ end
168
178
 
169
179
  def find_commit(sha)
170
180
  normalize_sha!(sha)
@@ -31,6 +31,10 @@ module Houston
31
31
  []
32
32
  end
33
33
 
34
+ def branch(name)
35
+ nil
36
+ end
37
+
34
38
  def commits_between(sha1, sha2)
35
39
  []
36
40
  end
@@ -50,6 +54,10 @@ module Houston
50
54
  def refresh!(async: false)
51
55
  end
52
56
 
57
+ def exists?
58
+ false
59
+ end
60
+
53
61
  # ------------------------------------------------------------------------- #
54
62
 
55
63
 
@@ -74,17 +74,17 @@ Handlebars.registerHelper 'linkToCommit', (commit)->
74
74
 
75
75
  Handlebars.registerHelper 'testerAvatar', (email, size, title)->
76
76
  tester = window.testers.findByEmail(email)
77
- gravatarUrl = "//www.gravatar.com/avatar/#{MD5(email.toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
77
+ gravatarUrl = "https://www.gravatar.com/avatar/#{MD5(email.toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
78
78
  "<img src=\"#{gravatarUrl}\" width=\"#{size}\" height=\"#{size}\" rel=\"tooltip\" title=\"#{tester.get('name')}\" />"
79
79
 
80
80
  Handlebars.registerHelper 'userAvatar', (size)->
81
81
  user = window.user
82
- gravatarUrl = "//www.gravatar.com/avatar/#{MD5(user.get('email').toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
82
+ gravatarUrl = "https://www.gravatar.com/avatar/#{MD5(user.get('email').toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
83
83
  "<img src=\"#{gravatarUrl}\" width=\"#{size}\" height=\"#{size}\" rel=\"tooltip\" title=\"#{user.get('name')}\" />"
84
84
 
85
85
  Handlebars.registerHelper 'avatar', (email, size, title)->
86
86
  return "<img class=\"avatar avatar-empty\" width=\"#{size}\" height=\"#{size}\" />" unless email
87
- gravatarUrl = "//www.gravatar.com/avatar/#{MD5(email.toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
87
+ gravatarUrl = "https://www.gravatar.com/avatar/#{MD5(email.toLowerCase().trim())}?r=g&d=retro&s=#{size * 2}"
88
88
  if title
89
89
  "<img src=\"#{gravatarUrl}\" class=\"avatar\" width=\"#{size}\" height=\"#{size}\" rel=\"tooltip\" title=\"#{title}\" />"
90
90
  else
@@ -0,0 +1,77 @@
1
+ #repos {
2
+ margin: 0;
3
+ padding: 0;
4
+ }
5
+
6
+ .repo {
7
+ display: block;
8
+ padding: 0 4px;
9
+ border-radius: 2px;
10
+
11
+ &:hover {
12
+ background: rgba(128, 212, 255, 0.1);
13
+ }
14
+
15
+ &.selected {
16
+ background: rgba(128, 212, 255, 0.25);
17
+ }
18
+
19
+ &.disabled {
20
+ background: #f9f9f9;
21
+ }
22
+
23
+ &.retired {
24
+ .repo-owner { color: #ddd; }
25
+ .repo-name > .label { opacity: 0.4; }
26
+ .repo-owner, .repo-name {
27
+ position: relative;
28
+
29
+ &::after {
30
+ display: block;
31
+ content: '.';
32
+ color: transparent;
33
+ position: absolute;
34
+ top: 0;
35
+ left: 0;
36
+ height: 50%;
37
+ width: 100%;
38
+ margin: 0;
39
+ border-bottom: 2px solid #555;
40
+ }
41
+ }
42
+ }
43
+
44
+ input[type="checkbox"] {
45
+ margin: 8px;
46
+ float: left;
47
+
48
+ &[disabled] + label {
49
+ color: #bbb;
50
+ }
51
+ }
52
+
53
+ label {
54
+ padding: 4px 0;
55
+ margin: 0;
56
+ }
57
+
58
+ .repo-visibility {
59
+ display: inline-block;
60
+ margin: 0 4px;
61
+
62
+ .fa { width: 14px; }
63
+ .fa-unlock { opacity: 0.1; }
64
+ }
65
+
66
+ .repo-owner {
67
+ &::after {
68
+ display: inline-block;
69
+ content: '/';
70
+ margin: 0 0.33em;
71
+ }
72
+ }
73
+
74
+ .repo-name b {
75
+ color: #505050;
76
+ }
77
+ }
@@ -22,6 +22,8 @@ $project-navbar-height: 30px;
22
22
 
23
23
  .navbar .brand {
24
24
  padding: 6px 20px 10px;
25
+ position: relative;
26
+ z-index: 1;
25
27
  }
26
28
 
27
29
  // Don't let the navbar wrap onto multiple lines
@@ -1,68 +1,54 @@
1
- h4.github-repo {
2
- margin: 1.33em 0 0.66em;
3
- font-weight: 500;
1
+ td.pull-request-avatar {
2
+ width: 32px;
4
3
 
5
- .pull-requests-count { vertical-align: middle; }
6
- }
7
-
8
- ul.pull-requests { margin: 0; }
9
-
10
- .pull-request {
11
- list-style-type: none;
12
- display: block;
13
- margin: 0;
14
- line-height: 24px;
15
-
16
- &.back-burner a {
17
- color: #c9c9c9;
18
-
19
- .pull-request-author { opacity: 0.16; }
20
- .pull-request-number { color: #d6d6d6; }
21
- .pull-request-age { color: #d6d6d6; }
22
- }
23
-
24
- a {
25
- display: block;
26
- padding: 0.33em 0;
27
-
28
- &:hover {
29
- text-decoration: none;
30
- background: #EDF9FF;
31
- color: #005580;
32
-
33
- .pull-request-author { opacity: 1.0; }
34
- .pull-request-number { color: #6C8592; }
35
- .pull-request-age { color: #AABCC5; }
36
- }
4
+ img {
5
+ width: 32px;
6
+ height: 32px;
37
7
  }
38
8
  }
39
9
 
40
- .pull-request-number {
41
- display: inline-block;
42
- vertical-align: middle;
43
- text-align: right;
44
- width: 2.5em; // enough room for 4 digits (i.e. 9999 pull requests)
45
- font-size: 1.66em;
46
- font-weight: 100;
47
- color: #777;
48
- }
49
-
50
- .pull-request-author {
51
- vertical-align: middle;
52
- margin-left: 0.25em;
53
- width: 24px;
54
- height: 24px;
10
+ td.pull-request-project {
11
+ white-space: nowrap;
55
12
  }
56
13
 
57
- .pull-request-title {
14
+ .pull-request-labels .label {
58
15
  display: inline-block;
59
- vertical-align: middle;
60
- margin-left: 0.25em;
16
+ padding: 2px 4px 4px;
17
+ font-size: 11px;
18
+ font-weight: bold;
19
+ line-height: 1;
20
+ color: #fff;
21
+ border-radius: 2px;
22
+ box-shadow: inset 0 -1px 0 rgba(0,0,0,0.12);
61
23
  }
62
24
 
63
- .pull-request-age {
64
- display: inline-block;
65
- vertical-align: middle;
66
- margin-left: 0.5em;
67
- color: #c9c9c9;
25
+ .pull-request-labels-toggle {
26
+ margin: 0.66em 0 2em;
27
+
28
+ input[type="checkbox"] { visibility: hidden; width: 0; height: 0; }
29
+ label { display: inline-block; }
30
+
31
+ // Premailer does not like the selector. It will result in an error
32
+ // NoMethodError: undefined method `<<' for nil:NilClass
33
+ // hpricot-0.8.6/lib/hpricot/elements.rb:307→ filter
34
+ // hpricot-0.8.6/lib/hpricot/elements.rb:290→ filter
35
+ // hpricot-0.8.6/lib/hpricot/traverse.rb:327→ search
36
+ // premailer-1.8.6/lib/premailer/adapter/hpricot.rb:46→ block in to_inline_css
37
+ // css_parser-1.3.7/lib/css_parser/parser.rb:192→ block (2 levels) in each_selector
38
+ // css_parser-1.3.7/lib/css_parser/rule_set.rb:90→ block in each_selector
39
+ // css_parser-1.3.7/lib/css_parser/rule_set.rb:90→ each
40
+ // css_parser-1.3.7/lib/css_parser/rule_set.rb:90→ each_selector
41
+ // css_parser-1.3.7/lib/css_parser/parser.rb:191→ block in each_selector
42
+ // css_parser-1.3.7/lib/css_parser/parser.rb:180→ block in each_rule_set
43
+ // css_parser-1.3.7/lib/css_parser/parser.rb:178→ each
44
+ // css_parser-1.3.7/lib/css_parser/parser.rb:178→ each_rule_set
45
+ // css_parser-1.3.7/lib/css_parser/parser.rb:190→ each_selector
46
+ // premailer-1.8.6/lib/premailer/adapter/hpricot.rb:21→ to_inline_css
47
+ // houston-core-57242effb689/app/mailers/view_mailer.rb:65→ block (2 levels) in mail
48
+ input[type="checkbox"]:not(:checked) + label {
49
+ .label {
50
+ background: #efefef !important;
51
+ color: #888 !important;
52
+ }
53
+ }
68
54
  }
@@ -2,6 +2,11 @@
2
2
  border-radius: 100em;
3
3
  }
4
4
 
5
+ .avatar.avatar-not-our-user {
6
+ border: 2px dotted #aaa;
7
+ margin: -2px;
8
+ }
9
+
5
10
  // just like on the timeline page
6
11
  h1.project-banner .avatar {
7
12
  float: right;
@@ -1,12 +1,15 @@
1
+ $default: rgb(80,80,80);
1
2
  <% Houston.config.project_colors.each do |name, value| %>
2
3
  $<%= name %>: <%= value.rgb %>;
3
4
  <% end %>
4
5
 
6
+ <% project_colors = %w{default} + Houston.config.project_colors.keys %>
7
+
5
8
  .label {
6
9
  vertical-align: baseline;
7
10
  font-weight: 400;
8
11
 
9
- <% Houston.config.project_colors.each do |name, value| %>
12
+ <% project_colors.each do |name| %>
10
13
  &.<%= name %> { background-color: $<%= name %>; }
11
14
  <% end %>
12
15
 
@@ -17,7 +20,7 @@
17
20
  }
18
21
 
19
22
  .dashboard .label {
20
- <% Houston.config.project_colors.each do |name, value| %>
23
+ <% project_colors.each do |name| %>
21
24
  &.<%= name %> {
22
25
  background-color: $<%= name %>;
23
26
  color: rgba(255,255,255,0.9);
@@ -36,13 +39,13 @@
36
39
  top: 1px;
37
40
  margin-left: 0.25em;
38
41
 
39
- <% Houston.config.project_colors.each do |name, value| %>
42
+ <% project_colors.each do |name| %>
40
43
  &.<%= name %> { background-color: $<%= name %>; }
41
44
  <% end %>
42
45
  }
43
46
 
44
47
  .project-tile {
45
- <% Houston.config.project_colors.each do |name, value| %>
48
+ <% project_colors.each do |name| %>
46
49
  &.<%= name %>:hover { background-color: $<%= name %>; }
47
50
  <% end %>
48
51
  }
@@ -50,12 +53,12 @@
50
53
  #email_body h1.project-banner,
51
54
  .current-project,
52
55
  .project-navbar {
53
- <% Houston.config.project_colors.each do |name, value| %>
56
+ <% project_colors.each do |name| %>
54
57
  &.<%= name %> { background-color: $<%= name %>; }
55
58
  <% end %>
56
59
  }
57
60
 
58
- <% Houston.config.project_colors.each do |name, value| %>
61
+ <% project_colors.each do |name| %>
59
62
  .project-navbar.<%= name %> .nav > li.current,
60
63
  .project-banner.<%= name %> {
61
64
  background-color: lighten($<%= name %>, 32%);
@@ -72,7 +75,7 @@
72
75
 
73
76
  .modal-header { background-color: #73746F; }
74
77
 
75
- <% Houston.config.project_colors.each do |name, value| %>
78
+ <% project_colors.each do |name| %>
76
79
  #new_ticket_modal.<%= name %> {
77
80
  .modal-header { background-color: $<%= name %>; }
78
81
  }