summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2019-04-03 12:35:25 +0000
committerNick Thomas <nick@gitlab.com>2019-04-03 12:35:25 +0000
commitd03608dcc356dddd696bd081f5a35fa416c4439c (patch)
tree035d1ddb8bcef59e91576d42efc1dbd8824adc9d
parent433cc96551a6d1f1621f9e105b1e7eb1ccc41b7a (diff)
parente0824f17367a44e5bac84dac7197f9b45e37ab01 (diff)
downloadgitlab-shell-d03608dcc356dddd696bd081f5a35fa416c4439c.tar.gz
Merge branch 'remove-hooks' into 'master'
Remove hooks, they belong to Gitaly now See merge request gitlab-org/gitlab-shell!291
-rw-r--r--README.md8
-rwxr-xr-xhooks/post-receive24
-rwxr-xr-xhooks/pre-receive34
-rwxr-xr-xhooks/update20
-rw-r--r--lib/gitlab_access.rb43
-rw-r--r--lib/gitlab_custom_hook.rb98
-rw-r--r--lib/gitlab_net.rb1
-rw-r--r--lib/gitlab_post_receive.rb125
-rw-r--r--spec/gitlab_access_spec.rb77
-rw-r--r--spec/gitlab_custom_hook_spec.rb295
-rw-r--r--spec/gitlab_post_receive_spec.rb284
11 files changed, 11 insertions, 998 deletions
diff --git a/README.md b/README.md
index 7cb9619..5bd0024 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ An overview of the four cases described above:
## Git hooks
-For historical reasons the gitlab-shell repository also contains the
+The gitlab-shell repository used to also contain the
Git hooks that allow GitLab to validate Git pushes (e.g. "is this user
allowed to push to this protected branch"). These hooks also trigger
events in GitLab (e.g. to start a CI pipeline after a push).
@@ -30,17 +30,13 @@ require direct disk access to Git repositories, and that is only
possible on Gitaly servers. It makes no sense to have to install
gitlab-shell on Gitaly servers.
-As of GitLab 11.9 [the actual Git hooks are in the Gitaly
+As of GitLab 11.10 [the actual Git hooks are in the Gitaly
repository](https://gitlab.com/gitlab-org/gitaly/tree/v1.22.0/ruby/vendor/gitlab-shell/hooks),
but gitlab-shell must still be installed on Gitaly servers because the
hooks rely on configuration data (e.g. the GitLab internal API URL) that
is not yet available in Gitaly itself. Also see the [transition
plan](https://gitlab.com/gitlab-org/gitaly/issues/1226#note_126519133).
-This means that for GitLab 11.9 and up, it is pointless to make changes
-to Git hook code in the gitlab-shell repository, because the code that
-gets run is in the Gitaly repository instead.
-
## Code status
[![pipeline status](https://gitlab.com/gitlab-org/gitlab-shell/badges/master/pipeline.svg)](https://gitlab.com/gitlab-org/gitlab-shell/commits/master)
diff --git a/hooks/post-receive b/hooks/post-receive
index 2b6538f..73740da 100755
--- a/hooks/post-receive
+++ b/hooks/post-receive
@@ -1,22 +1,4 @@
-#!/usr/bin/env ruby
+#!/bin/sh
+echo "The gitlab-shell hooks have been migrated to Gitaly, see https://gitlab.com/gitlab-org/gitaly/issues/1226"
+exit 1
-# This file was placed here by GitLab. It makes sure that your pushed commits
-# will be processed properly.
-
-refs = $stdin.read
-key_id = ENV.delete('GL_ID')
-gl_repository = ENV['GL_REPOSITORY']
-repo_path = Dir.pwd
-
-require_relative '../lib/gitlab_custom_hook'
-require_relative '../lib/hooks_utils'
-require_relative '../lib/gitlab_post_receive'
-
-push_options = HooksUtils.get_push_options
-
-if GitlabPostReceive.new(gl_repository, repo_path, key_id, refs, push_options).exec &&
- GitlabCustomHook.new(repo_path, key_id).post_receive(refs)
- exit 0
-else
- exit 1
-end
diff --git a/hooks/pre-receive b/hooks/pre-receive
index 6ce5879..73740da 100755
--- a/hooks/pre-receive
+++ b/hooks/pre-receive
@@ -1,32 +1,4 @@
-#!/usr/bin/env ruby
+#!/bin/sh
+echo "The gitlab-shell hooks have been migrated to Gitaly, see https://gitlab.com/gitlab-org/gitaly/issues/1226"
+exit 1
-# This file was placed here by GitLab. It makes sure that your pushed commits
-# will be processed properly.
-
-refs = $stdin.read
-key_id = ENV.delete('GL_ID')
-protocol = ENV.delete('GL_PROTOCOL')
-repo_path = Dir.pwd
-gl_repository = ENV['GL_REPOSITORY']
-
-def increase_reference_counter(gl_repository, repo_path)
- result = GitlabNet.new.pre_receive(gl_repository)
-
- result && result['reference_counter_increased']
-end
-
-require_relative '../lib/gitlab_custom_hook'
-require_relative '../lib/gitlab_access'
-require_relative '../lib/gitlab_net'
-
-# It's important that on pre-receive `increase_reference_counter` gets executed
-# last so that it only runs if everything else succeeded. On post-receive on the
-# other hand, we run GitlabPostReceive first because the push is already done
-# and we don't want to skip it if the custom hook fails.
-if GitlabAccess.new(gl_repository, repo_path, key_id, refs, protocol).exec &&
- GitlabCustomHook.new(repo_path, key_id).pre_receive(refs) &&
- increase_reference_counter(gl_repository, repo_path)
- exit 0
-else
- exit 1
-end
diff --git a/hooks/update b/hooks/update
index 4c2fc08..73740da 100755
--- a/hooks/update
+++ b/hooks/update
@@ -1,18 +1,4 @@
-#!/usr/bin/env ruby
+#!/bin/sh
+echo "The gitlab-shell hooks have been migrated to Gitaly, see https://gitlab.com/gitlab-org/gitaly/issues/1226"
+exit 1
-# This file was placed here by GitLab. It makes sure that your pushed commits
-# will be processed properly.
-
-ref_name = ARGV[0]
-old_value = ARGV[1]
-new_value = ARGV[2]
-repo_path = Dir.pwd
-key_id = ENV.delete('GL_ID')
-
-require_relative '../lib/gitlab_custom_hook'
-
-if GitlabCustomHook.new(repo_path, key_id).update(ref_name, old_value, new_value)
- exit 0
-else
- exit 1
-end
diff --git a/lib/gitlab_access.rb b/lib/gitlab_access.rb
deleted file mode 100644
index 72abd14..0000000
--- a/lib/gitlab_access.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require_relative 'gitlab_init'
-require_relative 'gitlab_net'
-require_relative 'gitlab_access_status'
-require_relative 'gitlab_metrics'
-require_relative 'object_dirs_helper'
-require 'json'
-
-class GitlabAccess
- class AccessDeniedError < StandardError; end
-
- attr_reader :config, :gl_repository, :repo_path, :changes, :protocol
-
- def initialize(gl_repository, repo_path, actor, changes, protocol)
- @config = GitlabConfig.new
- @gl_repository = gl_repository
- @repo_path = repo_path.strip
- @actor = actor
- @changes = changes.lines
- @protocol = protocol
- end
-
- def exec
- status = GitlabMetrics.measure('check-access:git-receive-pack') do
- api.check_access('git-receive-pack', @gl_repository, @repo_path, @actor, @changes, @protocol, env: ObjectDirsHelper.all_attributes.to_json)
- end
-
- raise AccessDeniedError, status.message unless status.allowed?
-
- true
- rescue GitlabNet::ApiUnreachableError
- $stderr.puts "GitLab: Failed to authorize your Git request: internal API unreachable"
- false
- rescue AccessDeniedError => ex
- $stderr.puts "GitLab: #{ex.message}"
- false
- end
-
- protected
-
- def api
- GitlabNet.new
- end
-end
diff --git a/lib/gitlab_custom_hook.rb b/lib/gitlab_custom_hook.rb
deleted file mode 100644
index 67096df..0000000
--- a/lib/gitlab_custom_hook.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-require 'open3'
-require_relative 'gitlab_init'
-require_relative 'gitlab_metrics'
-
-class GitlabCustomHook
- attr_reader :vars, :config
-
- def initialize(repo_path, key_id)
- @repo_path = repo_path
- @vars = { 'GL_ID' => key_id }
- @config = GitlabConfig.new
- end
-
- def pre_receive(changes)
- GitlabMetrics.measure("pre-receive-hook") do
- find_hooks('pre-receive').all? do |hook|
- call_receive_hook(hook, changes)
- end
- end
- end
-
- def post_receive(changes)
- GitlabMetrics.measure("post-receive-hook") do
- find_hooks('post-receive').all? do |hook|
- call_receive_hook(hook, changes)
- end
- end
- end
-
- def update(ref_name, old_value, new_value)
- GitlabMetrics.measure("update-hook") do
- find_hooks('update').all? do |hook|
- system(vars, hook, ref_name, old_value, new_value)
- end
- end
- end
-
- private
-
- def call_receive_hook(hook, changes)
- # Prepare the hook subprocess. Attach a pipe to its stdin, and merge
- # both its stdout and stderr into our own stdout.
- stdin_reader, stdin_writer = IO.pipe
- hook_pid = spawn(vars, hook, in: stdin_reader, err: :out)
- stdin_reader.close
-
- # Submit changes to the hook via its stdin.
- begin
- IO.copy_stream(StringIO.new(changes), stdin_writer)
- rescue Errno::EPIPE # rubocop:disable Lint/HandleExceptions
- # It is not an error if the hook does not consume all of its input.
- end
-
- # Close the pipe to let the hook know there is no further input.
- stdin_writer.close
-
- Process.wait(hook_pid)
- $?.success?
- end
-
- # lookup hook files in this order:
- #
- # 1. <repository>.git/custom_hooks/<hook_name> - per project hook
- # 2. <repository>.git/custom_hooks/<hook_name>.d/* - per project hooks
- # 3. <repository>.git/hooks/<hook_name>.d/* - global hooks
- #
- def find_hooks(hook_name)
- hook_files = []
-
- # <repository>.git/custom_hooks/<hook_name>
- project_custom_hook_file = File.join(@repo_path, 'custom_hooks', hook_name)
- hook_files.push(project_custom_hook_file) if File.executable?(project_custom_hook_file)
-
- # <repository>.git/custom_hooks/<hook_name>.d/*
- project_custom_hooks_dir = File.join(@repo_path, 'custom_hooks', "#{hook_name}.d")
- hook_files += match_hook_files(project_custom_hooks_dir)
-
- # <repository>.git/hooks/<hook_name>.d/* OR <custom_hook_dir>/<hook_name>.d/*
- global_custom_hooks_parent = config.custom_hooks_dir(default: File.join(@repo_path, 'hooks'))
- global_custom_hooks_dir = File.join(global_custom_hooks_parent, "#{hook_name}.d")
- hook_files += match_hook_files(global_custom_hooks_dir)
-
- hook_files
- end
-
- # match files from path:
- # 1. file must be executable
- # 2. file must not match backup file
- #
- # the resulting list is sorted
- def match_hook_files(path)
- return [] unless Dir.exist?(path)
-
- Dir["#{path}/*"].select do |f|
- !f.end_with?('~') && File.executable?(f)
- end.sort
- end
-end
diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb
index a84ba84..07fef22 100644
--- a/lib/gitlab_net.rb
+++ b/lib/gitlab_net.rb
@@ -3,7 +3,6 @@ require 'openssl'
require 'json'
require_relative 'gitlab_config'
-require_relative 'gitlab_access'
require_relative 'gitlab_lfs_authentication'
require_relative 'http_helper'
diff --git a/lib/gitlab_post_receive.rb b/lib/gitlab_post_receive.rb
deleted file mode 100644
index 7c5bd19..0000000
--- a/lib/gitlab_post_receive.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-require_relative 'gitlab_init'
-require_relative 'gitlab_net'
-require_relative 'gitlab_metrics'
-require 'json'
-require 'base64'
-require 'securerandom'
-
-class GitlabPostReceive
- attr_reader :config, :gl_repository, :repo_path, :changes, :jid
-
- def initialize(gl_repository, repo_path, actor, changes, push_options)
- @config = GitlabConfig.new
- @gl_repository = gl_repository
- @repo_path = repo_path.strip
- @actor = actor
- @changes = changes
- @push_options = push_options
- @jid = SecureRandom.hex(12)
- end
-
- def exec
- response = GitlabMetrics.measure("post-receive") do
- api.post_receive(gl_repository, @actor, changes, @push_options)
- end
-
- return false unless response
- print_formatted_alert_message(response['broadcast_message']) if response['broadcast_message']
- print_merge_request_links(response['merge_request_urls']) if response['merge_request_urls']
- puts response['redirected_message'] if response['redirected_message']
- puts response['project_created_message'] if response['project_created_message']
- print_warnings(response['warnings']) if response['warnings']
-
- response['reference_counter_decreased']
- rescue GitlabNet::ApiUnreachableError
- false
- end
-
- protected
-
- def api
- @api ||= GitlabNet.new
- end
-
- def print_merge_request_links(merge_request_urls)
- return if merge_request_urls.empty?
- puts
- merge_request_urls.each { |mr| print_merge_request_link(mr) }
- end
-
- def print_merge_request_link(merge_request)
- message =
- if merge_request["new_merge_request"]
- "To create a merge request for #{merge_request['branch_name']}, visit:"
- else
- "View merge request for #{merge_request['branch_name']}:"
- end
-
- puts message
- puts((" " * 2) + merge_request["url"])
- puts
- end
-
- def print_warnings(warnings)
- message = "WARNINGS:\n#{warnings}"
- print_formatted_alert_message(message)
- end
-
- def print_formatted_alert_message(message)
- # A standard terminal window is (at least) 80 characters wide.
- total_width = 80
-
- # Git prefixes remote messages with "remote: ", so this width is subtracted
- # from the width available to us.
- total_width -= "remote: ".length # rubocop:disable Performance/FixedSize
-
- # Our centered text shouldn't start or end right at the edge of the window,
- # so we add some horizontal padding: 2 chars on either side.
- text_width = total_width - 2 * 2
-
- # Automatically wrap message at text_width (= 68) characters:
- # Splits the message up into the longest possible chunks matching
- # "<between 0 and text_width characters><space or end-of-line>".
-
- msg_start_idx = 0
- lines = []
- while msg_start_idx < message.length
- parsed_line = parse_broadcast_msg(message[msg_start_idx..-1], text_width)
- msg_start_idx += parsed_line.length
- lines.push(parsed_line.strip)
- end
-
- puts
- puts "=" * total_width
- puts
-
- lines.each do |line|
- line.strip!
-
- # Center the line by calculating the left padding measured in characters.
- line_padding = [(total_width - line.length) / 2, 0].max
- puts((" " * line_padding) + line)
- end
-
- puts
- puts "=" * total_width
- end
-
- private
-
- def parse_broadcast_msg(msg, text_length)
- msg ||= ""
- # just return msg if shorter than or equal to text length
- return msg if msg.length <= text_length
-
- # search for word break shorter than text length
- truncate_to_space = msg.match(/\A(.{,#{text_length}})(?=\s|$)(\s*)/).to_s
-
- if truncate_to_space.empty?
- # search for word break longer than text length
- truncate_to_space = msg.match(/\A\S+/).to_s
- end
-
- truncate_to_space
- end
-end
diff --git a/spec/gitlab_access_spec.rb b/spec/gitlab_access_spec.rb
deleted file mode 100644
index 6c1d348..0000000
--- a/spec/gitlab_access_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-require 'gitlab_access'
-
-describe GitlabAccess do
- let(:repository_path) { "/home/git/repositories" }
- let(:repo_name) { 'dzaporozhets/gitlab-ci' }
- let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
- let(:api) do
- double(GitlabNet).tap do |api|
- allow(api).to receive(:check_access).and_return(GitAccessStatus.new(true,
- '200',
- 'ok',
- gl_repository: 'project-1',
- gl_project_path: 'group/subgroup/project',
- gl_id: 'user-123',
- gl_username: 'testuser',
- git_config_options: ['receive.MaxInputSize=10000'],
- gitaly: nil,
- git_protocol: 'version=2'))
- end
- end
- subject do
- GitlabAccess.new(nil, repo_path, 'key-123', 'wow', 'ssh').tap do |access|
- allow(access).to receive(:exec_cmd).and_return(:exec_called)
- allow(access).to receive(:api).and_return(api)
- end
- end
-
- before do
- allow_any_instance_of(GitlabConfig).to receive(:repos_path).and_return(repository_path)
- end
-
- describe :initialize do
- it { expect(subject.repo_path).to eq(repo_path) }
- it { expect(subject.changes).to eq(['wow']) }
- it { expect(subject.protocol).to eq('ssh') }
- end
-
- describe "#exec" do
- context "access is granted" do
- it "returns true" do
- expect(subject.exec).to be_truthy
- end
- end
-
- context "access is denied" do
- before do
- allow(api).to receive(:check_access).and_return(GitAccessStatus.new(
- false,
- '401',
- 'denied',
- gl_repository: nil,
- gl_project_path: nil,
- gl_id: nil,
- gl_username: nil,
- git_config_options: nil,
- gitaly: nil,
- git_protocol: nil
- ))
- end
-
- it "returns false" do
- expect(subject.exec).to be_falsey
- end
- end
-
- context "API connection fails" do
- before do
- allow(api).to receive(:check_access).and_raise(GitlabNet::ApiUnreachableError)
- end
-
- it "returns false" do
- expect(subject.exec).to be_falsey
- end
- end
- end
-end
diff --git a/spec/gitlab_custom_hook_spec.rb b/spec/gitlab_custom_hook_spec.rb
deleted file mode 100644
index 540cd2b..0000000
--- a/spec/gitlab_custom_hook_spec.rb
+++ /dev/null
@@ -1,295 +0,0 @@
-# coding: utf-8
-require 'spec_helper'
-require 'gitlab_custom_hook'
-
-describe GitlabCustomHook do
- let(:original_root_path) { ROOT_PATH }
- let(:tmp_repo_path) { File.join(original_root_path, 'tmp', 'repo.git') }
- let(:tmp_root_path) { File.join(original_root_path, 'tmp') }
- let(:global_custom_hooks_path) { global_hook_path('custom_global_hooks') }
- let(:hook_ok) { File.join(original_root_path, 'spec', 'support', 'hook_ok') }
- let(:hook_fail) { File.join(original_root_path, 'spec', 'support', 'hook_fail') }
- let(:hook_gl_id) { File.join(original_root_path, 'spec', 'support', 'gl_id_test_hook') }
-
- let(:vars) { { "GL_ID" => "key_1" } }
- let(:old_value) { "old-value" }
- let(:new_value) { "new-value" }
- let(:ref_name) { "name/of/ref" }
- let(:changes) { "#{old_value} #{new_value} #{ref_name}\n" }
-
- let(:gitlab_custom_hook) { GitlabCustomHook.new(tmp_repo_path, 'key_1') }
-
- def hook_path(path)
- File.join(tmp_repo_path, path.split('/'))
- end
-
- def global_hook_path(path)
- File.join(tmp_root_path, path.split('/'))
- end
-
- def create_hook(path, which)
- FileUtils.ln_sf(which, hook_path(path))
- end
-
- # global hooks multiplexed
- def create_global_hooks_d(which, hook_name = 'hook')
- create_hook('hooks/pre-receive.d/' + hook_name, which)
- create_hook('hooks/update.d/' + hook_name, which)
- create_hook('hooks/post-receive.d/' + hook_name, which)
- end
-
- # repo hooks
- def create_repo_hooks(which)
- create_hook('custom_hooks/pre-receive', which)
- create_hook('custom_hooks/update', which)
- create_hook('custom_hooks/post-receive', which)
- end
-
- # repo hooks multiplexed
- def create_repo_hooks_d(which, hook_name = 'hook')
- create_hook('custom_hooks/pre-receive.d/' + hook_name, which)
- create_hook('custom_hooks/update.d/' + hook_name, which)
- create_hook('custom_hooks/post-receive.d/' + hook_name, which)
- end
-
- def cleanup_hook_setup
- FileUtils.rm_rf(File.join(tmp_repo_path))
- FileUtils.rm_rf(File.join(global_custom_hooks_path))
- FileUtils.rm_rf(File.join(tmp_root_path, 'hooks'))
- FileUtils.rm_f(File.join(tmp_root_path, 'config.yml'))
- end
-
- def expect_call_receive_hook(path)
- expect(gitlab_custom_hook)
- .to receive(:call_receive_hook)
- .with(hook_path(path), changes)
- .and_call_original
- end
-
- def expect_call_update_hook(path)
- expect(gitlab_custom_hook)
- .to receive(:system)
- .with(vars, hook_path(path), ref_name, old_value, new_value)
- .and_call_original
- end
-
- # setup paths
- # <repository>.git/hooks/ - symlink to gitlab-shell/hooks global dir
- # <repository>.git/hooks/<hook_name> - executed by git itself, this is gitlab-shell/hooks/<hook_name>
- # <repository>.git/hooks/<hook_name>.d/* - global hooks: all executable files (minus editor backup files)
- # <repository>.git/custom_hooks/<hook_name> - per project hook (this is already existing behavior)
- # <repository>.git/custom_hooks/<hook_name>.d/* - per project hooks
- #
- # custom hooks are invoked in such way that first failure prevents other scripts being ran
- # as global scripts are ran first, failing global skips repo hooks
-
- before do
- cleanup_hook_setup
-
- FileUtils.mkdir_p(File.join(tmp_repo_path, 'custom_hooks'))
- FileUtils.mkdir_p(File.join(tmp_root_path, 'hooks'))
-
- ['pre-receive', 'update', 'post-receive'].each do |hook|
- FileUtils.mkdir_p(File.join(tmp_repo_path, 'custom_hooks', "#{hook}.d"))
- FileUtils.mkdir_p(File.join(tmp_root_path, 'hooks', "#{hook}.d"))
- end
-
- FileUtils.symlink(File.join(tmp_root_path, 'hooks'), File.join(tmp_repo_path, 'hooks'))
- FileUtils.symlink(File.join(ROOT_PATH, 'config.yml.example'), File.join(tmp_root_path, 'config.yml'))
-
- stub_const('ROOT_PATH', tmp_root_path)
- end
-
- after do
- cleanup_hook_setup
- end
-
- context 'with gl_id_test_hook as repo hook' do
- before do
- create_repo_hooks(hook_gl_id)
- end
-
- context 'pre_receive hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- end
- end
-
- context 'post_receive hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.post_receive(changes)).to eq(true)
- end
- end
-
- context 'update hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(true)
- end
- end
- end
-
- context 'with gl_id_test_hook as global hook' do
- before do
- create_global_hooks_d(hook_gl_id)
- end
-
- context 'pre_receive hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- end
- end
-
- context 'post_receive hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.post_receive(changes)).to eq(true)
- end
- end
-
- context 'update hook' do
- it 'passes GL_ID variable to hook' do
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(true)
- end
- end
- end
-
- context "having no hooks" do
- it "returns true" do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(true)
- expect(gitlab_custom_hook.post_receive(changes)).to eq(true)
- end
- end
-
- context "having only successful repo hooks" do
- before do
- create_repo_hooks(hook_ok)
- end
-
- it "returns true" do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(true)
- expect(gitlab_custom_hook.post_receive(changes)).to eq(true)
- end
- end
-
- context "having both successful repo and global hooks" do
- before do
- create_repo_hooks(hook_ok)
- create_global_hooks_d(hook_ok)
- end
-
- it "returns true" do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(true)
- expect(gitlab_custom_hook.post_receive(changes)).to eq(true)
- end
- end
-
- context "having failing repo and successful global hooks" do
- before do
- create_repo_hooks_d(hook_fail)
- create_global_hooks_d(hook_ok)
- end
-
- it "returns false" do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(false)
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(false)
- expect(gitlab_custom_hook.post_receive(changes)).to eq(false)
- end
-
- it "only executes the global hook" do
- expect_call_receive_hook("custom_hooks/pre-receive.d/hook")
- expect_call_update_hook("custom_hooks/update.d/hook")
- expect_call_receive_hook("custom_hooks/post-receive.d/hook")
-
- gitlab_custom_hook.pre_receive(changes)
- gitlab_custom_hook.update(ref_name, old_value, new_value)
- gitlab_custom_hook.post_receive(changes)
- end
- end
-
- context "having successful repo but failing global hooks" do
- before do
- create_repo_hooks_d(hook_ok)
- create_global_hooks_d(hook_fail)
- end
-
- it "returns false" do
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(false)
- expect(gitlab_custom_hook.update(ref_name, old_value, new_value)).to eq(false)
- expect(gitlab_custom_hook.post_receive(changes)).to eq(false)
- end
-
- it "executes the relevant hooks" do
- expect_call_receive_hook("hooks/pre-receive.d/hook")
- expect_call_receive_hook("custom_hooks/pre-receive.d/hook")
- expect_call_update_hook("hooks/update.d/hook")
- expect_call_update_hook("custom_hooks/update.d/hook")
- expect_call_receive_hook("hooks/post-receive.d/hook")
- expect_call_receive_hook("custom_hooks/post-receive.d/hook")
-
- gitlab_custom_hook.pre_receive(changes)
- gitlab_custom_hook.update(ref_name, old_value, new_value)
- gitlab_custom_hook.post_receive(changes)
- end
- end
-
- context "executing hooks in expected order" do
- before do
- create_repo_hooks_d(hook_ok, '01-test')
- create_repo_hooks_d(hook_ok, '02-test')
- create_global_hooks_d(hook_ok, '03-test')
- create_global_hooks_d(hook_ok, '04-test')
- end
-
- it "executes hooks in order" do
- expect_call_receive_hook("custom_hooks/pre-receive.d/01-test").ordered
- expect_call_receive_hook("custom_hooks/pre-receive.d/02-test").ordered
- expect_call_receive_hook("hooks/pre-receive.d/03-test").ordered
- expect_call_receive_hook("hooks/pre-receive.d/04-test").ordered
-
- expect_call_update_hook("custom_hooks/update.d/01-test").ordered
- expect_call_update_hook("custom_hooks/update.d/02-test").ordered
- expect_call_update_hook("hooks/update.d/03-test").ordered
- expect_call_update_hook("hooks/update.d/04-test").ordered
-
- expect_call_receive_hook("custom_hooks/post-receive.d/01-test").ordered
- expect_call_receive_hook("custom_hooks/post-receive.d/02-test").ordered
- expect_call_receive_hook("hooks/post-receive.d/03-test").ordered
- expect_call_receive_hook("hooks/post-receive.d/04-test").ordered
-
- gitlab_custom_hook.pre_receive(changes)
- gitlab_custom_hook.update(ref_name, old_value, new_value)
- gitlab_custom_hook.post_receive(changes)
- end
- end
-
- context "when the custom_hooks_dir config option is set" do
- before do
- allow(gitlab_custom_hook.config).to receive(:custom_hooks_dir).and_return(global_custom_hooks_path)
-
- FileUtils.mkdir_p(File.join(global_custom_hooks_path, "pre-receive.d"))
- FileUtils.ln_sf(hook_ok, File.join(global_custom_hooks_path, "pre-receive.d", "hook"))
-
- create_global_hooks_d(hook_fail)
- end
-
- it "finds hooks in that directory" do
- expect(gitlab_custom_hook)
- .to receive(:call_receive_hook)
- .with(global_hook_path("custom_global_hooks/pre-receive.d/hook"), changes)
- .and_call_original
-
- expect(gitlab_custom_hook.pre_receive(changes)).to eq(true)
- end
-
- it "does not execute hooks in the default location" do
- expect(gitlab_custom_hook)
- .not_to receive(:call_receive_hook)
- .with("hooks/pre-receive.d/hook", changes)
- .and_call_original
-
- gitlab_custom_hook.pre_receive(changes)
- end
- end
-end
diff --git a/spec/gitlab_post_receive_spec.rb b/spec/gitlab_post_receive_spec.rb
deleted file mode 100644
index d061830..0000000
--- a/spec/gitlab_post_receive_spec.rb
+++ /dev/null
@@ -1,284 +0,0 @@
-# coding: utf-8
-require 'spec_helper'
-require 'gitlab_post_receive'
-
-describe GitlabPostReceive do
- let(:repository_path) { "/home/git/repositories" }
- let(:repo_name) { 'dzaporozhets/gitlab-ci' }
- let(:actor) { 'key-123' }
- let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
- let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
- let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
- let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
- let(:gl_repository) { "project-1" }
- let(:push_options) { [] }
- let(:gitlab_post_receive) { GitlabPostReceive.new(gl_repository, repo_path, actor, wrongly_encoded_changes, push_options) }
- let(:broadcast_message) { "test " * 10 + "message " * 10 }
- let(:enqueued_at) { Time.new(2016, 6, 23, 6, 59) }
- let(:new_merge_request_urls) do
- [{
- 'branch_name' => 'new_branch',
- 'url' => 'http://localhost/dzaporozhets/gitlab-ci/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch',
- 'new_merge_request' => true
- }]
- end
- let(:existing_merge_request_urls) do
- [{
- 'branch_name' => 'feature_branch',
- 'url' => 'http://localhost/dzaporozhets/gitlab-ci/merge_requests/1',
- 'new_merge_request' => false
- }]
- end
-
- before do
- $logger = double('logger').as_null_object # Global vars are bad
- allow_any_instance_of(GitlabConfig).to receive(:repos_path).and_return(repository_path)
- end
-
- describe "#exec" do
- let(:response) { { 'reference_counter_decreased' => true } }
-
- it 'calls the api to notify the execution of the hook' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
-
- expect(gitlab_post_receive.exec).to eq(true)
- end
-
- context 'merge request urls and broadcast messages' do
- let(:response) do
- {
- 'reference_counter_decreased' => true,
- 'merge_request_urls' => new_merge_request_urls,
- 'broadcast_message' => broadcast_message
- }
- end
-
- it 'prints the merge request urls and broadcast message' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- assert_broadcast_message_printed(gitlab_post_receive)
- assert_new_mr_printed(gitlab_post_receive)
-
- expect(gitlab_post_receive.exec).to eq(true)
- end
-
- context 'when contains long url string at end' do
- let(:broadcast_message) { "test " * 10 + "message " * 10 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url" }
-
- it 'doesnt truncate url' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- assert_broadcast_message_printed_keep_long_url_end(gitlab_post_receive)
- assert_new_mr_printed(gitlab_post_receive)
-
- expect(gitlab_post_receive.exec).to eq(true)
- end
- end
-
- context 'when contains long url string at start' do
- let(:broadcast_message) { "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "test " * 10 + "message " * 11}
-
- it 'doesnt truncate url' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- assert_broadcast_message_printed_keep_long_url_start(gitlab_post_receive)
- assert_new_mr_printed(gitlab_post_receive)
-
- expect(gitlab_post_receive.exec).to eq(true)
- end
- end
-
- context 'when contains long url string in middle' do
- let(:broadcast_message) { "test " * 11 + "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url " + "message " * 11}
-
- it 'doesnt truncate url' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- assert_broadcast_message_printed_keep_long_url_middle(gitlab_post_receive)
- assert_new_mr_printed(gitlab_post_receive)
-
- expect(gitlab_post_receive.exec).to eq(true)
- end
- end
- end
-
- context 'when warnings are present' do
- let(:response) do
- {
- 'reference_counter_decreased' => true,
- 'warnings' => 'My warning message'
- }
- end
-
- it 'treats the warning as a broadcast message' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- expect(gitlab_post_receive).to receive(:print_formatted_alert_message).with("WARNINGS:\nMy warning message")
- expect(gitlab_post_receive.exec).to eq(true)
- end
- end
-
- context 'when redirected message available' do
- let(:message) { "This is a redirected message" }
- let(:response) do
- {
- 'reference_counter_decreased' => true,
- 'redirected_message' => message
- }
- end
-
- it 'prints redirected message' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
- assert_redirected_message_printed(gitlab_post_receive)
- expect(gitlab_post_receive.exec).to eq(true)
- end
-
- context 'when project created message is available' do
- let(:message) { "This is a created project message" }
- let(:response) do
- {
- 'reference_counter_decreased' => true,
- 'project_created_message' => message
- }
- end
-
- it 'prints project created message' do
- expect_any_instance_of(GitlabNet).to receive(:post_receive).and_return(response)
-
- assert_project_created_message_printed(gitlab_post_receive)
-
- expect(gitlab_post_receive.exec).to be true
- end
- end
- end
- end
-
- private
-
- def assert_new_mr_printed(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "To create a merge request for new_branch, visit:"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- " http://localhost/dzaporozhets/gitlab-ci/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
- end
-
- def assert_existing_mr_printed(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "View merge request for feature_branch:"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- " http://localhost/dzaporozhets/gitlab-ci/merge_requests/1"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
- end
-
- def assert_broadcast_message_printed(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " test test test test test test test test test test message message"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- " message message message message message message message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- end
-
- def assert_redirected_message_printed(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).with("This is a redirected message")
- end
-
- def assert_project_created_message_printed(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).with("This is a created project message")
- end
-
- def assert_broadcast_message_printed_keep_long_url_end(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " test test test test test test test test test test message message"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- " message message message message message message message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- end
-
- def assert_broadcast_message_printed_keep_long_url_start(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " test test test test test test test test test test message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " message message message message message message message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- end
-
- def assert_broadcast_message_printed_keep_long_url_middle(gitlab_post_receive)
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- expect(gitlab_post_receive).to receive(:puts).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " test test test test test test test test test test test"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- "https://localhost:5000/test/a/really/long/url/that/is/in/the/broadcast/message/do-not-truncate-when-url"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " message message message message message message message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).with(
- " message message message"
- ).ordered
-
- expect(gitlab_post_receive).to receive(:puts).ordered
- expect(gitlab_post_receive).to receive(:puts).with(
- "========================================================================"
- ).ordered
- end
-end