Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-12-07 03:11:02 +00:00
parent 7e89568aa1
commit 6666461136
47 changed files with 616 additions and 379 deletions

View File

@ -1,25 +0,0 @@
---
# Cop supports --autocorrect.
Layout/FirstArrayElementIndentation:
Exclude:
- 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
- 'spec/lib/gitlab/search/found_blob_spec.rb'
- 'spec/models/ci/runner_version_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/requests/api/task_completion_status_spec.rb'
- 'spec/services/security/merge_reports_service_spec.rb'
- 'spec/simplecov_env.rb'
- 'spec/support/atlassian/jira_connect/schemata.rb'
- 'spec/support/capybara.rb'
- 'spec/support/helpers/project_template_test_helper.rb'
- 'spec/support/helpers/test_env.rb'
- 'spec/support/helpers/usage_data_helpers.rb'
- 'spec/support/matchers/exceed_query_limit.rb'
- 'spec/support/migrations_helpers/vulnerabilities_findings_helper.rb'
- 'spec/support/prometheus/additional_metrics_shared_examples.rb'
- 'spec/support/shared_contexts/policies/group_policy_shared_context.rb'
- 'spec/support/shared_examples/graphql/label_fields.rb'
- 'spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb'
- 'spec/views/projects/issues/_related_branches.html.haml_spec.rb'
- 'tooling/lib/tooling/helm3_client.rb'

View File

@ -1 +1 @@
22722e29aa21a554ed1e729f9b23a485929ac4cf
434051eb74b0043267538213192a790095caf671

View File

