summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Rodríguez <alejorro70@gmail.com>2017-02-05 15:04:23 -0300
committerAlejandro Rodríguez <alejorro70@gmail.com>2017-03-01 18:46:59 -0300
commitf8fa6e6f472179cfd9261a35d309d986f8db8ebd (patch)
treedcbaa836cbc91c15fc0aa77e5610a23f874b1934
parentb6a945b39354ec2b2c09fc5f6904dfbf8990df26 (diff)
downloadgitlab-ce-gitaly-post-receive.tar.gz
Add internal endpoint to notify post-receive to Gitalygitaly-post-receive
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock8
-rw-r--r--changelogs/unreleased/gitaly-post-receive.yml4
-rw-r--r--config/initializers/8_gitaly.rb2
-rw-r--r--lib/api/internal.rb12
-rw-r--r--lib/gitlab/gitaly_client.rb29
-rw-r--r--lib/gitlab/gitaly_client/notifications.rb17
-rw-r--r--spec/lib/gitlab/gitaly_client/notifications_spec.rb20
-rw-r--r--spec/requests/api/internal_spec.rb28
-rw-r--r--spec/support/matchers/gitaly_matchers.rb3
10 files changed, 126 insertions, 0 deletions
diff --git a/Gemfile b/Gemfile
index 8e181fee73b..fefccf87275 100644
--- a/Gemfile
+++ b/Gemfile
@@ -350,3 +350,6 @@ gem 'health_check', '~> 2.2.0'
# System information
gem 'vmstat', '~> 2.3.0'
gem 'sys-filesystem', '~> 1.1.6'
+
+# Gitaly GRPC client
+gem 'gitaly', '~> 0.2.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d6ce2a62b6..d5433f5d652 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -245,6 +245,9 @@ GEM
json
get_process_mem (0.2.0)
gherkin-ruby (0.3.2)
+ gitaly (0.2.1)
+ google-protobuf (~> 3.1)
+ grpc (~> 1.0)
github-linguist (4.7.6)
charlock_holmes (~> 0.7.3)
escape_utils (~> 1.1.0)
@@ -296,6 +299,7 @@ GEM
multi_json (~> 1.10)
retriable (~> 1.4)
signet (~> 0.6)
+ google-protobuf (3.2.0)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
@@ -317,6 +321,9 @@ GEM
grape-entity (0.6.0)
activesupport
multi_json (>= 1.3.2)
+ grpc (1.1.2)
+ google-protobuf (~> 3.1)
+ googleauth (~> 0.5.1)
haml (4.0.7)
tilt
haml_lint (0.21.0)
@@ -877,6 +884,7 @@ DEPENDENCIES
fuubar (~> 2.0.0)
gemnasium-gitlab-service (~> 0.2)
gemojione (~> 3.0)
+ gitaly (~> 0.2.1)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1)
diff --git a/changelogs/unreleased/gitaly-post-receive.yml b/changelogs/unreleased/gitaly-post-receive.yml
new file mode 100644
index 00000000000..cf206e39084
--- /dev/null
+++ b/changelogs/unreleased/gitaly-post-receive.yml
@@ -0,0 +1,4 @@
+---
+title: Add internal API to notify Gitaly of post receive
+merge_request: 8983
+author:
diff --git a/config/initializers/8_gitaly.rb b/config/initializers/8_gitaly.rb
new file mode 100644
index 00000000000..07dd30f0a24
--- /dev/null
+++ b/config/initializers/8_gitaly.rb
@@ -0,0 +1,2 @@
+# Make sure we initialize a Gitaly channel before Sidekiq starts multi-threaded execution.
+Gitlab::GitalyClient.channel unless Rails.env.test?
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index d235977fbd8..7eed93aba00 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -132,6 +132,18 @@ module API
{ success: true, recovery_codes: codes }
end
+
+ post "/notify_post_receive" do
+ status 200
+
+ return unless Gitlab::GitalyClient.enabled?
+
+ begin
+ Gitlab::GitalyClient::Notifications.new.post_receive(params[:repo_path])
+ rescue GRPC::Unavailable => e
+ render_api_error(e, 500)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
new file mode 100644
index 00000000000..b981a629fb0
--- /dev/null
+++ b/lib/gitlab/gitaly_client.rb
@@ -0,0 +1,29 @@
+require 'gitaly'
+
+module Gitlab
+ module GitalyClient
+ def self.gitaly_address
+ if Gitlab.config.gitaly.socket_path
+ "unix://#{Gitlab.config.gitaly.socket_path}"
+ end
+ end
+
+ def self.channel
+ return @channel if defined?(@channel)
+
+ @channel =
+ if enabled?
+ # NOTE: Gitaly currently runs on a Unix socket, so permissions are
+ # handled using the file system and no additional authentication is
+ # required (therefore the :this_channel_is_insecure flag)
+ GRPC::Core::Channel.new(gitaly_address, {}, :this_channel_is_insecure)
+ else
+ nil
+ end
+ end
+
+ def self.enabled?
+ gitaly_address.present?
+ end
+ end
+end
diff --git a/lib/gitlab/gitaly_client/notifications.rb b/lib/gitlab/gitaly_client/notifications.rb
new file mode 100644
index 00000000000..b827a56207f
--- /dev/null
+++ b/lib/gitlab/gitaly_client/notifications.rb
@@ -0,0 +1,17 @@
+module Gitlab
+ module GitalyClient
+ class Notifications
+ attr_accessor :stub
+
+ def initialize
+ @stub = Gitaly::Notifications::Stub.new(nil, nil, channel_override: GitalyClient.channel)
+ end
+
+ def post_receive(repo_path)
+ repository = Gitaly::Repository.new(path: repo_path)
+ request = Gitaly::PostReceiveRequest.new(repository: repository)
+ stub.post_receive(request)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitaly_client/notifications_spec.rb b/spec/lib/gitlab/gitaly_client/notifications_spec.rb
new file mode 100644
index 00000000000..a6252c99aa1
--- /dev/null
+++ b/spec/lib/gitlab/gitaly_client/notifications_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::GitalyClient::Notifications do
+ let(:client) { Gitlab::GitalyClient::Notifications.new }
+
+ before do
+ allow(Gitlab.config.gitaly).to receive(:socket_path).and_return('path/to/gitaly.socket')
+ end
+
+ describe '#post_receive' do
+ let(:repo_path) { '/path/to/my_repo.git' }
+
+ it 'sends a post_receive message' do
+ expect_any_instance_of(Gitaly::Notifications::Stub).
+ to receive(:post_receive).with(post_receive_request_with_repo_path(repo_path))
+
+ client.post_receive(repo_path)
+ end
+ end
+end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index ffeacb15f17..f18b8e98707 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -409,6 +409,34 @@ describe API::Internal, api: true do
end
end
+ describe 'POST /notify_post_receive' do
+ let(:valid_params) do
+ { repo_path: project.repository.path, secret_token: secret_token }
+ end
+
+ before do
+ allow(Gitlab.config.gitaly).to receive(:socket_path).and_return('path/to/gitaly.socket')
+ end
+
+ it "calls the Gitaly client if it's enabled" do
+ expect_any_instance_of(Gitlab::GitalyClient::Notifications).
+ to receive(:post_receive).with(project.repository.path)
+
+ post api("/internal/notify_post_receive"), valid_params
+
+ expect(response).to have_http_status(200)
+ end
+
+ it "returns 500 if the gitaly call fails" do
+ expect_any_instance_of(Gitlab::GitalyClient::Notifications).
+ to receive(:post_receive).with(project.repository.path).and_raise(GRPC::Unavailable)
+
+ post api("/internal/notify_post_receive"), valid_params
+
+ expect(response).to have_http_status(500)
+ end
+ end
+
def project_with_repo_path(path)
double().tap do |fake_project|
allow(fake_project).to receive_message_chain('repository.path_to_repo' => path)
diff --git a/spec/support/matchers/gitaly_matchers.rb b/spec/support/matchers/gitaly_matchers.rb
new file mode 100644
index 00000000000..d7a53820684
--- /dev/null
+++ b/spec/support/matchers/gitaly_matchers.rb
@@ -0,0 +1,3 @@
+RSpec::Matchers.define :post_receive_request_with_repo_path do |path|
+ match { |actual| actual.repository.path == path }
+end