diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-18 09:10:36 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-18 09:10:36 +0300 |
commit | e9ae9c5f2ee47b084038ff62319504fc6d0abf20 (patch) | |
tree | 6a515ac128d8a351ca028c45e2f29ab1065738a3 | |
parent | edd6fda56d54d7223eb67a15341603e44c3a5f7a (diff) |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/models/concerns/sha_attribute.rb | 5 | ||||
-rw-r--r-- | doc/development/experiment_guide/index.md | 6 | ||||
-rw-r--r-- | doc/topics/cron/index.md | 6 | ||||
-rw-r--r-- | lib/gitlab/process_management.rb | 84 | ||||
-rw-r--r-- | locale/gitlab.pot | 2 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | qa/README.md | 10 | ||||
-rw-r--r-- | sidekiq_cluster/cli.rb | 19 | ||||
-rw-r--r-- | sidekiq_cluster/sidekiq_cluster.rb | 82 | ||||
-rw-r--r-- | spec/commands/sidekiq_cluster/cli_spec.rb | 24 | ||||
-rw-r--r-- | spec/frontend/__helpers__/mock_apollo_helper.js | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/process_management_spec.rb | 127 | ||||
-rw-r--r-- | spec/models/concerns/sha_attribute_spec.rb | 2 | ||||
-rw-r--r-- | spec/sidekiq_cluster/sidekiq_cluster_spec.rb | 106 | ||||
-rw-r--r-- | spec/simplecov_env.rb | 2 | ||||
-rw-r--r-- | yarn.lock | 11 |
16 files changed, 272 insertions, 219 deletions
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb index ba7c6c0cd8b..e49f4d03bda 100644 --- a/app/models/concerns/sha_attribute.rb +++ b/app/models/concerns/sha_attribute.rb @@ -3,11 +3,14 @@ module ShaAttribute extend ActiveSupport::Concern + # Needed for the database method + include DatabaseReflection + class_methods do def sha_attribute(name) return if ENV['STATIC_VERIFICATION'] - validate_binary_column_exists!(name) if Rails.env.development? + validate_binary_column_exists!(name) if Rails.env.development? || Rails.env.test? attribute(name, Gitlab::Database::ShaAttribute.new) end diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md index 1b1f756d4c0..fc88615f874 100644 --- a/doc/development/experiment_guide/index.md +++ b/doc/development/experiment_guide/index.md @@ -38,9 +38,9 @@ being removed before the [experiment cleanup process](https://about.gitlab.com/h If, as a reviewer or maintainer, you find code that would usually fail review but is acceptable for now, mention your concerns with a note that there's no need to change the code. The author can then add a comment to this piece of code -and link to the issue that resolves the experiment. If the experiment is -successful and becomes part of the product, any follow up issues should be -addressed. +and link to the issue that resolves the experiment. The author or reviewer can add a link to this concern in the +experiment rollout issue under the `Experiment Successful Cleanup Concerns` section of the description. +If the experiment is successful and becomes part of the product, any items that appear under this section will be addressed. ## Implementing an experiment diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md index f7a22bef07c..3947a72cac6 100644 --- a/doc/topics/cron/index.md +++ b/doc/topics/cron/index.md @@ -65,5 +65,7 @@ More examples of how to write a cron schedule can be found at ## How GitLab parses cron syntax strings GitLab uses [`fugit`](https://github.com/floraison/fugit) to parse cron syntax -strings on the server and [cron-validate](https://github.com/Airfooox/cron-validate) -to validate cron syntax in the browser. +strings on the server and [cron-validator](https://github.com/TheCloudConnectors/cron-validator) +to validate cron syntax in the browser. GitLab uses +[`cRonstrue`](https://github.com/bradymholt/cRonstrue) to convert cron to human-readable strings +in the browser. diff --git a/lib/gitlab/process_management.rb b/lib/gitlab/process_management.rb new file mode 100644 index 00000000000..2c2aaadb29a --- /dev/null +++ b/lib/gitlab/process_management.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module Gitlab + module ProcessManagement + # The signals that should terminate both the master and workers. + TERMINATE_SIGNALS = %i(INT TERM).freeze + + # The signals that should simply be forwarded to the workers. + FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze + + # Traps the given signals and yields the block whenever these signals are + # received. + # + # The block is passed the name of the signal. + # + # Example: + # + # trap_signals(%i(HUP TERM)) do |signal| + # ... + # end + def self.trap_signals(signals) + signals.each do |signal| + trap(signal) do + yield signal + end + end + end + + def self.trap_terminate(&block) + trap_signals(TERMINATE_SIGNALS, &block) + end + + def self.trap_forward(&block) + trap_signals(FORWARD_SIGNALS, &block) + end + + def self.signal(pid, signal) + Process.kill(signal, pid) + true + rescue Errno::ESRCH + false + end + + def self.signal_processes(pids, signal) + pids.each { |pid| signal(pid, signal) } + end + + # Waits for the given process to complete using a separate thread. + def self.wait_async(pid) + Thread.new do + Process.wait(pid) rescue Errno::ECHILD + end + end + + # Returns true if all the processes are alive. + def self.all_alive?(pids) + pids.each do |pid| + return false unless process_alive?(pid) + end + + true + end + + def self.any_alive?(pids) + pids_alive(pids).any? + end + + def self.pids_alive(pids) + pids.select { |pid| process_alive?(pid) } + end + + def self.process_alive?(pid) + # Signal 0 tests whether the process exists and we have access to send signals + # but is otherwise a noop (doesn't actually send a signal to the process) + signal(pid, 0) + end + + def self.write_pid(path) + File.open(path, 'w') do |handle| + handle.write(Process.pid.to_s) + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f87833e829d..024b4ea27a7 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -30807,7 +30807,7 @@ msgstr "" msgid "SecurityOrchestration|Scan execution policies can only be created by project owners." msgstr "" -msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}" +msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}" msgstr "" msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}" diff --git a/package.json b/package.json index 943a176ce75..4d37aae3f3a 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "copy-webpack-plugin": "^6.4.1", "core-js": "^3.18.2", "cron-validator": "^1.1.1", + "cronstrue": "^1.122.0", "cropper": "^2.3.0", "css-loader": "^2.1.1", "d3": "^5.16.0", diff --git a/qa/README.md b/qa/README.md index c380a5b6770..2e3f6af5bc3 100644 --- a/qa/README.md +++ b/qa/README.md @@ -73,6 +73,16 @@ bundle exec bin/qa Test::Instance::All http://localhost:3000 Note: If you want to run tests requiring SSH against GDK, you will need to [modify your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md). +Note: When you log into your GDK instance of GitLab for the first time, the root password requires a change. +GitLab QA expects the default initial password to be used in tests; see all default values listed in +[Supported GitLab environment variables](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables). +If you have changed your root password, you must set the `GITLAB_INITIAL_ROOT_PASSWORD` environment +variable. + +``` +export GITLAB_INITIAL_ROOT_PASSWORD="<GDK root password>" +``` + #### Running EE tests When running EE tests you'll need to have a license available. GitLab engineers can [request a license](https://about.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee). diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb index 55b4521d37d..2dbb1e9c7c7 100644 --- a/sidekiq_cluster/cli.rb +++ b/sidekiq_cluster/cli.rb @@ -11,6 +11,7 @@ require_relative '../lib/gitlab/utils' require_relative '../lib/gitlab/sidekiq_config/cli_methods' require_relative '../lib/gitlab/sidekiq_config/worker_matcher' require_relative '../lib/gitlab/sidekiq_logging/json_formatter' +require_relative '../lib/gitlab/process_management' require_relative 'sidekiq_cluster' module Gitlab @@ -106,7 +107,7 @@ module Gitlab end def write_pid - SidekiqCluster.write_pid(@pid) if @pid + ProcessManagement.write_pid(@pid) if @pid end def soft_timeout_seconds @@ -123,11 +124,11 @@ module Gitlab end def continue_waiting?(deadline) - SidekiqCluster.any_alive?(@processes) && monotonic_time < deadline + ProcessManagement.any_alive?(@processes) && monotonic_time < deadline end def hard_stop_stuck_pids - SidekiqCluster.signal_processes(SidekiqCluster.pids_alive(@processes), "-KILL") + ProcessManagement.signal_processes(ProcessManagement.pids_alive(@processes), "-KILL") end def wait_for_termination @@ -138,14 +139,14 @@ module Gitlab end def trap_signals - SidekiqCluster.trap_terminate do |signal| + ProcessManagement.trap_terminate do |signal| @alive = false - SidekiqCluster.signal_processes(@processes, signal) + ProcessManagement.signal_processes(@processes, signal) wait_for_termination end - SidekiqCluster.trap_forward do |signal| - SidekiqCluster.signal_processes(@processes, signal) + ProcessManagement.trap_forward do |signal| + ProcessManagement.signal_processes(@processes, signal) end end @@ -153,12 +154,12 @@ module Gitlab while @alive sleep(@interval) - unless SidekiqCluster.all_alive?(@processes) + unless ProcessManagement.all_alive?(@processes) # If a child process died we'll just terminate the whole cluster. It's up to # runit and such to then restart the cluster. @logger.info('A worker terminated, shutting down the cluster') - SidekiqCluster.signal_processes(@processes, :TERM) + ProcessManagement.signal_processes(@processes, :TERM) break end end diff --git a/sidekiq_cluster/sidekiq_cluster.rb b/sidekiq_cluster/sidekiq_cluster.rb index 49478ba740d..c3aa9e05a09 100644 --- a/sidekiq_cluster/sidekiq_cluster.rb +++ b/sidekiq_cluster/sidekiq_cluster.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative 'dependencies' +require_relative '../lib/gitlab/process_management' module Gitlab module SidekiqCluster @@ -17,49 +18,6 @@ module Gitlab # After surpassing the soft timeout. DEFAULT_HARD_TIMEOUT_SECONDS = 5 - # The signals that should terminate both the master and workers. - TERMINATE_SIGNALS = %i(INT TERM).freeze - - # The signals that should simply be forwarded to the workers. - FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze - - # Traps the given signals and yields the block whenever these signals are - # received. - # - # The block is passed the name of the signal. - # - # Example: - # - # trap_signals(%i(HUP TERM)) do |signal| - # ... - # end - def self.trap_signals(signals) - signals.each do |signal| - trap(signal) do - yield signal - end - end - end - - def self.trap_terminate(&block) - trap_signals(TERMINATE_SIGNALS, &block) - end - - def self.trap_forward(&block) - trap_signals(FORWARD_SIGNALS, &block) - end - - def self.signal(pid, signal) - Process.kill(signal, pid) - true - rescue Errno::ESRCH - false - end - - def self.signal_processes(pids, signal) - pids.each { |pid| signal(pid, signal) } - end - # Starts Sidekiq workers for the pairs of processes. # # Example: @@ -118,7 +76,7 @@ module Gitlab out: $stdout ) - wait_async(pid) + ProcessManagement.wait_async(pid) pid end @@ -144,41 +102,5 @@ module Gitlab concurrency_from_queues.clamp(min, max) end - - # Waits for the given process to complete using a separate thread. - def self.wait_async(pid) - Thread.new do - Process.wait(pid) rescue Errno::ECHILD - end - end - - # Returns true if all the processes are alive. - def self.all_alive?(pids) - pids.each do |pid| - return false unless process_alive?(pid) - end - - true - end - - def self.any_alive?(pids) - pids_alive(pids).any? - end - - def self.pids_alive(pids) - pids.select { |pid| process_alive?(pid) } - end - - def self.process_alive?(pid) - # Signal 0 tests whether the process exists and we have access to send signals - # but is otherwise a noop (doesn't actually send a signal to the process) - signal(pid, 0) - end - - def self.write_pid(path) - File.open(path, 'w') do |handle| - handle.write(Process.pid.to_s) - end - end end end diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb index baa4a2b4ec3..f5642c00ca4 100644 --- a/spec/commands/sidekiq_cluster/cli_spec.rb +++ b/spec/commands/sidekiq_cluster/cli_spec.rb @@ -246,7 +246,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath describe '#write_pid' do context 'when a PID is specified' do it 'writes the PID to a file' do - expect(Gitlab::SidekiqCluster).to receive(:write_pid).with('/dev/null') + expect(Gitlab::ProcessManagement).to receive(:write_pid).with('/dev/null') cli.option_parser.parse!(%w(-P /dev/null)) cli.write_pid @@ -255,7 +255,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath context 'when no PID is specified' do it 'does not write a PID' do - expect(Gitlab::SidekiqCluster).not_to receive(:write_pid) + expect(Gitlab::ProcessManagement).not_to receive(:write_pid) cli.write_pid end @@ -264,13 +264,13 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath describe '#wait_for_termination' do it 'waits for termination of all sub-processes and succeeds after 3 checks' do - expect(Gitlab::SidekiqCluster).to receive(:any_alive?) + expect(Gitlab::ProcessManagement).to receive(:any_alive?) .with(an_instance_of(Array)).and_return(true, true, true, false) - expect(Gitlab::SidekiqCluster).to receive(:pids_alive) + expect(Gitlab::ProcessManagement).to receive(:pids_alive) .with([]).and_return([]) - expect(Gitlab::SidekiqCluster).to receive(:signal_processes) + expect(Gitlab::ProcessManagement).to receive(:signal_processes) .with([], "-KILL") stub_const("Gitlab::SidekiqCluster::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1) @@ -292,13 +292,13 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath .with([['foo']], default_options) .and_return(worker_pids) - expect(Gitlab::SidekiqCluster).to receive(:any_alive?) + expect(Gitlab::ProcessManagement).to receive(:any_alive?) .with(worker_pids).and_return(true).at_least(10).times - expect(Gitlab::SidekiqCluster).to receive(:pids_alive) + expect(Gitlab::ProcessManagement).to receive(:pids_alive) .with(worker_pids).and_return([102]) - expect(Gitlab::SidekiqCluster).to receive(:signal_processes) + expect(Gitlab::ProcessManagement).to receive(:signal_processes) .with([102], "-KILL") cli.run(%w(foo)) @@ -313,8 +313,8 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath describe '#trap_signals' do it 'traps the termination and forwarding signals' do - expect(Gitlab::SidekiqCluster).to receive(:trap_terminate) - expect(Gitlab::SidekiqCluster).to receive(:trap_forward) + expect(Gitlab::ProcessManagement).to receive(:trap_terminate) + expect(Gitlab::ProcessManagement).to receive(:trap_forward) cli.trap_signals end @@ -324,10 +324,10 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath it 'runs until one of the processes has been terminated' do allow(cli).to receive(:sleep).with(a_kind_of(Numeric)) - expect(Gitlab::SidekiqCluster).to receive(:all_alive?) + expect(Gitlab::ProcessManagement).to receive(:all_alive?) .with(an_instance_of(Array)).and_return(false) - expect(Gitlab::SidekiqCluster).to receive(:signal_processes) + expect(Gitlab::ProcessManagement).to receive(:signal_processes) .with(an_instance_of(Array), :TERM) cli.start_loop diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js index 520d6c72541..ee4bbd42b1e 100644 --- a/spec/frontend/__helpers__/mock_apollo_helper.js +++ b/spec/frontend/__helpers__/mock_apollo_helper.js @@ -26,7 +26,5 @@ export function createMockClient(handlers = [], resolvers = {}, cacheOptions = { export default function createMockApollo(handlers, resolvers, cacheOptions) { const mockClient = createMockClient(handlers, resolvers, cacheOptions); - const apolloProvider = new VueApollo({ defaultClient: mockClient }); - - return apolloProvider; + return new VueApollo({ defaultClient: mockClient }); } diff --git a/spec/lib/gitlab/process_management_spec.rb b/spec/lib/gitlab/process_management_spec.rb new file mode 100644 index 00000000000..71c4acdecb9 --- /dev/null +++ b/spec/lib/gitlab/process_management_spec.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require_relative '../../../lib/gitlab/process_management' + +RSpec.describe Gitlab::ProcessManagement do + describe '.trap_signals' do + it 'traps the given signals' do + expect(described_class).to receive(:trap).ordered.with(:INT) + expect(described_class).to receive(:trap).ordered.with(:HUP) + + described_class.trap_signals(%i(INT HUP)) + end + end + + describe '.trap_terminate' do + it 'traps the termination signals' do + expect(described_class).to receive(:trap_signals) + .with(described_class::TERMINATE_SIGNALS) + + described_class.trap_terminate { } + end + end + + describe '.trap_forward' do + it 'traps the signals to forward' do + expect(described_class).to receive(:trap_signals) + .with(described_class::FORWARD_SIGNALS) + + described_class.trap_forward { } + end + end + + describe '.signal_processes' do + it 'sends a signal to every given process' do + expect(described_class).to receive(:signal).with(1, :INT) + + described_class.signal_processes([1], :INT) + end + end + + describe '.signal' do + it 'sends a signal to the given process' do + allow(Process).to receive(:kill).with(:INT, 4) + expect(described_class.signal(4, :INT)).to eq(true) + end + + it 'returns false when the process does not exist' do + allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH) + expect(described_class.signal(4, :INT)).to eq(false) + end + end + + describe '.wait_async' do + it 'waits for a process in a separate thread' do + thread = described_class.wait_async(Process.spawn('true')) + + # Upon success Process.wait just returns the PID. + expect(thread.value).to be_a_kind_of(Numeric) + end + end + + # In the X_alive? checks, we check negative PIDs sometimes as a simple way + # to be sure the pids are definitely for non-existent processes. + # Note that -1 is special, and sends the signal to every process we have permission + # for, so we use -2, -3 etc + describe '.all_alive?' do + it 'returns true if all processes are alive' do + processes = [Process.pid] + + expect(described_class.all_alive?(processes)).to eq(true) + end + + it 'returns false when a thread was not alive' do + processes = [-2] + + expect(described_class.all_alive?(processes)).to eq(false) + end + end + + describe '.process_alive?' do + it 'returns true if the proces is alive' do + process = Process.pid + + expect(described_class.process_alive?(process)).to eq(true) + end + + it 'returns false when a thread was not alive' do + process = -2 + + expect(described_class.process_alive?(process)).to eq(false) + end + end + + describe '.pids_alive' do + it 'returns the pids that are alive, from a given array' do + pids = [Process.pid, -2] + + expect(described_class.pids_alive(pids)).to match_array([Process.pid]) + end + end + + describe '.any_alive?' do + it 'returns true if at least one process is alive' do + processes = [Process.pid, -2] + + expect(described_class.any_alive?(processes)).to eq(true) + end + + it 'returns false when all threads are dead' do + processes = [-2, -3] + + expect(described_class.any_alive?(processes)).to eq(false) + end + end + + describe '.write_pid' do + it 'writes the PID of the current process to the given file' do + handle = double(:handle) + + allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle) + + expect(handle).to receive(:write).with(Process.pid.to_s) + + described_class.write_pid('/dev/null') + end + end +end diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb index 220eadfab92..1bcf3dc8b61 100644 --- a/spec/models/concerns/sha_attribute_spec.rb +++ b/spec/models/concerns/sha_attribute_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe ShaAttribute do - let(:model) { Class.new(ApplicationRecord) { include ShaAttribute } } + let(:model) { Class.new(ActiveRecord::Base) { include ShaAttribute } } before do columns = [ diff --git a/spec/sidekiq_cluster/sidekiq_cluster_spec.rb b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb index 1d2b47e78ce..3df2aa70553 100644 --- a/spec/sidekiq_cluster/sidekiq_cluster_spec.rb +++ b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb @@ -5,53 +5,6 @@ require 'rspec-parameterized' require_relative '../../sidekiq_cluster/sidekiq_cluster' RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath - describe '.trap_signals' do - it 'traps the given signals' do - expect(described_class).to receive(:trap).ordered.with(:INT) - expect(described_class).to receive(:trap).ordered.with(:HUP) - - described_class.trap_signals(%i(INT HUP)) - end - end - - describe '.trap_terminate' do - it 'traps the termination signals' do - expect(described_class).to receive(:trap_signals) - .with(described_class::TERMINATE_SIGNALS) - - described_class.trap_terminate { } - end - end - - describe '.trap_forward' do - it 'traps the signals to forward' do - expect(described_class).to receive(:trap_signals) - .with(described_class::FORWARD_SIGNALS) - - described_class.trap_forward { } - end - end - - describe '.signal' do - it 'sends a signal to the given process' do - allow(Process).to receive(:kill).with(:INT, 4) - expect(described_class.signal(4, :INT)).to eq(true) - end - - it 'returns false when the process does not exist' do - allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH) - expect(described_class.signal(4, :INT)).to eq(false) - end - end - - describe '.signal_processes' do - it 'sends a signal to every given process' do - expect(described_class).to receive(:signal).with(1, :INT) - - described_class.signal_processes([1], :INT) - end - end - describe '.start' do it 'starts Sidekiq with the given queues, environment and options' do expected_options = { @@ -99,7 +52,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath it 'starts a Sidekiq process' do allow(Process).to receive(:spawn).and_return(1) - expect(described_class).to receive(:wait_async).with(1) + expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1) expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1) end @@ -109,7 +62,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath .with(env, *args, anything) .and_return(1) - expect(described_class).to receive(:wait_async).with(1) + expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1) expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1) end @@ -119,7 +72,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath .with(anything, *args, a_hash_including(pgroup: true)) .and_return(1) - allow(described_class).to receive(:wait_async) + allow(Gitlab::ProcessManagement).to receive(:wait_async) expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1) end end @@ -152,57 +105,4 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath it { expect(described_class.concurrency(queues, min, max)).to eq(expected) } end end - - describe '.wait_async' do - it 'waits for a process in a separate thread' do - thread = described_class.wait_async(Process.spawn('true')) - - # Upon success Process.wait just returns the PID. - expect(thread.value).to be_a_kind_of(Numeric) - end - end - - # In the X_alive? checks, we check negative PIDs sometimes as a simple way - # to be sure the pids are definitely for non-existent processes. - # Note that -1 is special, and sends the signal to every process we have permission - # for, so we use -2, -3 etc - describe '.all_alive?' do - it 'returns true if all processes are alive' do - processes = [Process.pid] - - expect(described_class.all_alive?(processes)).to eq(true) - end - - it 'returns false when a thread was not alive' do - processes = [-2] - - expect(described_class.all_alive?(processes)).to eq(false) - end - end - - describe '.any_alive?' do - it 'returns true if at least one process is alive' do - processes = [Process.pid, -2] - - expect(described_class.any_alive?(processes)).to eq(true) - end - - it 'returns false when all threads are dead' do - processes = [-2, -3] - - expect(described_class.any_alive?(processes)).to eq(false) - end - end - - describe '.write_pid' do - it 'writes the PID of the current process to the given file' do - handle = double(:handle) - - allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle) - - expect(handle).to receive(:write).with(Process.pid.to_s) - - described_class.write_pid('/dev/null') - end - end end diff --git a/spec/simplecov_env.rb b/spec/simplecov_env.rb index 617a45ae449..e6ce4d256f0 100644 --- a/spec/simplecov_env.rb +++ b/spec/simplecov_env.rb @@ -49,7 +49,7 @@ module SimpleCovEnv track_files '{app,config/initializers,config/initializers_before_autoloader,db/post_migrate,haml_lint,lib,rubocop,tooling}/**/*.rb' add_filter '/vendor/ruby/' - add_filter '/app/controllers/sherlock/' + add_filter '/app/controllers/sherlock/' # Profiling tool used only in development add_filter '/bin/' add_filter 'db/fixtures/' # Matches EE files as well add_filter '/lib/gitlab/sidekiq_middleware/' diff --git a/yarn.lock b/yarn.lock index b7f16a7282f..78cdedccd40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3863,9 +3863,14 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cron-validator@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.1.1.tgz#0a27bb75508c7bc03c8b840d2d9f170eeacb5615" - integrity sha512-vfZb05w/wezuwPZBDvdIBmJp2BvuJExHeyKRa5oBqD2ZDXR61hb3QgPc/3ZhBEQJlAy8Jlnn5XC/JCT3IDqxwg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.2.1.tgz#0f0de2de36d231a6ace0e43ffc6c0564fe6edf1a" + integrity sha512-RqdpGSokGFICPc8qAkT38aXqZLLanXghQTK2q7a2x2FabSwDd2ARrazd5ElEWAXzToUcMG4cZIwDH+5RM0q1mA== + +cronstrue@^1.122.0: + version "1.122.0" + resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-1.122.0.tgz#bd6838077b476d28f61d381398b47b8c3912a126" + integrity sha512-PFuhZd+iPQQ0AWTXIEYX+t3nFGzBrWxmTWUKJOrsGRewaBSLKZ4I1f8s2kryU75nNxgyugZgiGh2OJsCTA/XlA== cropper@^2.3.0: version "2.3.0" |