@ -118,6 +118,7 @@ export default {
return {
'gl-text-gray-500!': this.canUpdate && this.isNoMilestone,
'is-not-focused': !this.isFocused,
'gl-min-w-20': true,
};
},
},
@ -214,9 +215,10 @@ export default {
<template>
<gl-form-group
class="work-item-dropdown"
class="work-item-dropdown gl-flex-nowrap"
:label="$options.i18n.MILESTONE"
label-class="gl-pb-0! gl-overflow-wrap-break gl-mt-3"
label-for="milestone-value"
label-class="gl-pb-0! gl-mt-3 gl-overflow-wrap-break"
label-cols="3"
label-cols-lg="2"
>
@ -229,6 +231,8 @@ export default {
</span>
<gl-dropdown
v-else
id="milestone-value"
class="col-9 gl-pl-0"
:toggle-class="dropdownClasses"
:text="dropdownText"
:loading="updateInProgress"

View File

@ -53,6 +53,7 @@ module Import
def authorize_url
state = SecureRandom.base64(64)
session[auth_state_key] = state
session[:auth_on_failure_path] = "#{new_project_path}#import_project"
if Feature.enabled?(:remove_legacy_github_client)
oauth_client.auth_code.authorize_url(
redirect_uri: callback_import_url,

View File

@ -7,5 +7,9 @@ module Postgresql
def fully_qualified_table_name
"#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.#{table_name}"
end
def table_schema
Gitlab::Database::GitlabSchema.table_schema(table_name)
end
end
end

View File

@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78991
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350972
milestone: '14.8'
type: development
group: group::authentication and authorization
group: group::workspace
default_enabled: false

View File

@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/11209
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321404
milestone: '11.11'
type: development
group: group::authentication and authorization
group: group::workspace
default_enabled: false

View File

@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78542
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350637
milestone: '14.8'
type: development
group: group::authentication and authorization
group: group::workspace
default_enabled: true

View File

@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321407
milestone: '11.11'
type: development
group: group::authentication and authorization
group: group::workspace
default_enabled: false

View File

@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79855
rollout_issue_url:
milestone: '14.8'
type: ops
group: 'group::authentication and authorization'
group: 'group::workspace'
default_enabled: true

View File

@ -55,6 +55,22 @@ devise_scope :user do
get '/users/almost_there' => 'confirmations#almost_there'
post '/users/resend_verification_code', to: 'sessions#resend_verification_code'
get '/users/successful_verification', to: 'sessions#successful_verification'
# Redirect on GitHub authorization request errors. E.g. it could happen when user:
# 1. cancel authorization the GitLab OAuth app via GitHub to import GitHub repos
# (they'll be redirected to /projects/new#import_project)
# 2. cancel signing in to GitLab using GitHub account
# (they'll be redirected to /users/sign_in)
# In these cases, GitHub redirects user to the GitLab OAuth app's
# registered callback URL - /users/auth, which is the url to the auth user's profile page
get '/users/auth',
constraints: ->(req) {
req.params[:error].present? && req.params[:state].present?
},
to: redirect { |_params, req|
redirect_path = req.session.delete(:auth_on_failure_path)
redirect_path || Rails.application.routes.url_helpers.new_user_session_path
}
end
scope '-/users', module: :users do

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class AddIndexAuthorIdCreatedAtOnMergeRequests < Gitlab::Database::Migration[2.0]
INDEX_NAME = 'index_merge_requests_on_author_id_and_created_at'
disable_ddl_transaction!
def up
add_concurrent_index :merge_requests, %i[author_id created_at], name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :merge_requests, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
52294ac9fd807fdff49d918d6b49c071b53e683a479af6beef9449302080e44f

View File

@ -29844,6 +29844,8 @@ CREATE INDEX index_merge_requests_on_assignee_id ON merge_requests USING btree (
CREATE INDEX index_merge_requests_on_author_id ON merge_requests USING btree (author_id);
CREATE INDEX index_merge_requests_on_author_id_and_created_at ON merge_requests USING btree (author_id, created_at);
CREATE INDEX index_merge_requests_on_author_id_and_id ON merge_requests USING btree (author_id, id);
CREATE INDEX index_merge_requests_on_author_id_and_target_project_id ON merge_requests USING btree (author_id, target_project_id);

View File

@ -10,18 +10,34 @@ module Gitlab
# See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
EXPECTED_TRIGGER_RECORD_COUNT = 3
def self.tables_to_lock(connection)
Gitlab::Database::GitlabSchema.tables_to_schema.each do |table_name, schema_name|
yield table_name, schema_name
end
Gitlab::Database::SharedModel.using_connection(connection) do
Postgresql::DetachedPartition.find_each do |detached_partition|
yield detached_partition.fully_qualified_table_name, detached_partition.table_schema
end
end
end
def initialize(table_name:, connection:, database_name:, logger: nil, dry_run: false)
@table_name = table_name
@connection = connection
@database_name = database_name
@logger = logger
@dry_run = dry_run
@table_name_without_schema = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
.extract_schema_qualified_name(table_name)
.identifier
end
def table_locked_for_writes?(table_name)
query = <<~SQL
SELECT COUNT(*) from information_schema.triggers
WHERE event_object_table = '#{table_name}'
WHERE event_object_table = '#{table_name_without_schema}'
AND trigger_name = '#{write_trigger_name(table_name)}'
SQL
@ -56,7 +72,7 @@ module Gitlab
private
attr_reader :table_name, :connection, :database_name, :logger, :dry_run
attr_reader :table_name, :connection, :database_name, :logger, :dry_run, :table_name_without_schema
def execute_sql_statement(sql)
if dry_run
@ -99,7 +115,7 @@ module Gitlab
end
def write_trigger_name(table_name)
"gitlab_schema_write_trigger_for_#{table_name}"
"gitlab_schema_write_trigger_for_#{table_name_without_schema}"
end
end
end

View File

@ -27,14 +27,31 @@ module Gitlab
# it maps the tables to the tables that depend on it
def tables_dependencies
@tables.to_h do |table_name|
[table_name, all_foreign_keys[table_name]&.map(&:from_table).to_a]
[table_name, all_foreign_keys[table_name]]
end
end
def all_foreign_keys
@all_foreign_keys ||= @tables.flat_map do |table_name|
@connection.foreign_keys(table_name)
end.group_by(&:to_table)
@all_foreign_keys ||= @tables.each_with_object(Hash.new { |h, k| h[k] = [] }) do |table, hash|
foreign_keys_for(table).each do |fk|
hash[fk.to_table] << table
end
end
end
def foreign_keys_for(table)
# Detached partitions like gitlab_partitions_dynamic._test_gitlab_partition_20220101
# store their foreign keys in the public schema.
#
# See spec/lib/gitlab/database/tables_sorted_by_foreign_keys_spec.rb
# for an example
name = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(table)
if name.schema == ::Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA.to_s
@connection.foreign_keys(name.identifier)
else
@connection.foreign_keys(table)
end
end
end
end

View File

@ -24,6 +24,14 @@ module Gitlab
GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(schema_name)
end.keys
Gitlab::Database::SharedModel.using_connection(connection) do
Postgresql::DetachedPartition.find_each do |detached_partition|
next if GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(detached_partition.table_schema)
tables_to_truncate << detached_partition.fully_qualified_table_name
end
end
tables_sorted = Gitlab::Database::TablesSortedByForeignKeys.new(connection, tables_to_truncate).execute
# Checking if all the tables have the write-lock triggers
# to make sure we are deleting the right tables on the right database.
@ -66,7 +74,11 @@ module Gitlab
truncated_tables = []
tables_sorted.flatten.each do |table|
sql_statement = "SELECT set_config('lock_writes.#{table}', 'false', false)"
table_name_without_schema = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
.extract_schema_qualified_name(table)
.identifier
sql_statement = "SELECT set_config('lock_writes.#{table_name_without_schema}', 'false', false)"
logger&.info(sql_statement)
connection.execute(sql_statement) unless dry_run
end

View File

@ -6,7 +6,8 @@ namespace :gitlab do
task lock_writes: [:environment, 'gitlab:db:validate_config'] do
Gitlab::Database::EachDatabase.each_database_connection(include_shared: false) do |connection, database_name|
schemas_for_connection = Gitlab::Database.gitlab_schemas_for_connection(connection)
Gitlab::Database::GitlabSchema.tables_to_schema.each do |table_name, schema_name|
Gitlab::Database::LockWritesManager.tables_to_lock(connection) do |table_name, schema_name|
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/366834
next if schema_name == :gitlab_geo
@ -30,7 +31,7 @@ namespace :gitlab do
desc "GitLab | DB | Remove all triggers that prevents writes from all databases"
task unlock_writes: :environment do
Gitlab::Database::EachDatabase.each_database_connection do |connection, database_name|
Gitlab::Database::GitlabSchema.tables_to_schema.each do |table_name, schema_name|
Gitlab::Database::LockWritesManager.tables_to_lock(connection) do |table_name, schema_name|
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/366834
next if schema_name == :gitlab_geo

View File

@ -69,17 +69,13 @@ class VersionCheck
case response&.code
when 200
Gitlab::Json.parse(response.body)
else
{ error: 'version check failed', status: response&.code }
response.body
end
end
def response
with_reactive_cache do |data|
raise InvalidateReactiveCache if data[:error]
data
Gitlab::Json.parse(data) if data
end
end
end

View File

@ -37,6 +37,14 @@ RSpec.describe Gitlab::Database::LockWritesManager do
it 'returns true for a table that is locked for writes' do
expect { subject.lock_writes }.to change { subject.table_locked_for_writes?(test_table) }.from(false).to(true)
end
context 'for detached partition tables in another schema' do
let(:test_table) { 'gitlab_partitions_dynamic._test_table_20220101' }
it 'returns true for a table that is locked for writes' do
expect { subject.lock_writes }.to change { subject.table_locked_for_writes?(test_table) }.from(false).to(true)
end
end
end
describe '#lock_writes' do

View File

@ -4,7 +4,10 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::TablesSortedByForeignKeys do
let(:connection) { ApplicationRecord.connection }
let(:tables) { %w[_test_gitlab_main_items _test_gitlab_main_references] }
let(:tables) do
%w[_test_gitlab_main_items _test_gitlab_main_references _test_gitlab_partition_parent
gitlab_partitions_dynamic._test_gitlab_partition_20220101]
end
subject do
described_class.new(connection, tables).execute
@ -19,13 +22,33 @@ RSpec.describe Gitlab::Database::TablesSortedByForeignKeys do
item_id BIGINT NOT NULL,
CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
);
CREATE TABLE _test_gitlab_partition_parent (
id bigserial not null,
created_at timestamptz not null,
item_id BIGINT NOT NULL,
primary key (id, created_at),
CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
) PARTITION BY RANGE(created_at);
CREATE TABLE gitlab_partitions_dynamic._test_gitlab_partition_20220101
PARTITION OF _test_gitlab_partition_parent
FOR VALUES FROM ('20220101') TO ('20220131');
ALTER TABLE _test_gitlab_partition_parent DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_partition_20220101;
SQL
connection.execute(statement)
end
describe '#execute' do
it 'returns the tables sorted by the foreign keys dependency' do
expect(subject).to eq([['_test_gitlab_main_references'], ['_test_gitlab_main_items']])
expect(subject).to eq(
[
['_test_gitlab_main_references'],
['_test_gitlab_partition_parent'],
['gitlab_partitions_dynamic._test_gitlab_partition_20220101'],
['_test_gitlab_main_items']
])
end
it 'returns both tables together if they are strongly connected' do
@ -35,7 +58,12 @@ RSpec.describe Gitlab::Database::TablesSortedByForeignKeys do
SQL
connection.execute(statement)
expect(subject).to eq([tables])
expect(subject).to eq(
[
['_test_gitlab_partition_parent'],
['gitlab_partitions_dynamic._test_gitlab_partition_20220101'],
%w[_test_gitlab_main_items _test_gitlab_main_references]
])
end
end
end

View File

@ -6,14 +6,9 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
:suppress_gitlab_schemas_validate_connection do
include MigrationsHelpers
let(:logger) { instance_double(Logger) }
let(:dry_run) { false }
let(:until_table) { nil }
let(:min_batch_size) { 1 }
let(:main_connection) { ApplicationRecord.connection }
let(:ci_connection) { Ci::ApplicationRecord.connection }
let(:test_gitlab_main_table) { '_test_gitlab_main_table' }
let(:test_gitlab_ci_table) { '_test_gitlab_ci_table' }
# Main Database
let(:main_db_main_item_model) { table("_test_gitlab_main_items", database: "main") }
@ -21,24 +16,37 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
let(:main_db_ci_item_model) { table("_test_gitlab_ci_items", database: "main") }
let(:main_db_ci_reference_model) { table("_test_gitlab_ci_references", database: "main") }
let(:main_db_shared_item_model) { table("_test_gitlab_shared_items", database: "main") }
let(:main_db_partitioned_item) { table("_test_gitlab_hook_logs", database: "main") }
let(:main_db_partitioned_item_detached) do
table("gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101", database: "main")
end
# CI Database
let(:ci_db_main_item_model) { table("_test_gitlab_main_items", database: "ci") }
let(:ci_db_main_reference_model) { table("_test_gitlab_main_references", database: "ci") }
let(:ci_db_ci_item_model) { table("_test_gitlab_ci_items", database: "ci") }
let(:ci_db_ci_reference_model) { table("_test_gitlab_ci_references", database: "ci") }
let(:ci_db_shared_item_model) { table("_test_gitlab_shared_items", database: "ci") }
subject(:truncate_legacy_tables) do
described_class.new(
database_name: database_name,
min_batch_size: min_batch_size,
logger: logger,
dry_run: dry_run,
until_table: until_table
).execute
let(:ci_db_partitioned_item) { table("_test_gitlab_hook_logs", database: "ci") }
let(:ci_db_partitioned_item_detached) do
table("gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101", database: "ci")
end
shared_examples 'truncating legacy tables on a database' do
let(:logger) { instance_double(Logger) }
let(:dry_run) { false }
let(:until_table) { nil }
subject(:truncate_legacy_tables) do
described_class.new(
database_name: connection.pool.db_config.name,
min_batch_size: min_batch_size,
logger: logger,
dry_run: dry_run,
until_table: until_table
).execute
end
before do
skip_if_multiple_databases_not_setup
@ -51,6 +59,24 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
item_id BIGINT NOT NULL,
CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
);
CREATE TABLE _test_gitlab_hook_logs (
id bigserial not null,
created_at timestamptz not null,
item_id BIGINT NOT NULL,
primary key (id, created_at),
CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
) PARTITION BY RANGE(created_at);
CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101
PARTITION OF _test_gitlab_hook_logs
FOR VALUES FROM ('20220101') TO ('20220131');
CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_20220201
PARTITION OF _test_gitlab_hook_logs
FOR VALUES FROM ('20220201') TO ('20220228');
ALTER TABLE _test_gitlab_hook_logs DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_hook_logs_20220101;
SQL
main_connection.execute(main_tables_sql)
@ -84,18 +110,37 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
main_db_ci_item_model.create!(id: i)
main_db_ci_reference_model.create!(item_id: i)
main_db_shared_item_model.create!(id: i)
main_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
main_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
# CI Database
ci_db_main_item_model.create!(id: i)
ci_db_main_reference_model.create!(item_id: i)
ci_db_ci_item_model.create!(id: i)
ci_db_ci_reference_model.create!(item_id: i)
ci_db_shared_item_model.create!(id: i)
ci_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
ci_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
end
Gitlab::Database::SharedModel.using_connection(main_connection) do
Postgresql::DetachedPartition.create!(
table_name: '_test_gitlab_hook_logs_20220101',
drop_after: Time.current
)
end
Gitlab::Database::SharedModel.using_connection(ci_connection) do
Postgresql::DetachedPartition.create!(
table_name: '_test_gitlab_hook_logs_20220101',
drop_after: Time.current
)
end
allow(Gitlab::Database::GitlabSchema).to receive(:tables_to_schema).and_return(
{
"_test_gitlab_main_items" => :gitlab_main,
"_test_gitlab_main_references" => :gitlab_main,
"_test_gitlab_hook_logs" => :gitlab_main,
"_test_gitlab_ci_items" => :gitlab_ci,
"_test_gitlab_ci_references" => :gitlab_ci,
"_test_gitlab_shared_items" => :gitlab_shared,
@ -119,7 +164,7 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
Gitlab::Database::LockWritesManager.new(
table_name: table,
connection: connection,
database_name: database_name
database_name: connection.pool.db_config.name
).lock_writes
end
end
@ -199,7 +244,6 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
context 'when truncating gitlab_ci tables on the main database' do
let(:connection) { ApplicationRecord.connection }
let(:database_name) { "main" }
let(:legacy_tables_models) { [main_db_ci_item_model, main_db_ci_reference_model] }
let(:referencing_table_model) { main_db_ci_reference_model }
let(:referenced_table_model) { main_db_ci_item_model }
@ -217,8 +261,10 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
context 'when truncating gitlab_main tables on the ci database' do
let(:connection) { Ci::ApplicationRecord.connection }
let(:database_name) { "ci" }
let(:legacy_tables_models) { [ci_db_main_item_model, ci_db_main_reference_model] }
let(:legacy_tables_models) do
[ci_db_main_item_model, ci_db_main_reference_model, ci_db_partitioned_item, ci_db_partitioned_item_detached]
end
let(:referencing_table_model) { ci_db_main_reference_model }
let(:referenced_table_model) { ci_db_main_item_model }
let(:other_tables_models) do

View File

@ -90,9 +90,13 @@ RSpec.describe Gitlab::GithubImport::Importer::IssuesImporter do
.to receive(:each_object_to_import)
.and_yield(github_issue)
expect(Gitlab::GithubImport::ImportIssueWorker).to receive(:bulk_perform_in).with(1.second, [
[project.id, an_instance_of(Hash), an_instance_of(String)]
], batch_size: 1000, batch_delay: 1.minute)
expect(Gitlab::GithubImport::ImportIssueWorker)
.to receive(:bulk_perform_in)
.with(1.second,
[[project.id, an_instance_of(Hash), an_instance_of(String)]],
batch_size: 1000,
batch_delay: 1.minute
)
waiter = importer.parallel_import

View File

@ -141,9 +141,8 @@ RSpec.describe Gitlab::Search::FoundBlob do
subject { described_class.new(blob_path: path, project: project, ref: 'master') }
before do
allow(Gitlab::Git::Blob).to receive(:batch).and_return([
Gitlab::Git::Blob.new(path: path)
])
allow(Gitlab::Git::Blob)
.to receive(:batch).and_return([Gitlab::Git::Blob.new(path: path)])
end
it { expect(subject.path).to eq('a/b/c.md') }

View File

@ -2,9 +2,7 @@
require 'spec_helper'
RSpec.describe VersionCheck, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
RSpec.describe VersionCheck do
describe '.url' do
it 'returns the correct URL' do
expect(described_class.url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.json\?gitlab_info=\w+})
@ -32,7 +30,7 @@ RSpec.describe VersionCheck, :use_clean_rails_memory_store_caching do
end
it 'returns the response object' do
expect(described_class.new.calculate_reactive_cache).to eq({ "status" => "success" })
expect(described_class.new.calculate_reactive_cache).to eq("{ \"status\": \"success\" }")
end
end
@ -41,31 +39,38 @@ RSpec.describe VersionCheck, :use_clean_rails_memory_store_caching do
stub_request(:get, described_class.url).to_return(status: 500, body: nil, headers: {})
end
it 'returns an error hash' do
expect(described_class.new.calculate_reactive_cache).to eq({ error: 'version check failed', status: 500 })
it 'returns nil' do
expect(described_class.new.calculate_reactive_cache).to be(nil)
end
end
end
describe '#response' do
context 'cache returns value' do
it 'returns the response object' do
version_check = described_class.new
data = { status: 'success' }
stub_reactive_cache(version_check, data)
let(:response) { { "severity" => "success" }.to_json }
expect(version_check.response).to eq(data)
before do
allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:with_reactive_cache).and_return(response)
end
end
it 'returns the response object' do
expect(described_class.new.response).to be(response)
end
end
context 'cache returns error' do
it 'returns nil and invalidates the reactive cache' do
version_check = described_class.new
stub_reactive_cache(version_check, error: 'version check failed')
context 'cache returns nil' do
let(:response) { nil }
expect(version_check).to receive(:refresh_reactive_cache!).and_call_original
expect(version_check.response).to be_nil
expect(read_reactive_cache(version_check)).to be_nil
before do
allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:with_reactive_cache).and_return(response)
end
end
it 'returns nil' do
expect(described_class.new.response).to be(nil)
end
end
end

View File

@ -28,11 +28,9 @@ RSpec.describe Ci::RunnerVersion, feature_category: :runner do
end
it 'contains any valid or unprocessed runner version that is not already recommended' do
is_expected.to match_array([
runner_version_nil,
runner_version_not_available,
runner_version_available
])
is_expected.to match_array(
[runner_version_nil, runner_version_not_available, runner_version_available]
)
end
end

View File

@ -2224,32 +2224,34 @@ RSpec.describe Repository do
describe '#after_change_head' do
it 'flushes the method caches' do
expect(repository).to receive(:expire_method_caches).with([
:size,
:commit_count,
:readme_path,
:contribution_guide,
:changelog,
:license_blob,
:license_licensee,
:license_gitaly,
:gitignore,
:gitlab_ci_yml,
:branch_names,
:tag_names,
:branch_count,
:tag_count,
:avatar,
:exists?,
:root_ref,
:merged_branch_names,
:has_visible_content?,
:issue_template_names_hash,
:merge_request_template_names_hash,
:user_defined_metrics_dashboard_paths,
:xcode_project?,
:has_ambiguous_refs?
])
expect(repository).to receive(:expire_method_caches).with(
[
:size,
:commit_count,
:readme_path,
:contribution_guide,
:changelog,
:license_blob,
:license_licensee,
:license_gitaly,
:gitignore,
:gitlab_ci_yml,
:branch_names,
:tag_names,
:branch_count,
:tag_count,
:avatar,
:exists?,
:root_ref,
:merged_branch_names,
:has_visible_content?,
:issue_template_names_hash,
:merge_request_template_names_hash,
:user_defined_metrics_dashboard_paths,
:xcode_project?,
:has_ambiguous_refs?
]
)
repository.after_change_head
end

View File

@ -10,44 +10,44 @@ RSpec.describe 'task completion status response' do
shared_examples 'taskable completion status provider' do |path|
samples = [
{
description: '',
expected_count: 0,
expected_completed_count: 0
},
{
description: 'Lorem ipsum',
expected_count: 0,
expected_completed_count: 0
},
{
description: %{- [ ] task 1
{
description: '',
expected_count: 0,
expected_completed_count: 0
},
{
description: 'Lorem ipsum',
expected_count: 0,
expected_completed_count: 0
},
{
description: %{- [ ] task 1
- [x] task 2 },
expected_count: 2,
expected_completed_count: 1
},
{
description: %{- [ ] task 1
expected_count: 2,
expected_completed_count: 1
},
{
description: %{- [ ] task 1
- [ ] task 2 },
expected_count: 2,
expected_completed_count: 0
},
{
description: %{- [x] task 1
expected_count: 2,
expected_completed_count: 0
},
{
description: %{- [x] task 1
- [x] task 2 },
expected_count: 2,
expected_completed_count: 2
},
{
description: %{- [ ] task 1},
expected_count: 1,
expected_completed_count: 0
},
{
description: %{- [x] task 1},
expected_count: 1,
expected_completed_count: 1
}
expected_count: 2,
expected_completed_count: 2
},
{
description: %{- [ ] task 1},
expected_count: 1,
expected_completed_count: 0
},
{
description: %{- [x] task 1},
expected_count: 1,
expected_completed_count: 1
}
]
samples.each do |sample_data|
context "with a description of #{sample_data[:description].inspect}" do

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'user routing', :clean_gitlab_redis_sessions, feature_category: :authentication_and_authorization do
include SessionHelpers
context 'when GitHub OAuth on project import is cancelled' do
it_behaves_like 'redirecting a legacy path', '/users/auth?error=access_denied&state=xyz', '/users/sign_in'
end
context 'when GitHub OAuth on sign in is cancelled' do
before do
stub_session(auth_on_failure_path: '/projects/new#import_project')
end
context 'when all required parameters are present' do
it_behaves_like 'redirecting a legacy path',
'/users/auth?error=access_denied&state=xyz',
'/projects/new#import_project'
end
context 'when one of the required parameters is missing' do
it_behaves_like 'redirecting a legacy path',
'/users/auth?error=access_denied&state=',
'/auth'
end
end
end

View File

@ -187,25 +187,25 @@ RSpec.describe Security::MergeReportsService, '#execute' do
it 'deduplicates (except cwe and wasc) and sorts the vulnerabilities by severity (desc) then by compare key' do
expect(merged_report.findings).to(
eq([
finding_cwe_2,
finding_wasc_2,
finding_cwe_1,
finding_id_2_loc_2,
finding_id_2_loc_1,
finding_wasc_1,
finding_id_1
])
finding_cwe_2,
finding_wasc_2,
finding_cwe_1,
finding_id_2_loc_2,
finding_id_2_loc_1,
finding_wasc_1,
finding_id_1
])
)
end
it 'deduplicates scanned resources' do
expect(merged_report.scanned_resources).to(
eq([
scanned_resource,
scanned_resource_1,
scanned_resource_2,
scanned_resource_3
])
scanned_resource,
scanned_resource_1,
scanned_resource_2,
scanned_resource_3
])
)
end

