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
@@ -14,6 +14,8 @@ module CommitSynchronizer
|
|
14
14
|
|
15
15
|
unreachable_commits = project.commits.unreachable.pluck(:sha)
|
16
16
|
flag_reachable_commits! unreachable_commits & expected_commits
|
17
|
+
|
18
|
+
project.update_column :head_sha, project.repo.branch("master")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
@@ -82,6 +84,7 @@ private
|
|
82
84
|
commit = find_by_sha(native_commit.sha)
|
83
85
|
return commit if commit
|
84
86
|
|
87
|
+
$!.additional_information["project"] = project.slug
|
85
88
|
$!.additional_information["native_commit.sha"] = native_commit.sha
|
86
89
|
raise
|
87
90
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Github::PullsController < ApplicationController
|
2
|
+
|
3
|
+
def index
|
4
|
+
@pulls = Github::PullRequest.order(created_at: :desc).preload(:project, :user)
|
5
|
+
@labels = @pulls.flat_map(&:labels).uniq { |label| label["name"] }.sort_by { |label| label["name"] }
|
6
|
+
@selected_labels = params.fetch(:only, "").split(/,\s*/)
|
7
|
+
@selected_labels = @labels.map { |label| label["name"] } if @selected_labels.none?
|
8
|
+
@selected_labels -= params.fetch(:except, "").split(/,\s*/)
|
9
|
+
@title = "Pull Requests (#{@pulls.count})"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -3,7 +3,7 @@ class ProjectTestsController < ApplicationController
|
|
3
3
|
def index
|
4
4
|
@project = Project.find_by_slug! params[:slug]
|
5
5
|
|
6
|
-
head = params.fetch :at, @project.
|
6
|
+
head = params.fetch :at, @project.head_sha
|
7
7
|
commits = params.fetch(:limit, 500).to_i
|
8
8
|
|
9
9
|
@commits = Houston.benchmark("[project_tests#index] fetch commits") {
|
@@ -35,7 +35,7 @@ class ProjectTestsController < ApplicationController
|
|
35
35
|
@totals = Hash[@test.test_results.group(:status).pluck(:status, "COUNT(*)")]
|
36
36
|
|
37
37
|
begin
|
38
|
-
head = params.fetch :at, @project.
|
38
|
+
head = params.fetch :at, @project.head_sha
|
39
39
|
stop_shas = @test.introduced_in_shas
|
40
40
|
@commits = Houston.benchmark("[project_tests#show] fetch commits") {
|
41
41
|
@project.repo.ancestors(head, including_self: true, limit: 100, hide: stop_shas) }
|
@@ -54,7 +54,7 @@ class ProjectTestsController < ApplicationController
|
|
54
54
|
|
55
55
|
@results = @test.test_results.where(test_run_id: @runs.map(&:id))
|
56
56
|
.joins(:test_run)
|
57
|
-
.select("test_runs.sha",
|
57
|
+
.select("test_runs.sha", "test_results.*")
|
58
58
|
.index_by { |result| result[:sha] }
|
59
59
|
@runs = @runs.index_by(&:sha)
|
60
60
|
end
|
@@ -9,8 +9,8 @@ class ProjectsController < ApplicationController
|
|
9
9
|
@projects = Project \
|
10
10
|
.includes(:owners)
|
11
11
|
.includes(:maintainers)
|
12
|
+
.includes(:head)
|
12
13
|
.unretired
|
13
|
-
.map { |project| ProjectDependencies.new(project) }
|
14
14
|
@test_runs = TestRun.most_recent.index_by(&:project_id)
|
15
15
|
@releases = Release.where(environment_name: "production").most_recent.index_by(&:project_id)
|
16
16
|
end
|
@@ -28,6 +28,50 @@ class ProjectsController < ApplicationController
|
|
28
28
|
@project.roles.build(user: current_user) if @project.roles.none?
|
29
29
|
end
|
30
30
|
|
31
|
+
def new_from_github
|
32
|
+
authorize! :create, Project
|
33
|
+
|
34
|
+
existing_projects = Project.unscoped.where("extended_attributes->'git_location' LIKE '%github.com%'")
|
35
|
+
github_repos = Houston.benchmark "Fetching repos" do
|
36
|
+
Houston.github.repos
|
37
|
+
end
|
38
|
+
@repos = github_repos.map do |repo|
|
39
|
+
project = existing_projects.detect { |project|
|
40
|
+
[repo.git_url, repo.ssh_url, repo.clone_url].member?(project.extended_attributes["git_location"]) }
|
41
|
+
{ name: repo.name,
|
42
|
+
owner: repo.owner.login,
|
43
|
+
full_name: repo.full_name,
|
44
|
+
private: repo[:private],
|
45
|
+
git_location: repo.ssh_url,
|
46
|
+
project: project }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def create_from_github
|
52
|
+
authorize! :create, Project
|
53
|
+
|
54
|
+
repos = params.fetch(:repos, [])
|
55
|
+
projects = Project.transaction do
|
56
|
+
repos.map do |repo|
|
57
|
+
owner, name = repo.split("/")
|
58
|
+
title = name.humanize.gsub(/\b(?<!['’.`])[a-z]/) { $&.capitalize }.gsub("-", "::")
|
59
|
+
Project.create!(
|
60
|
+
name: title,
|
61
|
+
slug: name,
|
62
|
+
version_control_name: "Git",
|
63
|
+
extended_attributes: {"git_location" => "git@github.com:#{repo}.git"})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
flash[:notice] = "#{projects.count} projects added"
|
68
|
+
redirect_to projects_path
|
69
|
+
|
70
|
+
rescue ActiveRecord::RecordInvalid
|
71
|
+
flash[:error] = $!.message
|
72
|
+
redirect_to :back
|
73
|
+
end
|
74
|
+
|
31
75
|
|
32
76
|
def edit
|
33
77
|
@project = Project.find_by_slug!(params[:id])
|
@@ -1,20 +1,17 @@
|
|
1
1
|
class ReleasesController < ApplicationController
|
2
2
|
include UrlHelper
|
3
|
-
|
3
|
+
include ReleaseHelper
|
4
|
+
before_filter :get_release_and_project, only: [:show, :edit, :update, :destroy]
|
5
|
+
before_filter :get_project_and_environment, only: [:index, :new, :create]
|
4
6
|
before_filter :load_tickets, only: [:new, :edit, :create, :update]
|
5
7
|
|
8
|
+
|
9
|
+
|
6
10
|
def index
|
7
11
|
@title = "Releases • #{@project.name}"
|
8
12
|
@title << " (#{@environment})" if @environment
|
9
13
|
end
|
10
14
|
|
11
|
-
def show
|
12
|
-
@release = @releases.find(params[:id])
|
13
|
-
authorize! :show, @release
|
14
|
-
|
15
|
-
@title = "Release #{@release.release_date.strftime("%b %-d")} • #{@project.name}"
|
16
|
-
end
|
17
|
-
|
18
15
|
def new
|
19
16
|
@title = "New Release (#{@environment}) • #{@project.name}"
|
20
17
|
|
@@ -42,22 +39,6 @@ class ReleasesController < ApplicationController
|
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
45
|
-
def edit
|
46
|
-
@release = @releases.find(params[:id])
|
47
|
-
authorize! :update, @release
|
48
|
-
|
49
|
-
if params[:recreate]
|
50
|
-
if @release.can_read_commits?
|
51
|
-
@release.load_commits!
|
52
|
-
@release.load_tickets!
|
53
|
-
@release.build_changes_from_commits
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
@release.release_changes = [ReleaseChange.new(@release, "", "")] if @release.release_changes.none?
|
58
|
-
@release.valid?
|
59
|
-
end
|
60
|
-
|
61
42
|
def create
|
62
43
|
@release = @releases.new(params[:release])
|
63
44
|
@release.user = current_user
|
@@ -81,8 +62,39 @@ class ReleasesController < ApplicationController
|
|
81
62
|
end
|
82
63
|
end
|
83
64
|
|
65
|
+
|
66
|
+
|
67
|
+
def show
|
68
|
+
authorize! :show, @release
|
69
|
+
|
70
|
+
@title = "Release #{@release.release_date.strftime("%b %-d")} • #{@project.name}"
|
71
|
+
|
72
|
+
if request.format.oembed?
|
73
|
+
render json: {
|
74
|
+
version: "1.0",
|
75
|
+
type: "link",
|
76
|
+
author_name: "#{@project.slug} / #{@release.environment_name}",
|
77
|
+
title: format_release_subject(@release),
|
78
|
+
html: format_release_description(@release) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def edit
|
83
|
+
authorize! :update, @release
|
84
|
+
|
85
|
+
if params[:recreate]
|
86
|
+
if @release.can_read_commits?
|
87
|
+
@release.load_commits!
|
88
|
+
@release.load_tickets!
|
89
|
+
@release.build_changes_from_commits
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
@release.release_changes = [ReleaseChange.new(@release, "", "")] if @release.release_changes.none?
|
94
|
+
@release.valid?
|
95
|
+
end
|
96
|
+
|
84
97
|
def update
|
85
|
-
@release = @releases.find(params[:id])
|
86
98
|
authorize! :update, @release
|
87
99
|
|
88
100
|
if @release.update_attributes(params[:release])
|
@@ -93,7 +105,6 @@ class ReleasesController < ApplicationController
|
|
93
105
|
end
|
94
106
|
|
95
107
|
def destroy
|
96
|
-
@release = @releases.find(params[:id])
|
97
108
|
authorize! :destroy, @release
|
98
109
|
|
99
110
|
@release.destroy
|
@@ -103,6 +114,11 @@ class ReleasesController < ApplicationController
|
|
103
114
|
|
104
115
|
private
|
105
116
|
|
117
|
+
def get_release_and_project
|
118
|
+
@release = Release.find(params[:id])
|
119
|
+
@project = @release.project
|
120
|
+
end
|
121
|
+
|
106
122
|
def get_project_and_environment
|
107
123
|
@project = Project.find_by_slug!(params[:project_id])
|
108
124
|
@environment = params[:environment] || @project.environments_with_release_notes.first
|
@@ -75,6 +75,14 @@ module ApplicationHelper
|
|
75
75
|
|
76
76
|
|
77
77
|
|
78
|
+
def pull_request_label(label)
|
79
|
+
background = "##{label["color"]}"
|
80
|
+
foreground = "#fff"
|
81
|
+
foreground = "#333" if %w{#f7c6c7 #d4c5f9 #fbca04 #fad8c7 #bfe5bf}.member? background
|
82
|
+
"<span class=\"label\" style=\"background: #{background}; color: #{foreground};\">#{label["name"]}</span>".html_safe
|
83
|
+
end
|
84
|
+
|
85
|
+
|
78
86
|
end
|
79
87
|
|
80
88
|
|
@@ -22,11 +22,11 @@ module AvatarHelper
|
|
22
22
|
# http://en.gravatar.com/site/implement/ruby
|
23
23
|
# http://en.gravatar.com/site/implement/url
|
24
24
|
def gravatar_url(email, options={})
|
25
|
-
url = "
|
25
|
+
url = "https://www.gravatar.com/avatar/#{Digest::MD5::hexdigest(email)}?r=g&d=retro"
|
26
26
|
url << "&s=#{options[:size]}" if options.key?(:size)
|
27
27
|
url
|
28
28
|
end
|
29
29
|
|
30
30
|
|
31
31
|
|
32
|
-
end
|
32
|
+
end
|
@@ -13,8 +13,8 @@ module CommitHelper
|
|
13
13
|
project = commit.project
|
14
14
|
content = block_given? ? yield : "<span class=\"commit-sha\">#{commit.sha[0...7]}</span>".html_safe
|
15
15
|
|
16
|
-
return content unless
|
17
|
-
link_to content,
|
16
|
+
return content unless url = github_commit_url(project, commit.sha)
|
17
|
+
link_to content, url, options.reverse_merge(target: "_blank")
|
18
18
|
end
|
19
19
|
|
20
20
|
def link_to_release_commit_range(release)
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module ProjectHelper
|
2
2
|
|
3
3
|
def with_most_recent_commit(project)
|
4
|
-
|
5
|
-
commit = project.find_commit_by_sha project.repo.branch("master")
|
4
|
+
commit = project.head
|
6
5
|
if commit
|
7
|
-
commit.project = project
|
6
|
+
commit.project = project # so that _Commit_ doesn't load project again
|
8
7
|
yield commit
|
9
8
|
end
|
10
9
|
end
|
@@ -12,7 +11,7 @@ module ProjectHelper
|
|
12
11
|
def with_most_recent_release(project)
|
13
12
|
release = @releases[project.id]
|
14
13
|
if release
|
15
|
-
release.project = project
|
14
|
+
release.project = project # so that _Release_ doesn't load project again
|
16
15
|
yield release
|
17
16
|
end
|
18
17
|
end
|
@@ -20,7 +19,7 @@ module ProjectHelper
|
|
20
19
|
def with_most_recent_test_run(project)
|
21
20
|
test_run = @test_runs[project.id]
|
22
21
|
if test_run
|
23
|
-
test_run.project = project
|
22
|
+
test_run.project = project # so that _TestRun_ doesn't load project again
|
24
23
|
yield test_run
|
25
24
|
end
|
26
25
|
end
|
@@ -4,6 +4,17 @@ module ReleaseHelper
|
|
4
4
|
"<span class=\"weekday\">#{date.strftime("%A")}</span> #{date.strftime("%b %e, %Y")}".html_safe
|
5
5
|
end
|
6
6
|
|
7
|
+
def format_release_subject(release)
|
8
|
+
release.date.strftime("%b %e, %Y • ") + release.released_at.strftime("%-I:%M%p").downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_release_description(release)
|
12
|
+
ordered_by_tag(release.release_changes)
|
13
|
+
.map { |change| "#{change.tag.name.upcase} #{change.description}" }
|
14
|
+
.join("\r\n")
|
15
|
+
.html_safe
|
16
|
+
end
|
17
|
+
|
7
18
|
def ordered_by_tag(changes)
|
8
19
|
changes.sort_by { |change| change.tag ? change.tag.position : 99 }
|
9
20
|
end
|
@@ -3,7 +3,7 @@ module TimelineHelper
|
|
3
3
|
def render_timeline_gap_for(date_range)
|
4
4
|
days = date_range.end - date_range.begin
|
5
5
|
if days < 3
|
6
|
-
date_range.inject("") { |html, date| html << render_timeline_date(date) }.html_safe
|
6
|
+
date_range.to_a.reverse.inject("") { |html, date| html << render_timeline_date(date) }.html_safe
|
7
7
|
else
|
8
8
|
<<-HTML.html_safe
|
9
9
|
<div class="timeline-date-gap"></div>
|
data/app/helpers/url_helper.rb
CHANGED
@@ -48,24 +48,6 @@ module UrlHelper
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def release_path(release, options={})
|
52
|
-
super(release.project.to_param, release.environment_name, release, options)
|
53
|
-
end
|
54
|
-
|
55
|
-
def edit_release_path(release, options={})
|
56
|
-
super(release.project.to_param, release.environment_name, release, options)
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def release_url(release, options={})
|
62
|
-
super(release.project.to_param, release.environment_name, release, options)
|
63
|
-
end
|
64
|
-
|
65
|
-
def edit_release_url(release, options={})
|
66
|
-
super(release.project.to_param, release.environment_name, release, options)
|
67
|
-
end
|
68
|
-
|
69
51
|
def new_release_url(release, options={})
|
70
52
|
super(release.project.to_param, release.environment_name, options.merge(deploy_id: release.deploy_id))
|
71
53
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CacheKeyDependencies
|
2
|
+
attr_reader :project
|
3
|
+
|
4
|
+
def self.for(*projects)
|
5
|
+
projects = projects[0] if projects.length == 1 && projects[0].respond_to?(:each)
|
6
|
+
projects.each do |project|
|
7
|
+
begin
|
8
|
+
self.new(project).perform!
|
9
|
+
rescue StandardError => e
|
10
|
+
Houston.report_exception(e)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(project)
|
16
|
+
@project = ProjectDependencies.new(project)
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform!
|
20
|
+
KeyDependency.all.each do |dependency|
|
21
|
+
version = ProjectDependency.new(project, dependency).version
|
22
|
+
project.extended_attributes = project.extended_attributes.merge(
|
23
|
+
"key_dependency.#{dependency.slug}" => version)
|
24
|
+
end
|
25
|
+
project.update_column :extended_attributes, project.extended_attributes
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/app/mailers/view_mailer.rb
CHANGED
data/app/models/commit.rb
CHANGED
@@ -21,21 +21,63 @@ module Github
|
|
21
21
|
validates :number, uniqueness: { scope: :project_id }
|
22
22
|
|
23
23
|
class << self
|
24
|
-
|
24
|
+
# Makes X + Y requests to GitHub
|
25
|
+
# where X is the number of projects in Houston on GitHub
|
26
|
+
# and Y is the number of pull requests for those projects
|
27
|
+
#
|
28
|
+
# We _could_ group repos by their owner and fetch `org_issues`
|
29
|
+
# but that will only work for organizations, not personal
|
30
|
+
# accounts.
|
31
|
+
#
|
32
|
+
# This method can chomp through your rate limit rather quickly.
|
33
|
+
# Also, on my computer it took 19 seconds to fetch 39 pull
|
34
|
+
# requests from 52 repos.
|
35
|
+
def fetch!(projects = Project.unretired)
|
36
|
+
repos = projects
|
37
|
+
.where("extended_attributes->'git_location' LIKE '%github.com%'")
|
38
|
+
.pluck("extended_attributes->'git_location'")
|
39
|
+
.map { |url| _repo_name_from_url(url) }
|
40
|
+
.compact
|
41
|
+
|
25
42
|
Houston.benchmark "Fetching pull requests" do
|
26
|
-
|
43
|
+
requests = 0
|
44
|
+
issues = repos.flat_map do |repo|
|
45
|
+
_fetch_issues_for!(repo).tap do |results|
|
46
|
+
requests += 1 + (results.length / 30)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
pulls = issues
|
27
51
|
.select { |issue| !issue.pull_request.nil? }
|
28
|
-
.map { |issue|
|
29
|
-
|
30
|
-
|
31
|
-
.
|
52
|
+
.map { |issue|
|
53
|
+
requests += 1
|
54
|
+
repo = issue.pull_request.url[/https:\/\/api.github.com\/repos\/(.*)\/pulls\/\d+/, 1]
|
55
|
+
Houston.github.pull_request(repo, issue.number)
|
56
|
+
.to_h
|
57
|
+
.merge(labels: issue.labels)
|
58
|
+
.with_indifferent_access }
|
59
|
+
|
60
|
+
Rails.logger.info "[pulls] #{requests} requests; #{Houston.github.last_response.headers["x-ratelimit-remaining"]} remaining"
|
61
|
+
pulls
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def _repo_name_from_url(url)
|
66
|
+
url[/\Agit@github\.com:(.*)\.git\Z/, 1] || url[/\Agit:\/\/github.com\/(.*)\.git\Z/, 1]
|
67
|
+
end
|
68
|
+
|
69
|
+
def _fetch_issues_for!(repo)
|
70
|
+
if repo.end_with? "/*"
|
71
|
+
Houston.github.org_issues(repo[0...-2], filter: "all", state: "open")
|
72
|
+
else
|
73
|
+
Houston.github.issues(repo, filter: "all", state: "open")
|
32
74
|
end
|
75
|
+
rescue Octokit::NotFound
|
76
|
+
[]
|
33
77
|
end
|
34
78
|
|
35
|
-
def sync!
|
36
|
-
expected_pulls = fetch!
|
37
|
-
expected_pulls.select! { |pr| pr["base"]["repo"]["name"] == pr["head"]["repo"]["name"] }
|
38
|
-
# select only ones where head and base are the same repo
|
79
|
+
def sync!(projects = Project.unretired)
|
80
|
+
expected_pulls = fetch!(projects)
|
39
81
|
Houston.benchmark "Syncing pull requests" do
|
40
82
|
existing_pulls = all.to_a
|
41
83
|
|
@@ -56,7 +98,9 @@ module Github
|
|
56
98
|
|
57
99
|
existing_pr ||= Github::PullRequest.new
|
58
100
|
existing_pr.merge_attributes(expected_pr)
|
59
|
-
existing_pr.save
|
101
|
+
unless existing_pr.save
|
102
|
+
Rails.logger.warn "\e[31m[pulls] Invalid PR: #{existing_pr.errors.full_messages.join("; ")}\e[0m"
|
103
|
+
end
|
60
104
|
existing_pr
|
61
105
|
end
|
62
106
|
end
|
@@ -93,42 +137,52 @@ module Github
|
|
93
137
|
end
|
94
138
|
|
95
139
|
def labeled(*labels)
|
96
|
-
where(["
|
140
|
+
where(["exists (select 1 from jsonb_array_elements(pull_requests.json_labels) as \"label\" where \"label\"->>'name' IN (?))", labels])
|
97
141
|
end
|
98
142
|
end
|
99
143
|
|
100
144
|
|
101
145
|
|
102
146
|
def labels=(value)
|
103
|
-
|
147
|
+
self.json_labels = value.map { |label| label.to_h.stringify_keys.pick("name", "color") }
|
148
|
+
end
|
149
|
+
|
150
|
+
def labels
|
151
|
+
json_labels
|
104
152
|
end
|
105
153
|
|
106
154
|
def add_label!(label, options={})
|
155
|
+
label = label.to_h.stringify_keys.pick("name", "color")
|
156
|
+
|
107
157
|
transaction do
|
108
158
|
pr = self.class.lock.find id
|
109
|
-
|
159
|
+
new_labels = pr.json_labels.reject { |l| l["name"] == label["name"] } + [label]
|
160
|
+
pr.update_attributes! json_labels: new_labels, actor: options[:as]
|
110
161
|
end
|
111
162
|
end
|
112
163
|
|
113
164
|
def remove_label!(label, options={})
|
165
|
+
label = label.to_h.stringify_keys.pick("name", "color")
|
166
|
+
|
114
167
|
transaction do
|
115
168
|
pr = self.class.lock.find id
|
116
|
-
|
169
|
+
new_labels = pr.json_labels.reject { |l| l["name"] == label["name"] }
|
170
|
+
pr.update_attributes! json_labels: new_labels, actor: options[:as]
|
117
171
|
end
|
118
172
|
end
|
119
173
|
|
120
174
|
|
121
175
|
|
122
176
|
def merge_attributes(pr)
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
177
|
+
self.repo = pr["base"]["repo"]["name"] unless repo
|
178
|
+
self.number = pr["number"] unless number
|
179
|
+
self.username = pr["user"]["login"] unless username
|
180
|
+
self.avatar_url = pr["user"]["avatar_url"] unless avatar_url
|
181
|
+
self.url = pr["html_url"] unless url
|
182
|
+
self.base_sha = pr["base"]["sha"] unless base_sha
|
183
|
+
self.base_ref = pr["base"]["ref"] unless base_ref
|
184
|
+
|
185
|
+
self.created_at = pr["created_at"]
|
132
186
|
self.title = pr["title"]
|
133
187
|
self.body = pr["body"]
|
134
188
|
self.head_sha = pr["head"]["sha"]
|
@@ -145,11 +199,13 @@ module Github
|
|
145
199
|
end
|
146
200
|
|
147
201
|
def associate_user_with_self
|
148
|
-
self.user = User.
|
202
|
+
self.user = User.find_by_github_username(username)
|
149
203
|
end
|
150
204
|
|
151
205
|
def associate_commits_with_self
|
152
|
-
|
206
|
+
Houston.try({max_tries: 2, base: 0}, ActiveRecord::RecordNotUnique) do
|
207
|
+
self.commits = project.commits.between(base_sha, head_sha)
|
208
|
+
end
|
153
209
|
end
|
154
210
|
|
155
211
|
end
|