1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
# frozen_string_literal: true
# This file contains environment settings for gitaly when it's running
# as part of the gitlab-ce/ee test suite.
#
# Please be careful when modifying this file. Your changes must work
# both for local development rspec runs, and in CI.
require 'securerandom'
require 'socket'
require 'logger'
module GitalyTest
LOGGER = begin
default_name = ENV['CI'] ? 'DEBUG' : 'WARN'
level_name = ENV['GITLAB_TESTING_LOG_LEVEL']&.upcase
level = Logger.const_get(level_name || default_name, true) # rubocop: disable Gitlab/ConstGetInheritFalse
Logger.new(STDOUT, level: level, formatter: ->(_, _, _, msg) { msg })
end
def tmp_tests_gitaly_dir
File.expand_path('../tmp/tests/gitaly', __dir__)
end
def tmp_tests_gitlab_shell_dir
File.expand_path('../tmp/tests/gitlab-shell', __dir__)
end
def rails_gitlab_shell_secret
File.expand_path('../.gitlab_shell_secret', __dir__)
end
def gemfile
File.join(tmp_tests_gitaly_dir, 'ruby', 'Gemfile')
end
def gemfile_dir
File.dirname(gemfile)
end
def gitlab_shell_secret_file
File.join(tmp_tests_gitlab_shell_dir, '.gitlab_shell_secret')
end
def env
env_hash = {
'HOME' => File.expand_path('tmp/tests'),
'GEM_PATH' => Gem.path.join(':'),
'BUNDLE_APP_CONFIG' => File.join(gemfile_dir, '.bundle'),
'BUNDLE_INSTALL_FLAGS' => nil,
'BUNDLE_GEMFILE' => gemfile,
'RUBYOPT' => nil,
# Git hooks can't run during tests as the internal API is not running.
'GITALY_TESTING_NO_GIT_HOOKS' => "1"
}
env_hash
end
# rubocop:disable GitlabSecurity/SystemCommandInjection
def set_bundler_config
system('bundle config set --local jobs 4', chdir: gemfile_dir)
system('bundle config set --local retry 3', chdir: gemfile_dir)
if ENV['CI']
bundle_path = File.expand_path('../vendor/gitaly-ruby', __dir__)
system('bundle', 'config', 'set', '--local', 'path', bundle_path, chdir: gemfile_dir)
end
end
# rubocop:enable GitlabSecurity/SystemCommandInjection
def config_path(service)
case service
when :gitaly
File.join(tmp_tests_gitaly_dir, 'config.toml')
when :gitaly2
File.join(tmp_tests_gitaly_dir, 'gitaly2.config.toml')
when :praefect
File.join(tmp_tests_gitaly_dir, 'praefect.config.toml')
end
end
def service_binary(service)
case service
when :gitaly, :gitaly2
'gitaly'
when :praefect
'praefect'
end
end
def install_gitaly_gems
system(env, "make #{tmp_tests_gitaly_dir}/.ruby-bundle", chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
end
def build_gitaly
system(env, 'make', chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
end
def start_gitaly
start(:gitaly)
end
def start_gitaly2
start(:gitaly2)
end
def start_praefect
start(:praefect)
end
def start(service)
args = ["#{tmp_tests_gitaly_dir}/#{service_binary(service)}"]
args.push("-config") if service == :praefect
args.push(config_path(service))
pid = spawn(env, *args, [:out, :err] => "log/#{service}-test.log")
begin
try_connect!(service)
rescue
Process.kill('TERM', pid)
raise
end
pid
end
# Taken from Gitlab::Shell.generate_and_link_secret_token
def ensure_gitlab_shell_secret!
secret_file = rails_gitlab_shell_secret
shell_link = gitlab_shell_secret_file
unless File.size?(secret_file)
File.write(secret_file, SecureRandom.hex(16))
end
unless File.exist?(shell_link)
FileUtils.ln_s(secret_file, shell_link)
end
end
def check_gitaly_config!
LOGGER.debug "Checking gitaly-ruby Gemfile...\n"
unless File.exist?(gemfile)
message = "#{gemfile} does not exist."
message += "\n\nThis might have happened if the CI artifacts for this build were destroyed." if ENV['CI']
abort message
end
LOGGER.debug "Checking gitaly-ruby bundle...\n"
out = ENV['CI'] ? STDOUT : '/dev/null'
abort 'bundle check failed' unless system(env, 'bundle', 'check', out: out, chdir: File.dirname(gemfile))
end
def read_socket_path(service)
# This code needs to work in an environment where we cannot use bundler,
# so we cannot easily use the toml-rb gem. This ad-hoc parser should be
# good enough.
config_text = IO.read(config_path(service))
config_text.lines.each do |line|
match_data = line.match(/^\s*socket_path\s*=\s*"([^"]*)"$/)
return match_data[1] if match_data
end
raise "failed to find socket_path in #{config_path(service)}"
end
def try_connect!(service)
LOGGER.debug "Trying to connect to #{service}: "
timeout = 20
delay = 0.1
socket = read_socket_path(service)
Integer(timeout / delay).times do
UNIXSocket.new(socket)
LOGGER.debug " OK\n"
return
rescue Errno::ENOENT, Errno::ECONNREFUSED
LOGGER.debug '.'
sleep delay
end
LOGGER.warn " FAILED to connect to #{service}\n"
raise "could not connect to #{socket}"
end
end
|