View File

@ -21,12 +21,14 @@ module SimpleCovEnv
def configure_formatter
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::SimpleFormatter,
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::CoberturaFormatter,
SimpleCov::Formatter::LcovFormatter
])
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
[
SimpleCov::Formatter::SimpleFormatter,
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::CoberturaFormatter,
SimpleCov::Formatter::LcovFormatter
]
)
end
def configure_job

View File

@ -11,7 +11,7 @@ module Atlassian
schemaVersion pipelineId buildNumber updateSequenceNumber
displayName url state issueKeys testInfo references
lastUpdated
),
),
'properties' => {
'schemaVersion' => schema_version_type,
'pipelineId' => { 'type' => 'string' },

View File

@ -16,15 +16,17 @@ Capybara.server_port = ENV['CAPYBARA_PORT'] if ENV['CAPYBARA_PORT']
JSConsoleError = Class.new(StandardError)
# Filter out innocuous JS console messages
JS_CONSOLE_FILTER = Regexp.union([
'"[HMR] Waiting for update signal from WDS..."',
'"[WDS] Hot Module Replacement enabled."',
'"[WDS] Live Reloading enabled."',
'Download the Vue Devtools extension',
'Download the Apollo DevTools',
"Unrecognized feature: 'interest-cohort'",
'Does this page need fixes or improvements?'
])
JS_CONSOLE_FILTER = Regexp.union(
[
'"[HMR] Waiting for update signal from WDS..."',
'"[WDS] Hot Module Replacement enabled."',
'"[WDS] Live Reloading enabled."',
'Download the Vue Devtools extension',
'Download the Apollo DevTools',
"Unrecognized feature: 'interest-cohort'",
'Does this page need fixes or improvements?'
]
)
CAPYBARA_WINDOW_SIZE = [1366, 768].freeze

View File

@ -1,8 +1,10 @@
# Allow list for spec/support/finder_collection.rb
# Permenant excludes
# Permanent excludes
# For example:
# FooFinder # Reason: It uses a memory backend
- Namespaces::BilledUsersFinder # Reason: There is no need to have anything else besides the ids is current structure
- Namespaces::FreeUserCap::UsersFinder # Reason: There is no need to have anything else besides the count
# Temporary excludes (aka TODOs)
# For example:

View File

@ -3,14 +3,14 @@
module ProjectTemplateTestHelper
def all_templates
%w[
rails spring express iosswift dotnetcore android
gomicro gatsby hugo jekyll plainhtml gitbook
hexo middleman gitpod_spring_petclinic nfhugo
nfjekyll nfplainhtml nfgitbook nfhexo salesforcedx
serverless_framework tencent_serverless_framework
jsonnet cluster_management kotlin_native_linux
pelican bridgetown
]
rails spring express iosswift dotnetcore android
gomicro gatsby hugo jekyll plainhtml gitbook
hexo middleman gitpod_spring_petclinic nfhugo
nfjekyll nfplainhtml nfgitbook nfhexo salesforcedx
serverless_framework tencent_serverless_framework
jsonnet cluster_management kotlin_native_linux
pelican bridgetown
]
end
end

