Merge branch 'gitaly-post-receive' into 'master'

Add internal endpoint to notify post-receive to Gitaly

See merge request !8983
This commit is contained in:
Robert Speicher 2017-03-02 01:20:40 +00:00
commit 3b3f0fab45
10 changed files with 126 additions and 0 deletions

View File

@ -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'

View File

@ -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)

View File

@ -0,0 +1,4 @@
---
title: Add internal API to notify Gitaly of post receive
merge_request: 8983
author:

View File

@ -0,0 +1,2 @@
# Make sure we initialize a Gitaly channel before Sidekiq starts multi-threaded execution.
Gitlab::GitalyClient.channel unless Rails.env.test?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -0,0 +1,3 @@
RSpec::Matchers.define :post_receive_request_with_repo_path do |path|
match { |actual| actual.repository.path == path }
end