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