diff --git a/.rubocop_todo/graphql/ordered_arguments.yml b/.rubocop_todo/graphql/ordered_arguments.yml index a2df1315ee9..3a4e805948d 100644 --- a/.rubocop_todo/graphql/ordered_arguments.yml +++ b/.rubocop_todo/graphql/ordered_arguments.yml @@ -4,9 +4,6 @@ GraphQL/OrderedArguments: - app/graphql/resolvers/base_issues_resolver.rb - app/graphql/resolvers/design_management/designs_resolver.rb - app/graphql/resolvers/design_management/version/design_at_version_resolver.rb - - app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb - - app/graphql/resolvers/design_management/version_in_collection_resolver.rb - - app/graphql/resolvers/group_milestones_resolver.rb - app/graphql/resolvers/merge_requests_resolver.rb - app/graphql/resolvers/paginated_tree_resolver.rb - app/graphql/resolvers/tree_resolver.rb diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index 7f3a46a841e..5a5c7211dc6 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -1.49.0 +1.50.0 diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue index c6e461b10e0..dc5a031c9f3 100644 --- a/app/assets/javascripts/repository/components/preview/index.vue +++ b/app/assets/javascripts/repository/components/preview/index.vue @@ -47,6 +47,9 @@ export default { } }, }, + safeHtmlConfig: { + ADD_TAGS: ['copy-code'], + }, }; @@ -62,7 +65,11 @@ export default {
-
+
diff --git a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb index 254f1efa0a5..97cc7554ba8 100644 --- a/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb +++ b/app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb @@ -13,13 +13,13 @@ module Resolvers DesignID = ::Types::GlobalIDType[::DesignManagement::Design] - argument :ids, [DesignID], - required: false, - description: 'Filters designs by their ID.' argument :filenames, [GraphQL::Types::String], required: false, description: 'Filters designs by their filename.' + argument :ids, [DesignID], + required: false, + description: 'Filters designs by their ID.' def self.single ::Resolvers::DesignManagement::Version::DesignAtVersionResolver diff --git a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb index 80db15755d3..2682ce6b3b1 100644 --- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb +++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb @@ -15,13 +15,13 @@ module Resolvers VersionID = ::Types::GlobalIDType[::DesignManagement::Version] - argument :sha, GraphQL::Types::String, - required: false, - description: "SHA256 of a specific version." argument :id, VersionID, as: :version_id, required: false, description: 'Global ID of the version.' + argument :sha, GraphQL::Types::String, + required: false, + description: "SHA256 of a specific version." def resolve(version_id: nil, sha: nil) # TODO: remove this line when the compatibility layer is removed diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb index 44192b6f4bf..319ff9f68c4 100644 --- a/app/graphql/resolvers/group_milestones_resolver.rb +++ b/app/graphql/resolvers/group_milestones_resolver.rb @@ -2,12 +2,12 @@ module Resolvers class GroupMilestonesResolver < MilestonesResolver - argument :include_descendants, GraphQL::Types::Boolean, - required: false, - description: 'Include milestones from all subgroups and subprojects.' argument :include_ancestors, GraphQL::Types::Boolean, required: false, description: 'Include milestones from all parent groups.' + argument :include_descendants, GraphQL::Types::Boolean, + required: false, + description: 'Include milestones from all subgroups and subprojects.' type Types::MilestoneType.connection_type, null: true diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index c9ca18c2ce0..30ae4bc0eda 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1021,7 +1021,15 @@ module Ci transaction do update_columns(status: :failed, failure_reason: :data_integrity_failure) all_queuing_entries.delete_all + all_runtime_metadata.delete_all end + + Gitlab::AppLogger.info( + message: 'Build doomed', + class: self.class.name, + build_id: id, + pipeline_id: pipeline_id, + project_id: project_id) end def degradation_threshold @@ -1067,6 +1075,10 @@ module Ci ::Ci::PendingBuild.upsert_from_build!(self) end + def create_runtime_metadata! + ::Ci::RunningBuild.upsert_shared_runner_build!(self) + end + ## # We can have only one queuing entry or running build tracking entry, # because there is a unique index on `build_id` in each table, but we need diff --git a/app/services/ci/stuck_builds/drop_helpers.rb b/app/services/ci/stuck_builds/drop_helpers.rb index f79b805c23d..048b52c6e13 100644 --- a/app/services/ci/stuck_builds/drop_helpers.rb +++ b/app/services/ci/stuck_builds/drop_helpers.rb @@ -34,7 +34,7 @@ module Ci # rubocop: enable CodeReuse/ActiveRecord def drop_build(type, build, reason) - Gitlab::AppLogger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{build.status}, failure_reason: #{reason})" + log_dropping_message(type, build, reason) Gitlab::OptimisticLocking.retry_lock(build, 3, name: 'stuck_ci_jobs_worker_drop_build') do |b| b.drop(reason) end @@ -53,6 +53,16 @@ module Ci project_id: build.project_id ) end + + def log_dropping_message(type, build, reason) + Gitlab::AppLogger.info(class: self.class.name, + message: "Dropping #{type} build", + build_stuck_type: type, + build_id: build.id, + runner_id: build.runner_id, + build_status: build.status, + build_failure_reason: reason) + end end end end diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md index cee6cddbbf0..2b85e31ee4b 100644 --- a/doc/administration/audit_event_streaming.md +++ b/doc/administration/audit_event_streaming.md @@ -6,11 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Audit event streaming **(ULTIMATE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default. +> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7. FLAG: -On self-managed GitLab, by default this feature is not available. To make it available per group, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. On GitLab.com, this feature is not available. -You should not use this feature for production environments. +On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. On GitLab.com, this feature is available. Event streaming allows owners of top-level groups to set an HTTP endpoint to receive **all** audit events about the group, and its subgroups and projects. diff --git a/doc/user/permissions.md b/doc/user/permissions.md index a55e9fa8ed1..3cb07ecfe99 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -512,6 +512,7 @@ instance and project. | Change project configuration | | | ✓ | ✓ | | Add specific runners | | | ✓ | ✓ | | Add shared runners | | | | ✓ | +| Clear runner caches manually | | | ✓ | ✓ | | See events in the system | | | | ✓ | | Admin Area | | | | ✓ | diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb index 57649ec74c8..bbe95788a35 100644 --- a/sidekiq_cluster/cli.rb +++ b/sidekiq_cluster/cli.rb @@ -200,9 +200,7 @@ module Gitlab end def sidekiq_exporter_enabled? - ::Settings.monitoring.sidekiq_exporter.enabled - rescue Settingslogic::MissingSetting - nil + ::Settings.dig('monitoring', 'sidekiq_exporter', 'enabled') end def exporter_has_a_unique_port? @@ -216,15 +214,11 @@ module Gitlab end def sidekiq_exporter_port - ::Settings.monitoring.sidekiq_exporter.port - rescue Settingslogic::MissingSetting - nil + ::Settings.dig('monitoring', 'sidekiq_exporter', 'port') end def sidekiq_health_check_port - ::Settings.monitoring.sidekiq_health_checks.port - rescue Settingslogic::MissingSetting - nil + ::Settings.dig('monitoring', 'sidekiq_health_checks', 'port') end def metrics_server_enabled? diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb index 148b8720740..d7488e8d965 100644 --- a/spec/commands/sidekiq_cluster/cli_spec.rb +++ b/spec/commands/sidekiq_cluster/cli_spec.rb @@ -5,7 +5,7 @@ require 'rspec-parameterized' require_relative '../../../sidekiq_cluster/cli' -RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath +RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do # rubocop:disable RSpec/FilePath let(:cli) { described_class.new('/dev/null') } let(:timeout) { Gitlab::SidekiqCluster::DEFAULT_SOFT_TIMEOUT_SECONDS } let(:default_options) do @@ -16,19 +16,39 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath let(:sidekiq_exporter_port) { '3807' } let(:sidekiq_health_checks_port) { '3807' } - before do - stub_env('RAILS_ENV', 'test') - stub_config( - monitoring: { - sidekiq_exporter: { - enabled: sidekiq_exporter_enabled, - port: sidekiq_exporter_port - }, - sidekiq_health_checks: { - port: sidekiq_health_checks_port + let(:config_file) { Tempfile.new('gitlab.yml') } + let(:config) do + { + 'test' => { + 'monitoring' => { + 'sidekiq_exporter' => { + 'address' => 'localhost', + 'enabled' => sidekiq_exporter_enabled, + 'port' => sidekiq_exporter_port + }, + 'sidekiq_health_checks' => { + 'address' => 'localhost', + 'enabled' => sidekiq_exporter_enabled, + 'port' => sidekiq_health_checks_port + } } } - ) + } + end + + before do + stub_env('RAILS_ENV', 'test') + + config_file.write(YAML.dump(config)) + config_file.close + + allow(::Settings).to receive(:source).and_return(config_file.path) + + ::Settings.reload! + end + + after do + config_file.unlink end describe '#run' do @@ -272,16 +292,9 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath context 'starting the server' do context 'without --dryrun' do context 'when there are no sidekiq_health_checks settings set' do - before do - stub_config( - monitoring: { - sidekiq_exporter: { - enabled: true, - port: sidekiq_exporter_port - } - } - ) + let(:sidekiq_exporter_enabled) { true } + before do allow(Gitlab::SidekiqCluster).to receive(:start) allow(cli).to receive(:write_pid) allow(cli).to receive(:trap_signals) @@ -293,25 +306,12 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath cli.run(%w(foo)) end - - it 'rescues Settingslogic::MissingSetting' do - expect { cli.run(%w(foo)) }.not_to raise_error(Settingslogic::MissingSetting) - end end context 'when the sidekiq_exporter.port setting is not set' do - before do - stub_config( - monitoring: { - sidekiq_exporter: { - enabled: true - }, - sidekiq_health_checks: { - port: sidekiq_health_checks_port - } - } - ) + let(:sidekiq_exporter_enabled) { true } + before do allow(Gitlab::SidekiqCluster).to receive(:start) allow(cli).to receive(:write_pid) allow(cli).to receive(:trap_signals) @@ -323,23 +323,25 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath cli.run(%w(foo)) end - - it 'rescues Settingslogic::MissingSetting' do - expect { cli.run(%w(foo)) }.not_to raise_error(Settingslogic::MissingSetting) - end end context 'when sidekiq_exporter.enabled setting is not set' do - before do - stub_config( - monitoring: { - sidekiq_exporter: {}, - sidekiq_health_checks: { - port: sidekiq_health_checks_port + let(:config) do + { + 'test' => { + 'monitoring' => { + 'sidekiq_exporter' => {}, + 'sidekiq_health_checks' => { + 'address' => 'localhost', + 'enabled' => sidekiq_exporter_enabled, + 'port' => sidekiq_health_checks_port + } } } - ) + } + end + before do allow(Gitlab::SidekiqCluster).to receive(:start) allow(cli).to receive(:write_pid) allow(cli).to receive(:trap_signals) @@ -353,6 +355,36 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath end end + context 'with a blank sidekiq_exporter setting' do + let(:config) do + { + 'test' => { + 'monitoring' => { + 'sidekiq_exporter' => nil, + 'sidekiq_health_checks' => nil + } + } + } + end + + before do + allow(Gitlab::SidekiqCluster).to receive(:start) + allow(cli).to receive(:write_pid) + allow(cli).to receive(:trap_signals) + allow(cli).to receive(:start_loop) + end + + it 'does not start a sidekiq metrics server' do + expect(MetricsServer).not_to receive(:spawn) + + cli.run(%w(foo)) + end + + it 'does not throw an error' do + expect { cli.run(%w(foo)) }.not_to raise_error + end + end + context 'with valid settings' do using RSpec::Parameterized::TableSyntax diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 98023334894..d1a9ace605a 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -335,6 +335,10 @@ FactoryBot.define do running runner factory: :ci_runner + + after(:create) do |build| + build.create_runtime_metadata! + end end trait :artifacts do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 5653ef275e9..c4f4e2cb2dc 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -5427,7 +5427,8 @@ RSpec.describe Ci::Build do describe '#doom!' do subject { build.doom! } - let_it_be(:build) { create(:ci_build, :queued) } + let(:traits) { [] } + let(:build) { create(:ci_build, *traits, pipeline: pipeline) } it 'updates status and failure_reason', :aggregate_failures do subject @@ -5436,10 +5437,33 @@ RSpec.describe Ci::Build do expect(build.failure_reason).to eq("data_integrity_failure") end - it 'drops associated pending build' do - subject + it 'logs a message' do + expect(Gitlab::AppLogger) + .to receive(:info) + .with(a_hash_including(message: 'Build doomed', class: build.class.name, build_id: build.id)) + .and_call_original - expect(build.reload.queuing_entry).not_to be_present + subject + end + + context 'with queued builds' do + let(:traits) { [:queued] } + + it 'drops associated pending build' do + subject + + expect(build.reload.queuing_entry).not_to be_present + end + end + + context 'with running builds' do + let(:traits) { [:picked] } + + it 'drops associated runtime metadata' do + subject + + expect(build.reload.runtime_metadata).not_to be_present + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c497f8245fe..a2f4236b3ed 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -463,6 +463,14 @@ RSpec.configure do |config| $stdout = STDOUT end + config.around(:each, stubbing_settings_source: true) do |example| + original_instance = ::Settings.instance_variable_get(:@instance) + + example.run + + ::Settings.instance_variable_set(:@instance, original_instance) + end + config.disable_monkey_patching! end