Add latest changes from gitlab-org/gitlab@master

[skip secret push protection]
This commit is contained in:
GitLab Bot
2026-01-05 00:12:52 +00:00
parent 23d1e473f0
commit 34ded62c8a
3 changed files with 41 additions and 15 deletions

View File

@ -126,12 +126,12 @@ module QA
run_git("git rev-parse --abbrev-ref HEAD").to_s
end
def push_changes(branch = @default_branch, push_options: nil, max_attempts: 3, raise_on_failure: true)
def push_changes(branch = @default_branch, push_options: nil, max_attempts: 3, raise_on_failure: true, timeout: 60)
cmd = ['git push']
cmd << push_options_hash_to_string(push_options)
cmd << uri
cmd << branch
run_git(cmd.compact.join(' '), raise_on_failure: raise_on_failure, max_attempts: max_attempts).to_s
run_git(cmd.compact.join(' '), raise_on_failure: raise_on_failure, max_attempts: max_attempts, timeout: timeout).to_s
end
def push_all_branches
@ -335,14 +335,15 @@ module QA
read_netrc_content.grep(/^#{Regexp.escape(netrc_content)}$/).any?
end
def run_git(command_str, raise_on_failure: true, env: env_vars, max_attempts: 1)
def run_git(command_str, raise_on_failure: true, env: env_vars, max_attempts: 1, timeout: nil)
run(
command_str,
raise_on_failure: raise_on_failure,
env: env,
max_attempts: max_attempts,
sleep_internal: command_retry_sleep_interval,
log_prefix: 'Git: '
log_prefix: 'Git: ',
timeout: timeout
)
end
end

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'open3'
require 'timeout'
module QA
module Support
@ -8,6 +9,7 @@ module QA
include QA::Support::Repeater
CommandError = Class.new(StandardError)
CommandTimeoutError = Class.new(CommandError)
Result = Struct.new(:command, :exitstatus, :response) do
alias_method :to_s, :response
@ -21,26 +23,44 @@ module QA
end
end
def run(command_str, raise_on_failure: true, env: [], max_attempts: 1, sleep_internal: 0, log_prefix: '')
def run(
command_str,
raise_on_failure: true,
env: [],
max_attempts: 1,
sleep_internal: 0,
log_prefix: '',
timeout: nil
)
command = [*env, command_str, '2>&1'].compact.join(' ')
result = nil
repeat_until(max_attempts: max_attempts, sleep_interval: sleep_internal, raise_on_failure: false) do
repeat_until(
max_attempts: max_attempts,
sleep_interval: sleep_internal,
raise_on_failure: false
) do
Runtime::Logger.debug "#{log_prefix}pwd=[#{Dir.pwd}], command=[#{command}]"
output, status = Open3.capture2e(command)
output.chomp!
Runtime::Logger.debug "#{log_prefix}output=[#{output}], exitstatus=[#{status.exitstatus}]"
result = Result.new(command, status.exitstatus, output)
begin
output, status = timeout ? Timeout.timeout(timeout) { Open3.capture2e(command) } : Open3.capture2e(command)
output.chomp!
Runtime::Logger.debug "#{log_prefix}output=[#{output}], exitstatus=[#{status.exitstatus}]"
result.success?
result = Result.new(command, status.exitstatus, output)
result.success?
rescue Timeout::Error
Runtime::Logger.debug "#{log_prefix}command timed out after #{timeout} seconds"
raise CommandTimeoutError, "The command #{command} timed out after #{timeout} seconds"
end
end
raise_error = raise_on_failure && !result.success?
if raise_error
raise CommandError,
"The command #{result.command} failed (#{result.exitstatus}) with the following output:\n#{result.response}"
"The command #{result.command} failed (#{result.exitstatus}) " \
"with the following output:\n#{result.response}"
end
result

View File

@ -45,7 +45,7 @@ RSpec.describe QA::Git::Repository do
context 'when command is successful' do
it 'returns the #run command Result output' do
expect(repository).to receive(:run).with(command, run_params.merge(max_attempts: 3)).and_return(result)
expect(repository).to receive(:run).with(command, run_params.merge(max_attempts: 3, timeout: timeout)).and_return(result)
expect(call_method).to eq(command_return)
end
@ -81,7 +81,7 @@ RSpec.describe QA::Git::Repository do
context 'when command is successful' do
it 'returns the #run command Result output' do
expect(repository).to receive(:run).with(command, run_params.merge(max_attempts: 1)).and_return(result)
expect(repository).to receive(:run).with(command, run_params.merge(max_attempts: 1, timeout: timeout)).and_return(result)
expect(call_method).to eq(command_return)
end
@ -110,6 +110,7 @@ RSpec.describe QA::Git::Repository do
let(:opts) { '' }
let(:call_method) { repository.clone }
let(:command) { "git clone #{opts} #{repo_uri_with_credentials} ./" }
let(:timeout) { nil }
context 'when no opts is given' do
it_behaves_like 'command with retries'
@ -128,6 +129,7 @@ RSpec.describe QA::Git::Repository do
it_behaves_like 'command with retries' do
let(:call_method) { repository.shallow_clone }
let(:command) { "git clone --depth 1 #{repo_uri_with_credentials} ./" }
let(:timeout) { nil }
end
end
@ -136,6 +138,7 @@ RSpec.describe QA::Git::Repository do
let(:tag_name) { 'v1.0' }
let(:call_method) { repository.delete_tag(tag_name) }
let(:command) { "git push origin --delete #{tag_name}" }
let(:timeout) { nil }
end
end
@ -143,6 +146,7 @@ RSpec.describe QA::Git::Repository do
let(:branch) { QA::Runtime::Env.default_branch }
let(:call_method) { repository.push_changes }
let(:command) { "git push #{repo_uri_with_credentials} #{branch}" }
let(:timeout) { 60 }
context 'when no branch is given' do
it_behaves_like 'command with retries'
@ -234,7 +238,7 @@ RSpec.describe QA::Git::Repository do
[0, 1, 2].each do |version|
it "configures git to use protocol version #{version}" do
expect(repository).to receive(:run).with("git config protocol.version #{version}",
run_params.merge(max_attempts: 1))
run_params.merge(max_attempts: 1, timeout: nil))
repository.git_protocol = version
end
@ -256,6 +260,7 @@ RSpec.describe QA::Git::Repository do
let(:result_output) { +'packet: ls-remote< version 2' }
let(:command_return) { '2' }
let(:extra_env_vars) { ["GIT_TRACE_PACKET=1"] }
let(:timeout) { nil }
end
it "reports the detected version" do