spec/lib/gdk/command/update_spec.rb (142 lines of code) (raw):
# frozen_string_literal: true
RSpec.describe GDK::Command::Update do
include ShelloutHelper
let(:sh) { gdk_shellout_double(success?: true) }
let(:gdk_available_after_update?) { true }
before do
allow(GDK::Hooks).to receive(:execute_hooks)
allow(GDK).to receive(:make).and_return(sh)
allow_gdk_shellout_command(%w[git rev-parse HEAD], chdir: GDK.config.gdk_root).and_return(
gdk_shellout_double(success?: true, run: 'abcdef1234')
)
reconfigure_task = instance_double(Rake::Task, invoke: nil)
allow(Rake::Task).to receive(:[]).with(:reconfigure).and_return(reconfigure_task)
allow(Utils).to receive(:executable_exist_via_tooling_manager?).and_return(gdk_available_after_update?)
gdk_migrate_task = instance_double(Rake::Task, invoke: nil)
allow(Rake::Task).to receive(:[]).with('gdk:migrate').and_return(gdk_migrate_task)
# Stubs for run_weekly_diagnostics
allow_gdk_shellout_command('asdf').and_return(
gdk_shellout_double(success?: true, readlines: [])
)
allow(GDK.config).to receive(:__cache_dir).and_return(Pathname.new('/fake/cache'))
allow(FileUtils).to receive(:mkdir_p)
allow(File).to receive(:exist?).and_return(false)
allow(File).to receive(:write)
end
describe '#run', :hide_output do
let(:env) { { 'PG_AUTO_UPDATE' => '1' } }
context 'when self-update is enabled' do
it 'runs self-update and update' do
expect(GDK).to receive(:make).with('self-update')
task = instance_double(Rake::Task, invoke: nil)
expect(Rake::Task).to receive(:[]).with(:update).and_return(task)
expect_any_instance_of(GDK::Announcements).to receive(:render_all)
expect(GDK::Output).to receive(:success).with('Successfully updated!')
subject.run
end
context 'when the sha was updated' do
after do
ENV['GDK_SELF_UPDATE'] = nil
end
it 'runs "gdk update" with the exec syscall' do
expect(GDK).to receive(:make).with('self-update') do
expect_gdk_shellout.with(%w[git rev-parse HEAD], chdir: GDK.config.gdk_root).and_return(
gdk_shellout_double(success?: true, run: 'd06f00d')
)
sh
end
error = 'Kernel.exec stops and replaces the current process'
expect(Kernel).to receive(:exec).with('gdk update').and_raise(error)
expect(Dir).to receive(:chdir).with(GDK.config.gdk_root.to_s)
expect { subject.run }.to raise_error(error)
expect(ENV.fetch('GDK_SELF_UPDATE', nil)).to eq('0')
end
end
end
context 'when self-update is disabled' do
before do
stub_env('GDK_SELF_UPDATE', '0')
end
it 'only runs update' do
expect(GDK).not_to receive(:make).with('self-update')
task = instance_double(Rake::Task, invoke: nil)
expect(Rake::Task).to receive(:[]).with(:update).and_return(task)
expect(task).to receive(:invoke)
expect_any_instance_of(GDK::Announcements).to receive(:render_all)
expect(GDK::Output).to receive(:success).with('Successfully updated!')
subject.run
end
end
context 'when update fails' do
it 'displays an error message', hide_output: false do
stub_no_color_env('true')
expect(GDK).to receive(:make).with('self-update')
task = instance_double(Rake::Task)
expect(Rake::Task).to receive(:[]).with(:update).and_return(task)
expect(task).to receive(:invoke).and_raise('test error')
expect_any_instance_of(GDK::Announcements).not_to receive(:render_all)
expect { subject.run }
.to output(/ERROR: test error\nERROR: Failed to update/).to_stderr
.and output(/You can try the following that may be of assistance/).to_stdout
end
end
context 'when migrate fails' do
it 'displays an error message', hide_output: false do
stub_no_color_env('true')
expect(GDK).to receive(:make).with('self-update')
migrate_task = instance_double(Rake::Task)
expect(Rake::Task).to receive(:[]).with('gdk:migrate').and_return(migrate_task)
expect(migrate_task).to receive(:invoke).and_raise('migration error')
expect_any_instance_of(GDK::Announcements).not_to receive(:render_all)
expect { subject.run }
.to output(/ERROR: migration error\nERROR: Failed to update/).to_stderr
.and output(/You can try the following that may be of assistance/).to_stdout
end
end
context 'when reconfigure fails' do
it 'returns false' do
expect(subject).to receive(:run_rake).with('gdk:migrate').and_return(true)
expect(subject).to receive(:run_rake).with(:update).and_return(true)
expect(subject).to receive(:run_rake).with(:reconfigure).and_return(false)
expect_any_instance_of(GDK::Announcements).not_to receive(:render_all)
expect(subject.run).to be(false)
end
end
it 'delegates to #update! and executes with success' do
expect(subject).to receive(:update!).and_return('some content')
expect(subject).to receive(:run_rake).with(:reconfigure).and_return(true)
expect(GDK::Output).to receive(:success).with('Successfully updated!')
expect(subject.run).to be(true)
end
it 'prints a duration summary' do
task = instance_double(Rake::Task, invoke: nil)
allow(Rake::Task).to receive(:[]).with(:update).and_return(task)
expect(GDK::Output).to receive(:success).with('Successfully updated!')
subject.run
end
context 'when gdk.auto_reconfigure flag is disabled' do
before do
yaml = {
'gdk' => {
'auto_reconfigure' => false
}
}
stub_gdk_yaml(yaml)
end
it 'does not execute reconfigure command after update' do
expect(subject).to receive(:update!).and_return('some content')
expect(subject).not_to receive(:run_rake).with(:reconfigure)
expect(GDK::Output).to receive(:success).with('Successfully updated!')
subject.run
end
end
context 'when `gdk` command no longer available after update' do
let(:gdk_available_after_update?) { false }
it 'prints an error' do
expect(subject).to receive(:update!).and_return(true)
expect(subject).to receive(:run_rake).with(:reconfigure).and_return(true)
expect(GDK::Telemetry).to receive(:capture_exception).with(described_class::GdkNotFoundError.new('`gdk` command is no longer available'))
expect(GDK::Output).to receive(:error).with('The `gdk` is no longer available after `gdk update`. This is unexpected, please report this in https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/2388.')
subject.run
end
end
end
end