View File

@ -490,12 +490,14 @@ module TestEnv
# The HEAD of the component_folder will be used as heuristic for the version
# of the binaries, allowing to use Git to determine if HEAD is later than
# the expected version. Note: Git considers HEAD to be an anchestor of HEAD.
_out, exit_status = Gitlab::Popen.popen(%W[
#{Gitlab.config.git.bin_path}
-C #{component_folder}
merge-base --is-ancestor
#{expected_version} HEAD
])
_out, exit_status = Gitlab::Popen.popen(
%W[
#{Gitlab.config.git.bin_path}
-C #{component_folder}
merge-base --is-ancestor
#{expected_version} HEAD
]
)
exit_status == 0
end

View File

@ -2,118 +2,118 @@
module UsageDataHelpers
COUNTS_KEYS = %i(
assignee_lists
ci_builds
ci_internal_pipelines
ci_external_pipelines
ci_pipeline_config_auto_devops
ci_pipeline_config_repository
ci_runners
ci_triggers
ci_pipeline_schedules
auto_devops_enabled
auto_devops_disabled
deploy_keys
deployments
successful_deployments
failed_deployments
environments
clusters
clusters_enabled
project_clusters_enabled
group_clusters_enabled
instance_clusters_enabled
clusters_disabled
project_clusters_disabled
group_clusters_disabled
instance_clusters_disabled
clusters_platforms_eks
clusters_platforms_gke
clusters_platforms_user
clusters_integrations_prometheus
clusters_management_project
in_review_folder
grafana_integrated_projects
groups
issues
issues_created_from_gitlab_error_tracking_ui
issues_with_associated_zoom_link
issues_using_zoom_quick_actions
issues_with_embedded_grafana_charts_approx
incident_issues
keys
label_lists
labels
lfs_objects
merge_requests
milestone_lists
milestones
notes
pool_repositories
projects
projects_imported_from_github
projects_asana_active
projects_jenkins_active
projects_jira_active
projects_jira_server_active
projects_jira_cloud_active
projects_jira_dvcs_cloud_active
projects_jira_dvcs_server_active
projects_slack_active
projects_slack_slash_commands_active
projects_custom_issue_tracker_active
projects_mattermost_active
projects_prometheus_active
projects_with_repositories_enabled
projects_with_error_tracking_enabled
projects_with_enabled_alert_integrations
projects_with_terraform_reports
projects_with_terraform_states
pages_domains
protected_branches
protected_branches_except_default
releases
remote_mirrors
snippets
personal_snippets
project_snippets
suggestions
terraform_reports
terraform_states
todos
uploads
web_hooks
user_preferences_user_gitpod_enabled
).freeze
assignee_lists
ci_builds
ci_internal_pipelines
ci_external_pipelines
ci_pipeline_config_auto_devops
ci_pipeline_config_repository
ci_runners
ci_triggers
ci_pipeline_schedules
auto_devops_enabled
auto_devops_disabled
deploy_keys
deployments
successful_deployments
failed_deployments
environments
clusters
clusters_enabled
project_clusters_enabled
group_clusters_enabled
instance_clusters_enabled
clusters_disabled
project_clusters_disabled
group_clusters_disabled
instance_clusters_disabled
clusters_platforms_eks
clusters_platforms_gke
clusters_platforms_user
clusters_integrations_prometheus
clusters_management_project
in_review_folder
grafana_integrated_projects
groups
issues
issues_created_from_gitlab_error_tracking_ui
issues_with_associated_zoom_link
issues_using_zoom_quick_actions
issues_with_embedded_grafana_charts_approx
incident_issues
keys
label_lists
labels
lfs_objects
merge_requests
milestone_lists
milestones
notes
pool_repositories
projects
projects_imported_from_github
projects_asana_active
projects_jenkins_active
projects_jira_active
projects_jira_server_active
projects_jira_cloud_active
projects_jira_dvcs_cloud_active
projects_jira_dvcs_server_active
projects_slack_active
projects_slack_slash_commands_active
projects_custom_issue_tracker_active
projects_mattermost_active
projects_prometheus_active
projects_with_repositories_enabled
projects_with_error_tracking_enabled
projects_with_enabled_alert_integrations
projects_with_terraform_reports
projects_with_terraform_states
pages_domains
protected_branches
protected_branches_except_default
releases
remote_mirrors
snippets
personal_snippets
project_snippets
suggestions
terraform_reports
terraform_states
todos
uploads
web_hooks
user_preferences_user_gitpod_enabled
).freeze
USAGE_DATA_KEYS = %i(
active_user_count
counts
counts_monthly
recorded_at
edition
version
installation_type
uuid
hostname
mattermost_enabled
signup_enabled
ldap_enabled
gravatar_enabled
omniauth_enabled
reply_by_email_enabled
container_registry_enabled
dependency_proxy_enabled
gitlab_shared_runners_enabled
gitlab_pages
git
gitaly
database
prometheus_metrics_enabled
web_ide_clientside_preview_enabled
object_store
topology
).freeze
active_user_count
counts
counts_monthly
recorded_at
edition
version
installation_type
uuid
hostname
mattermost_enabled
signup_enabled
ldap_enabled
gravatar_enabled
omniauth_enabled
reply_by_email_enabled
container_registry_enabled
dependency_proxy_enabled
gitlab_shared_runners_enabled
gitlab_pages
git
gitaly
database
prometheus_metrics_enabled
web_ide_clientside_preview_enabled
object_store
topology
).freeze
def stub_usage_data_connections
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)

