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.
- checksums.yaml +4 -4
- data/Gemfile.lock +94 -69
- data/app/adapters/houston/adapters/deployment/engineyard.rb +4 -3
- data/app/adapters/houston/adapters/version_control/git_adapter.rb +36 -42
- data/app/adapters/houston/adapters/version_control/git_adapter/github_repo.rb +2 -2
- data/app/adapters/houston/adapters/version_control/git_adapter/remote_repo.rb +23 -11
- data/app/adapters/houston/adapters/version_control/git_adapter/repo.rb +18 -8
- data/app/adapters/houston/adapters/version_control/null_repo.rb +8 -0
- data/app/assets/javascripts/core/handlebars_helpers.coffee +3 -3
- data/app/assets/stylesheets/application/github_repos.scss +77 -0
- data/app/assets/stylesheets/application/navigation.scss +2 -0
- data/app/assets/stylesheets/application/pull_requests.scss +44 -58
- data/app/assets/stylesheets/core/avatars.scss +5 -0
- data/app/assets/stylesheets/core/colors.scss.erb +10 -7
- data/app/concerns/commit_synchronizer.rb +3 -0
- data/app/controllers/github/pulls_controller.rb +12 -0
- data/app/controllers/project_tests_controller.rb +3 -3
- data/app/controllers/projects_controller.rb +45 -1
- data/app/controllers/releases_controller.rb +42 -26
- data/app/helpers/application_helper.rb +8 -0
- data/app/helpers/avatar_helper.rb +2 -2
- data/app/helpers/commit_helper.rb +2 -2
- data/app/helpers/oembed_helper.rb +8 -0
- data/app/helpers/project_helper.rb +4 -5
- data/app/helpers/release_helper.rb +11 -0
- data/app/helpers/timeline_helper.rb +1 -1
- data/app/helpers/url_helper.rb +0 -18
- data/app/interactors/cache_key_dependencies.rb +28 -0
- data/app/jobs/sync_all_tickets_job.rb +1 -0
- data/app/mailers/view_mailer.rb +0 -1
- data/app/models/commit.rb +1 -1
- data/app/models/github/pull_request.rb +82 -26
- data/app/models/github/pull_request_event.rb +2 -2
- data/app/models/milestone.rb +1 -0
- data/app/models/project.rb +14 -0
- data/app/models/project_dependencies.rb +5 -3
- data/app/models/task.rb +1 -1
- data/app/models/user.rb +41 -0
- data/app/views/commits/show.html.erb +9 -1
- data/app/views/github/pulls/index.html.erb +102 -0
- data/app/views/project_notification/new_release.html.erb +6 -0
- data/app/views/project_tickets/index.xls.erb +0 -7
- data/app/views/projects/_form.html.erb +29 -17
- data/app/views/projects/index.html.erb +3 -3
- data/app/views/projects/new_from_github.html.erb +67 -0
- data/app/views/releases/_commits.html.erb +1 -1
- data/app/views/releases/show.html.erb +9 -0
- data/app/views/users/_form.html.erb +35 -19
- data/config/application.rb +12 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/routes.rb +17 -3
- data/db/migrate/20151201042126_require_projects_to_have_name_and_slug.rb +6 -0
- data/db/migrate/20151202005557_add_head_sha_to_projects.rb +24 -0
- data/db/migrate/20151202011812_require_projects_to_have_color.rb +13 -0
- data/db/migrate/20151205204922_require_project_slugs_to_be_unique.rb +5 -0
- data/db/migrate/20151205214647_add_avatar_url_to_pull_requests.rb +5 -0
- data/db/migrate/20151209004458_add_json_labels_to_pull_requests.rb +5 -0
- data/db/migrate/20151209030113_add_timestamps_to_pull_requests.rb +6 -0
- data/db/structure.sql +31 -5
- data/houston.gemspec +7 -7
- data/lib/configuration.rb +3 -2
- data/lib/houston/version.rb +1 -1
- data/lib/rack/oembed.rb +23 -0
- data/templates/new-instance/config/jobs/cache_key_dependencies.rb +3 -0
- data/templates/new-instance/config/triggers/tests/slack_when_analyzed.rb +1 -4
- data/templates/new-instance/config/triggers/tests/slack_when_completed.rb +1 -1
- data/templates/new-instance/lib/slack_helpers.rb +1 -1
- data/test/integration/ticket_tasks_api_test.rb +1 -1
- data/test/unit/adapters/git_adapter_test.rb +29 -8
- data/test/unit/adapters/version_control_adapters_api_test.rb +2 -0
- data/test/unit/controllers/hooks_controller_test.rb +4 -4
- data/test/unit/models/commit_test.rb +2 -2
- data/test/unit/models/project_test.rb +2 -2
- data/test/unit/models/pull_request_test.rb +9 -4
- data/test/unit/models/task_test.rb +1 -1
- data/test/unit/models/ticket_test.rb +1 -1
- metadata +31 -16
@@ -6,7 +6,7 @@ module Houston
|
|
6
6
|
|
7
7
|
|
8
8
|
def project_url
|
9
|
-
location
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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}] #{
|
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] =
|
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
|
-
|
11
|
-
|
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?(
|
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 :
|
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 = "
|
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 = "
|
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 = "
|
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
|
+
}
|
@@ -1,68 +1,54 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
font-weight: 500;
|
1
|
+
td.pull-request-avatar {
|
2
|
+
width: 32px;
|
4
3
|
|
5
|
-
|
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-
|
41
|
-
|
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-
|
14
|
+
.pull-request-labels .label {
|
58
15
|
display: inline-block;
|
59
|
-
|
60
|
-
|
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-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
}
|
@@ -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
|
-
<%
|
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
|
-
<%
|
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
|
-
<%
|
42
|
+
<% project_colors.each do |name| %>
|
40
43
|
&.<%= name %> { background-color: $<%= name %>; }
|
41
44
|
<% end %>
|
42
45
|
}
|
43
46
|
|
44
47
|
.project-tile {
|
45
|
-
<%
|
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
|
-
<%
|
56
|
+
<% project_colors.each do |name| %>
|
54
57
|
&.<%= name %> { background-color: $<%= name %>; }
|
55
58
|
<% end %>
|
56
59
|
}
|
57
60
|
|
58
|
-
<%
|
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
|
-
<%
|
78
|
+
<% project_colors.each do |name| %>
|
76
79
|
#new_ticket_modal.<%= name %> {
|
77
80
|
.modal-header { background-color: $<%= name %>; }
|
78
81
|
}
|