View File

@ -65,12 +65,14 @@ module ExceedQueryLimitHelpers
MARGINALIA_ANNOTATION_REGEX = %r{\s*\/\*.*\*\/}.freeze
DB_QUERY_RE = Regexp.union([
/^(?<prefix>SELECT .* FROM "?[a-z_]+"?) (?<suffix>.*)$/m,
/^(?<prefix>UPDATE "?[a-z_]+"?) (?<suffix>.*)$/m,
/^(?<prefix>INSERT INTO "[a-z_]+" \((?:"[a-z_]+",?\s?)+\)) (?<suffix>.*)$/m,
/^(?<prefix>DELETE FROM "[a-z_]+") (?<suffix>.*)$/m
]).freeze
DB_QUERY_RE = Regexp.union(
[
/^(?<prefix>SELECT .* FROM "?[a-z_]+"?) (?<suffix>.*)$/m,
/^(?<prefix>UPDATE "?[a-z_]+"?) (?<suffix>.*)$/m,
/^(?<prefix>INSERT INTO "[a-z_]+" \((?:"[a-z_]+",?\s?)+\)) (?<suffix>.*)$/m,
/^(?<prefix>DELETE FROM "[a-z_]+") (?<suffix>.*)$/m
]
).freeze
def with_threshold(threshold)
@threshold = threshold

View File

@ -92,10 +92,10 @@ module MigrationHelpers
"url" => "http://goat:8080/WebGoat/logout",
"body" => "",
"headers" => [
{
"name" => "Accept",
"value" => "*/*"
}
{
"name" => "Accept",
"value" => "*/*"
}
]
},
"response" => {

View File

@ -92,9 +92,9 @@ RSpec.shared_examples 'additional metrics query' do
metrics: [
{
title: 'title', weight: 1, y_label: 'Values', queries: [
{ query_range: 'query_range_a', result: query_range_result },
{ query_range: 'query_range_b', label: 'label', unit: 'unit', result: query_range_result }
]
{ query_range: 'query_range_a', result: query_range_result },
{ query_range: 'query_range_b', label: 'label', unit: 'unit', result: query_range_result }
]
}
]
}

View File

@ -14,7 +14,7 @@ RSpec.shared_context 'GroupPolicy context' do
%i[
read_group read_counts
read_label read_issue_board_list read_milestone read_issue_board
]
]
end
let(:guest_permissions) do
@ -22,32 +22,32 @@ RSpec.shared_context 'GroupPolicy context' do
read_label read_group upload_file read_namespace read_group_activity
read_group_issues read_group_boards read_group_labels read_group_milestones
read_group_merge_requests
]
]
end
let(:reporter_permissions) do
%i[
admin_label
admin_milestone
admin_issue_board
read_container_image
read_harbor_registry
read_metrics_dashboard_annotation
read_prometheus
read_crm_contact
read_crm_organization
]
admin_label
admin_milestone
admin_issue_board
read_container_image
read_harbor_registry
read_metrics_dashboard_annotation
read_prometheus
read_crm_contact
read_crm_organization
]
end
let(:developer_permissions) do
%i[
create_metrics_dashboard_annotation
delete_metrics_dashboard_annotation
update_metrics_dashboard_annotation
create_custom_emoji
create_package
read_cluster
]
create_metrics_dashboard_annotation
delete_metrics_dashboard_annotation
update_metrics_dashboard_annotation
create_custom_emoji
create_package
read_cluster
]
end
let(:maintainer_permissions) do

View File

@ -42,9 +42,7 @@ RSpec.shared_examples 'querying a GraphQL type with labels' do
make_query(
[
query_graphql_field(:label, label_params, all_graphql_fields_for(Label)),
query_graphql_field(:labels, labels_params, [
query_graphql_field(:nodes, nil, all_graphql_fields_for(Label))
])
query_graphql_field(:labels, labels_params, [query_graphql_field(:nodes, nil, all_graphql_fields_for(Label))])
]
)
end

View File

@ -25,10 +25,12 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
end
it 'builds UploadedFiles' do
expect_uploaded_files([
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file1) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(file2) }
])
expect_uploaded_files(
[
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file1) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(file2) }
]
)
subject
end
@ -61,10 +63,12 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
end
it 'builds UploadedFiles' do
expect_uploaded_files([
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user screenshot) }
])
expect_uploaded_files(
[
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user screenshot) }
]
)
subject
end
@ -101,10 +105,12 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
end
it 'builds UploadedFiles' do
expect_uploaded_files([
{ filepath: uploaded_file, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar bananas) },
{ filepath: uploaded_file2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user friend ananas) }
])
expect_uploaded_files(
[
{ filepath: uploaded_file, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar bananas) },
{ filepath: uploaded_file2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user friend ananas) }
]
)
subject
end
@ -133,11 +139,13 @@ RSpec.shared_examples 'handling all upload parameters conditions' do
end
it 'builds UploadedFiles' do
expect_uploaded_files([
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user avatar) },
{ filepath: uploaded_filepath3, original_filename: filename3, remote_id: remote_id3, size: uploaded_file3.size, params_path: %w(user friend avatar) }
])
expect_uploaded_files(
[
{ filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file) },
{ filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user avatar) },
{ filepath: uploaded_filepath3, original_filename: filename3, remote_id: remote_id3, size: uploaded_file3.size, params_path: %w(user friend avatar) }
]
)
subject
end

View File

@ -71,11 +71,7 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
get_container_repository_storage_moves
json_ids = json_response.map { |storage_move| storage_move['id'] }
expect(json_ids).to eq([
storage_move.id,
storage_move_middle.id,
storage_move_oldest.id
])
expect(json_ids).to eq([storage_move.id, storage_move_middle.id, storage_move_oldest.id])
end
describe 'permissions' do

View File

@ -19,6 +19,30 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
let(:main_connection) { ApplicationRecord.connection }
let(:ci_connection) { Ci::ApplicationRecord.connection }
let(:detached_partition_table) { '_test_gitlab_main_part_20220101' }
before do
create_detached_partition_sql = <<~SQL
CREATE TABLE IF NOT EXISTS gitlab_partitions_dynamic._test_gitlab_main_part_20220101 (
id bigserial primary key not null
)
SQL
main_connection.execute(create_detached_partition_sql)
ci_connection.execute(create_detached_partition_sql)
Gitlab::Database::SharedModel.using_connection(main_connection) do
Postgresql::DetachedPartition.create!(
table_name: detached_partition_table,
drop_after: Time.current
)
end
allow(Gitlab::Database::GitlabSchema).to receive(:table_schema).and_call_original
allow(Gitlab::Database::GitlabSchema).to receive(:table_schema)
.with(detached_partition_table).and_return(:gitlab_main)
end
context 'single database' do
before do
skip_if_multiple_databases_are_setup
@ -46,6 +70,13 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
context 'multiple databases' do
before do
skip_if_multiple_databases_not_setup
Gitlab::Database::SharedModel.using_connection(ci_connection) do
Postgresql::DetachedPartition.create!(
table_name: detached_partition_table,
drop_after: Time.current
)
end
end
context 'when locking writes' do
@ -87,6 +118,13 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
main_connection.execute("truncate ci_build_needs")
end.to raise_error(ActiveRecord::StatementInvalid, /Table: "ci_build_needs" is write protected/)
end
it 'prevents writes to detached partitions' do
run_rake_task('gitlab:db:lock_writes')
expect do
ci_connection.execute("INSERT INTO gitlab_partitions_dynamic.#{detached_partition_table} DEFAULT VALUES")
end.to raise_error(ActiveRecord::StatementInvalid, /Table: "#{detached_partition_table}" is write protected/)
end
end
context 'when running in dry_run mode' do
@ -138,6 +176,14 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
main_connection.execute("delete from ci_builds")
end.not_to raise_error
end
it 'allows writes again to detached partitions' do
run_rake_task('gitlab:db:unlock_writes')
expect do
ci_connection.execute("INSERT INTO gitlab_partitions_dynamic._test_gitlab_main_part_20220101 DEFAULT VALUES")
end.not_to raise_error
end
end
end

View File

@ -9,10 +9,13 @@ RSpec.describe 'projects/issues/_related_branches' do
let(:status) { pipeline.detailed_status(build(:user)) }
before do
assign(:related_branches, [
{ name: 'other', link: 'link-to-other', pipeline_status: nil },
{ name: 'feature', link: 'link-to-feature', pipeline_status: status }
])
assign(:related_branches,
[
{ name: 'other', link: 'link-to-other', pipeline_status: nil },
{ name: 'feature', link: 'link-to-feature', pipeline_status: status }
]
)
render
end

View File

@ -35,10 +35,7 @@ module Tooling
end
def delete(release_name:)
run_command([
'uninstall',
release_name
])
run_command(['uninstall', release_name])
end
private