Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c77b780ee0
commit
95de7177f2
|
|
@ -8,7 +8,6 @@ RSpec/AvoidConditionalStatements:
|
|||
- 'ee/spec/features/boards/user_visits_board_spec.rb'
|
||||
- 'ee/spec/features/ci_shared_runner_warnings_spec.rb'
|
||||
- 'ee/spec/features/epic_boards/epic_boards_spec.rb'
|
||||
- 'ee/spec/features/epics/epic_show_spec.rb'
|
||||
- 'ee/spec/features/epics/gfm_autocomplete_spec.rb'
|
||||
- 'ee/spec/features/group_protected_branches_spec.rb'
|
||||
- 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
|
||||
|
|
|
|||
|
|
@ -132,11 +132,6 @@ class ProjectStatistics < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.bulk_increment_statistic(project, key, increments)
|
||||
unless Feature.enabled?(:project_statistics_bulk_increment, type: :development)
|
||||
total_amount = Gitlab::Counters::Increment.new(amount: increments.sum(&:amount))
|
||||
return increment_statistic(project, key, total_amount)
|
||||
end
|
||||
|
||||
return if project.pending_delete?
|
||||
|
||||
project.statistics.try do |project_statistics|
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
|
||||
.gl-mt-5
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { class: 'gl-mb-0' }) do
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true) do
|
||||
= _("Resend")
|
||||
|
||||
.clearfix.prepend-top-20
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
= f.label _('Confirm new password'), for: "user_password_confirmation"
|
||||
= f.password_field :password_confirmation, autocomplete: 'new-password', class: "form-control gl-form-input bottom", title: _('This field is required.'), data: { qa_selector: 'password_confirmation_field' }, required: true
|
||||
.clearfix.gl-px-5.gl-pb-5
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { class: 'gl-mb-0', data: { qa_selector: 'change_password_button' } }) do
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { data: { qa_selector: 'change_password_button' } }) do
|
||||
= _('Change your password')
|
||||
|
||||
.clearfix.prepend-top-20
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
|
||||
.gl-p-5
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { class: 'gl-mb-0' }) do
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true) do
|
||||
= _('Reset password')
|
||||
|
||||
.clearfix.prepend-top-20
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
%div
|
||||
= render 'devise/shared/tab_single', tab_title: _('Two-factor authentication') if Feature.disabled?(:restyle_login_page, @project)
|
||||
.login-box.gl-p-5
|
||||
.login-body
|
||||
- if @user.two_factor_enabled?
|
||||
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}" }) do |f|
|
||||
= render 'devise/shared/tab_single', tab_title: _('Two-factor authentication') if Feature.disabled?(:restyle_login_page, @project)
|
||||
.login-box.gl-p-5
|
||||
.login-body
|
||||
- if @user.two_factor_enabled?
|
||||
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}" }) do |f|
|
||||
.form-group
|
||||
= f.label :otp_attempt, _('Enter verification code')
|
||||
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
|
||||
%p.form-text.text-muted.hint
|
||||
= _("Enter the code from your two-factor authenticator app. If you've lost your device, you can enter one of your recovery codes.")
|
||||
|
||||
- if remember_me_enabled?
|
||||
- resource_params = params[resource_name].presence || params
|
||||
- if remember_me_enabled?
|
||||
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
|
||||
%div
|
||||
= f.label _('Enter verification code'), name: :otp_attempt, class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-mb-1' : ''
|
||||
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
|
||||
%p.form-text.text-muted.hint= _("Enter the code from your two-factor authenticator app. If you've lost your device, you can enter one of your recovery codes.")
|
||||
.prepend-top-20
|
||||
= f.submit _("Verify code"), pajamas_button: true, data: { qa_selector: 'verify_code_button' }
|
||||
- if @user.two_factor_webauthn_enabled?
|
||||
= render "authentication/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path
|
||||
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
|
||||
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { data: { qa_selector: 'verify_code_button' } }) do
|
||||
= _("Verify code")
|
||||
|
||||
- if @user.two_factor_webauthn_enabled?
|
||||
= render "authentication/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: project_statistics_bulk_increment
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/103879
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/385845
|
||||
milestone: '15.7'
|
||||
type: development
|
||||
group: group::pipeline security
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddAdminVulnerabilityToMemberRoles < Gitlab::Database::Migration[2.1]
|
||||
def change
|
||||
add_column :member_roles, :admin_vulnerability, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddOperatorValueIntervalToScanResultPolicies < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
AGE_VALUE_CONSTRAINT = 'age_value_null_or_positive'
|
||||
|
||||
def up
|
||||
add_column(:scan_result_policies, :age_value, :integer)
|
||||
add_column(:scan_result_policies, :age_operator, :integer, limit: 2)
|
||||
add_column(:scan_result_policies, :age_interval, :integer, limit: 2)
|
||||
|
||||
add_check_constraint(:scan_result_policies, 'age_value IS NULL OR age_value >= 0', AGE_VALUE_CONSTRAINT)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column(:scan_result_policies, :age_value)
|
||||
remove_column(:scan_result_policies, :age_operator)
|
||||
remove_column(:scan_result_policies, :age_interval)
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,7 @@ class DropExperimentUsersTable < Gitlab::Database::Migration[2.0]
|
|||
end
|
||||
|
||||
def down
|
||||
create_table :experiment_users do |t| # rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
create_table :experiment_users do |t|
|
||||
t.bigint :experiment_id, null: false
|
||||
t.bigint :user_id, null: false
|
||||
t.integer :group_type, limit: 2, null: false, default: 0
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class DropExperimentSubjectsTable < Gitlab::Database::Migration[2.0]
|
|||
|
||||
def down
|
||||
unless table_exists?(:experiment_subjects)
|
||||
create_table :experiment_subjects do |t| # rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
create_table :experiment_subjects do |t|
|
||||
t.bigint :experiment_id, null: false
|
||||
t.bigint :user_id
|
||||
t.bigint :project_id
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class DropExperimentsTable < Gitlab::Database::Migration[2.0]
|
|||
|
||||
def down
|
||||
unless table_exists?(:experiments)
|
||||
create_table :experiments do |t| # rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
create_table :experiments do |t|
|
||||
t.text :name, null: false
|
||||
|
||||
t.index :name, unique: true
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ class RemoveNamespacesTmpProjectIdColumn < Gitlab::Database::Migration[2.0]
|
|||
def down
|
||||
unless column_exists?(:namespaces, :tmp_project_id)
|
||||
with_lock_retries do
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:disable Migration/AddColumnsToWideTables
|
||||
add_column :namespaces, :tmp_project_id, :integer
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:enable Migration/AddColumnsToWideTables
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ class RemoveNewAmountUsedColumn < Gitlab::Database::Migration[2.1]
|
|||
def down
|
||||
return if column_exists?(:ci_project_monthly_usages, :new_amount_used)
|
||||
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:disable Migration/AddColumnsToWideTables
|
||||
add_column :ci_project_monthly_usages, :new_amount_used, :decimal, default: 0.0,
|
||||
precision: 18, scale: 2, null: false
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:enable Migration/AddColumnsToWideTables
|
||||
|
||||
install_rename_triggers :ci_project_monthly_usages, :amount_used, :new_amount_used, trigger_name: TRIGGER_NAME
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ class RemoveNewAmountUsedColumnOnCiNamespaceMonthlyUsages < Gitlab::Database::Mi
|
|||
def down
|
||||
return if column_exists?(:ci_namespace_monthly_usages, :new_amount_used)
|
||||
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:disable Migration/AddColumnsToWideTables
|
||||
add_column :ci_namespace_monthly_usages, :new_amount_used, :decimal, default: 0.0,
|
||||
precision: 18, scale: 2, null: false
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost, Migration/AddColumnsToWideTables
|
||||
# rubocop:enable Migration/AddColumnsToWideTables
|
||||
|
||||
install_rename_triggers :ci_namespace_monthly_usages, :amount_used, :new_amount_used, trigger_name: TRIGGER_NAME
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ class DropWebHookCallsHighColumn < Gitlab::Database::Migration[2.1]
|
|||
def down
|
||||
with_lock_retries do
|
||||
unless column_exists?(:plan_limits, :web_hook_calls_high)
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :plan_limits, :web_hook_calls_high, :integer, default: 0
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class DropPackagesEventsTable < Gitlab::Database::Migration[2.1]
|
|||
def down
|
||||
return if table_exists?(:packages_events)
|
||||
|
||||
create_table :packages_events do |t| # rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
create_table :packages_events do |t|
|
||||
t.integer :event_type, limit: 2, null: false
|
||||
t.integer :event_scope, limit: 2, null: false
|
||||
t.integer :originator_type, limit: 2, null: false
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class RemoveMachineIdFromBuildsMetadata < Gitlab::Database::Migration[2.1]
|
|||
end
|
||||
|
||||
def down
|
||||
add_column :p_ci_builds_metadata, :runner_machine_id, :bigint, if_not_exists: true # rubocop: disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :p_ci_builds_metadata, :runner_machine_id, :bigint, if_not_exists: true
|
||||
|
||||
add_concurrent_partitioned_index :p_ci_builds_metadata, :runner_machine_id, name: INDEX_NAME,
|
||||
where: 'runner_machine_id IS NOT NULL'
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ class RemoveApplicationSettingsClickhouseConnectionString < Gitlab::Database::Mi
|
|||
|
||||
def down
|
||||
unless column_exists?(:application_settings, :clickhouse_connection_string)
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :application_settings, :clickhouse_connection_string, :text
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
||||
add_text_limit :application_settings, :clickhouse_connection_string, 1024
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsCertManagers < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init migration:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L680-L689
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table "clusters_applications_cert_managers", id: :serial, force: :cascade do |t|
|
||||
t.integer "cluster_id", null: false
|
||||
|
|
@ -23,5 +22,4 @@ class DropClustersApplicationsCertManagers < Gitlab::Database::Migration[2.1]
|
|||
t.index ["cluster_id"], name: "index_clusters_applications_cert_managers_on_cluster_id", unique: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsCilium < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on original migration:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20200615234047_create_clusters_applications_cilium.rb
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table :clusters_applications_cilium do |t|
|
||||
t.references :cluster, null: false, index: { unique: true }
|
||||
|
|
@ -19,5 +18,4 @@ class DropClustersApplicationsCilium < Gitlab::Database::Migration[2.1]
|
|||
t.text :status_reason # rubocop:disable Migration/AddLimitToTextColumns
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsCrossplane < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on original migration:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/8b1637296b286a5c46e0d8fdf6da42a43a7c9986/db/migrate/20191017191341_create_clusters_applications_crossplane.rb
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table :clusters_applications_crossplane, id: :integer do |t|
|
||||
t.timestamps_with_timezone null: false
|
||||
|
|
@ -22,5 +21,4 @@ class DropClustersApplicationsCrossplane < Gitlab::Database::Migration[2.1]
|
|||
t.index :cluster_id, unique: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsHelm < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init schema:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L691-L702
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
# rubocop:disable Migration/Datetime
|
||||
def down
|
||||
create_table "clusters_applications_helm", id: :serial, force: :cascade do |t|
|
||||
|
|
@ -26,6 +25,5 @@ class DropClustersApplicationsHelm < Gitlab::Database::Migration[2.1]
|
|||
t.index ["cluster_id"], name: "index_clusters_applications_helm_on_cluster_id", unique: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
# rubocop:enable Migration/Datetime
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsIngress < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init schema:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L704-L715
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
# rubocop:disable Migration/Datetime
|
||||
def down
|
||||
create_table "clusters_applications_ingress", id: :serial, force: :cascade do |t|
|
||||
|
|
@ -27,6 +26,5 @@ class DropClustersApplicationsIngress < Gitlab::Database::Migration[2.1]
|
|||
t.index ["cluster_id"], name: "index_clusters_applications_ingress_on_cluster_id", unique: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
# rubocop:enable Migration/Datetime
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsJupyter < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init schema:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L717-L728
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table "clusters_applications_jupyter", id: :serial, force: :cascade do |t|
|
||||
t.integer "cluster_id", null: false
|
||||
|
|
@ -25,5 +24,4 @@ class DropClustersApplicationsJupyter < Gitlab::Database::Migration[2.1]
|
|||
t.index ["oauth_application_id"], name: "index_clusters_applications_jupyter_on_oauth_application_id"
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsKnative < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init migration:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L730-L740
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table "clusters_applications_knative", id: :serial, force: :cascade do |t|
|
||||
t.integer "cluster_id", null: false
|
||||
|
|
@ -25,5 +24,4 @@ class DropClustersApplicationsKnative < Gitlab::Database::Migration[2.1]
|
|||
t.index ["cluster_id"], name: "index_clusters_applications_knative_on_cluster_id", unique: true
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsPrometheus < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init schema:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L742-L750
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table "clusters_applications_prometheus", id: :serial, force: :cascade do |t|
|
||||
t.integer "cluster_id", null: false
|
||||
|
|
@ -26,5 +25,4 @@ class DropClustersApplicationsPrometheus < Gitlab::Database::Migration[2.1]
|
|||
t.boolean "healthy"
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropClustersApplicationsRunners < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on init schema:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/b237f836df215a4ada92b9406733e6cd2483ca2d/db/migrate/20181228175414_init_schema.rb#L752-L763
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table "clusters_applications_runners", id: :serial, force: :cascade do |t|
|
||||
t.integer "cluster_id", null: false
|
||||
|
|
@ -25,5 +24,4 @@ class DropClustersApplicationsRunners < Gitlab::Database::Migration[2.1]
|
|||
t.index ["runner_id"], name: "index_clusters_applications_runners_on_runner_id"
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class DropServerlessDomainCluster < Gitlab::Database::Migration[2.1]
|
|||
|
||||
# Based on original migration:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/5f7bd5b1455d87e2f1a2d1ae2c1147d51e97aa55/db/migrate/20191127030005_create_serverless_domain_cluster.rb
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
def down
|
||||
create_table :serverless_domain_cluster, id: false, primary_key: :uuid do |t|
|
||||
t.string :uuid, null: false, limit: 14, primary_key: true
|
||||
|
|
@ -29,5 +28,4 @@ class DropServerlessDomainCluster < Gitlab::Database::Migration[2.1]
|
|||
t.index :creator_id, name: 'index_serverless_domain_cluster_on_creator_id'
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ class RemoveCiTriggersRefColumn < Gitlab::Database::Migration[2.1]
|
|||
end
|
||||
|
||||
def down
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :ci_triggers, :ref, :string, if_not_exists: true
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ class RemoveTimeFormatIn24hColumn < Gitlab::Database::Migration[2.1]
|
|||
end
|
||||
|
||||
def down
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :user_preferences, :time_format_in_24h, :boolean
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ class RemoveProjectCiCdSettingOptInJwtColumn < Gitlab::Database::Migration[2.1]
|
|||
end
|
||||
|
||||
def down
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column(:project_ci_cd_settings, :opt_in_jwt, :boolean, default: false, null: false, if_not_exists: true)
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropUnnecessaryAsyncIndexFromEvents < Gitlab::Database::Migration[2.1]
|
||||
INDEX_NAME = 'index_on_events_to_improve_contribution_analytics_performance'
|
||||
|
||||
def up
|
||||
prepare_async_index_removal :events, %i[project_id target_type action created_at author_id id], name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
unprepare_async_index :events, %i[project_id target_type action created_at author_id id], name: INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -10,9 +10,7 @@ class RemoveBroadcastMessagesNamespaceIdColumn < Gitlab::Database::Migration[2.1
|
|||
end
|
||||
|
||||
def down
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost
|
||||
add_column :broadcast_messages, :namespace_id, :bigint unless column_exists?(:broadcast_messages, :namespace_id)
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
|
||||
add_concurrent_index :broadcast_messages, :namespace_id, name: INDEX_NAME
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
6c287edd3102743f83a94b3f961074eb2d85c63c7f7789c63cb51a11ef4c04c1
|
||||
|
|
@ -0,0 +1 @@
|
|||
e149178598dcfaadb8c56107a0c3f4bff7a8e942968fb879c479c7d1a8cca401
|
||||
|
|
@ -0,0 +1 @@
|
|||
4dcfbb2dc0168ab14a30e27d655910a56c2ad2585a4769ebceb22077dd8dd839
|
||||
|
|
@ -17886,7 +17886,8 @@ CREATE TABLE member_roles (
|
|||
updated_at timestamp with time zone NOT NULL,
|
||||
base_access_level integer NOT NULL,
|
||||
read_code boolean DEFAULT false,
|
||||
read_vulnerability boolean DEFAULT false NOT NULL
|
||||
read_vulnerability boolean DEFAULT false NOT NULL,
|
||||
admin_vulnerability boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE member_roles_id_seq
|
||||
|
|
@ -22289,7 +22290,11 @@ CREATE TABLE scan_result_policies (
|
|||
orchestration_policy_idx smallint NOT NULL,
|
||||
license_states text[] DEFAULT '{}'::text[],
|
||||
match_on_inclusion boolean,
|
||||
role_approvers integer[] DEFAULT '{}'::integer[]
|
||||
role_approvers integer[] DEFAULT '{}'::integer[],
|
||||
age_value integer,
|
||||
age_operator smallint,
|
||||
age_interval smallint,
|
||||
CONSTRAINT age_value_null_or_positive CHECK (((age_value IS NULL) OR (age_value >= 0)))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE scan_result_policies_id_seq
|
||||
|
|
|
|||
|
|
@ -737,6 +737,13 @@ To resolve this error, you must apply a new license to the GitLab instance witho
|
|||
1. Enter the [Rails console and add the license key](../../../user/admin_area/license_file.md#add-a-license-through-the-console).
|
||||
1. Re-enable the additional LDAP servers in the GitLab configuration and reconfigure GitLab again.
|
||||
|
||||
## Users are being removed from group and re-added again
|
||||
|
||||
If a user has been added to a group during group sync, and removed at the next sync, and this has happened repeatedly, make sure that the user doesn't have
|
||||
multiple or redundant LDAP identities.
|
||||
|
||||
If one of those identities was added for an older LDAP provider that is no longer in use, [remove the `identity` records that relate to the removed LDAP server](#remove-the-identity-records-that-relate-to-the-removed-ldap-server).
|
||||
|
||||
## Debugging Tools
|
||||
|
||||
### LDAP check
|
||||
|
|
|
|||
|
|
@ -210,14 +210,11 @@ There is a complete list of all GitLab [data types](replication/datatypes.md) an
|
|||
|
||||
If you try to view replication data on the primary site, you receive a warning that this may be inconsistent:
|
||||
|
||||
> Viewing projects and designs data from a primary site is not possible when using a unified URL. Visit the secondary site directly.
|
||||
> Viewing projects data from a primary site is not possible when using a unified URL. Visit the secondary site directly.
|
||||
|
||||
The only way to view projects replication data for a particular secondary site is to visit that secondary site directly. For example, `https://<IP of your secondary site>/admin/geo/replication/projects`.
|
||||
An [epic exists](https://gitlab.com/groups/gitlab-org/-/epics/4623) to fix this limitation.
|
||||
|
||||
The only way to view designs replication data for a particular secondary site is to visit that secondary site directly. For example, `https://<IP of your secondary site>/admin/geo/replication/designs`.
|
||||
An [epic exists](https://gitlab.com/groups/gitlab-org/-/epics/4624) to fix this limitation.
|
||||
|
||||
Keep in mind that mentioned URLs don't work when [Admin Mode](../../user/admin_area/settings/sign_in_restrictions.md#admin-mode) is enabled.
|
||||
|
||||
When using Unified URL, visiting the secondary site directly means you must route your requests to the secondary site. Exactly how this might be done depends on your networking configuration. If using DNS to route requests to the appropriate site, then you can, for example, edit your local machine's `/etc/hosts` file to route your requests to the desired secondary site. If the Geo sites are all behind a load balancer, then depending on the load balancer, you might be able to configure all requests from your IP to go to a particular secondary site.
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ successfully, you must replicate their data using some other means.
|
|||
|[CI Secure Files](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/secure_file.rb) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_ci_secure_file_replication`, enabled by default in 15.3. |
|
||||
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3)<sup>1</sup> | **Yes** (15.10) | **Yes** (12.3)<sup>1</sup> | **Yes** (15.10) | See [instructions](container_registry.md) to set up the Container Registry replication. |
|
||||
|[Terraform Module Registry](../../../user/packages/terraform_module_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
|
||||
|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | N/A | N/A | Designs also require replication of LFS objects and Uploads. |
|
||||
|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | **Yes** (16.1) | N/A | N/A | Designs also require replication of LFS objects and Uploads. Replication is behind the feature flag geo_design_management_repository_replication, enabled by default.|
|
||||
|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
|
||||
|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | **Yes** (13.12) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
|
||||
|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ for details.
|
|||
To use TLS certificates with Let's Encrypt, you can manually point the domain to one of the Geo sites, generate
|
||||
the certificate, then copy it to all other sites.
|
||||
|
||||
- [Viewing projects and designs data from a primary site is not possible when using a unified URL](../index.md#view-replication-data-on-the-primary-site).
|
||||
- [Viewing projects data from a primary site is not possible when using a unified URL](../index.md#view-replication-data-on-the-primary-site).
|
||||
|
||||
- When secondary proxying is used together with separate URLs, registering [GitLab runners](https://docs.gitlab.com/runner/) to clone from
|
||||
secondary sites is not supported. The runner registration succeeds, but the clone URL defaults to the primary site. The runner
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ Support for PDF files is tracked in [issue 32811](https://gitlab.com/gitlab-org/
|
|||
- [A project is destroyed](https://gitlab.com/gitlab-org/gitlab/-/issues/13429).
|
||||
- [An issue is deleted](https://gitlab.com/gitlab-org/gitlab/-/issues/13427).
|
||||
- In GitLab 12.7 and later, Design Management data [can be replicated](../../../administration/geo/replication/datatypes.md#limitations-on-replicationverification)
|
||||
by Geo but [not verified](https://gitlab.com/gitlab-org/gitlab/-/issues/32467).
|
||||
and in GitLab 16.1 and later it can be [verified by Geo as well](https://gitlab.com/gitlab-org/gitlab/-/issues/355660).
|
||||
|
||||
## View a design
|
||||
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ module Gitlab
|
|||
@authentication_provider = @context[:authentication_provider]
|
||||
|
||||
# TODO: Remove this code once we close https://gitlab.com/gitlab-org/gitlab/-/issues/367870
|
||||
return unless @is_audit_event_yaml_defined
|
||||
return if @is_audit_event_yaml_defined
|
||||
|
||||
# rubocop:disable Gitlab/RailsLogger
|
||||
Rails.logger.warn('WARNING: Logging audit events without an event type definition will be deprecated soon.')
|
||||
Rails.logger.warn('See https://docs.gitlab.com/ee/development/audit_event_guide/#event-type-definitions')
|
||||
# rubocop:enable Gitlab/RailsLogger
|
||||
message = 'Logging audit events without an event type definition will be deprecated soon ' \
|
||||
'(https://docs.gitlab.com/ee/development/audit_event_guide/#event-type-definitions)'
|
||||
|
||||
Gitlab::AppLogger.warn(message: message, event_type: @name)
|
||||
end
|
||||
|
||||
def single_audit
|
||||
|
|
|
|||
|
|
@ -78,11 +78,7 @@ module Gitlab
|
|||
|
||||
def increment(increment)
|
||||
result = redis_state do |redis|
|
||||
if Feature.enabled?(:project_statistics_bulk_increment, type: :development)
|
||||
redis.eval(LUA_INCREMENT_WITH_DEDUPLICATION_SCRIPT, **increment_args(increment)).to_i
|
||||
else
|
||||
redis.incrby(key, increment.amount)
|
||||
end
|
||||
redis.eval(LUA_INCREMENT_WITH_DEDUPLICATION_SCRIPT, **increment_args(increment)).to_i
|
||||
end
|
||||
|
||||
FlushCounterIncrementsWorker.perform_in(WORKER_DELAY, counter_record.class.name, counter_record.id, attribute)
|
||||
|
|
@ -94,11 +90,7 @@ module Gitlab
|
|||
result = redis_state do |redis|
|
||||
redis.pipelined do |pipeline|
|
||||
increments.each do |increment|
|
||||
if Feature.enabled?(:project_statistics_bulk_increment, type: :development)
|
||||
pipeline.eval(LUA_INCREMENT_WITH_DEDUPLICATION_SCRIPT, **increment_args(increment))
|
||||
else
|
||||
pipeline.incrby(key, increment.amount)
|
||||
end
|
||||
pipeline.eval(LUA_INCREMENT_WITH_DEDUPLICATION_SCRIPT, **increment_args(increment))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28013,6 +28013,9 @@ msgstr ""
|
|||
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "MemberRole|%{requirement} has to be enabled in order to enable %{permission}."
|
||||
msgstr ""
|
||||
|
||||
msgid "MemberRole|%{role} - custom"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50089,7 +50092,7 @@ msgstr ""
|
|||
msgid "Viewing commit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Viewing projects and designs data from a primary site is not possible when using a unified URL. Visit the secondary site directly. %{geo_help_url}"
|
||||
msgid "Viewing projects data from a primary site is not possible when using a unified URL. Visit the secondary site directly. %{geo_help_url}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Violation"
|
||||
|
|
|
|||
|
|
@ -93,17 +93,18 @@ module QA
|
|||
# Download files from GCS bucket by environment name
|
||||
# Delete the files afterward
|
||||
def download(ci_project_name)
|
||||
bucket_items = gcs_storage.list_objects(BUCKET, prefix: ci_project_name).items
|
||||
logger.info("Downloading resource files from GCS for #{ci_project_name}...")
|
||||
bucket_items = gcs_storage.list_objects(BUCKET, prefix: "#{ci_project_name}/").items
|
||||
|
||||
files_list = bucket_items&.each_with_object([]) do |obj, arr|
|
||||
arr << obj.name
|
||||
end
|
||||
|
||||
if files_list.blank?
|
||||
if bucket_items.blank?
|
||||
logger.info("\nNothing to download!")
|
||||
return
|
||||
end
|
||||
|
||||
files_list = bucket_items.each_with_object([]) do |obj, arr|
|
||||
arr << obj.name
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p('tmp/')
|
||||
|
||||
files_list.each do |file_name|
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require_relative '../../migration_helpers'
|
|||
module RuboCop
|
||||
module Cop
|
||||
module Migration
|
||||
# Cop that checks that no background batched migration helpers are called by regular migrations.
|
||||
# Cop that checks that no schema migration methods are called by post-deployment migrations.
|
||||
class SchemaAdditionMethodsNoPost < RuboCop::Cop::Base
|
||||
include MigrationHelpers
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ module RuboCop
|
|||
private
|
||||
|
||||
def rolling_back_migration?(node)
|
||||
rolling_back_migration(node.parent)
|
||||
node.each_ancestor(:def).any? { |a| rolling_back_migration(a) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,12 +18,45 @@ RSpec.describe Gitlab::Audit::Auditor, feature_category: :audit_events do
|
|||
end
|
||||
|
||||
let(:logger) { instance_spy(Gitlab::AuditJsonLogger) }
|
||||
let(:app_logger) { instance_spy(Gitlab::AppLogger) }
|
||||
|
||||
subject(:auditor) { described_class }
|
||||
|
||||
describe '.audit' do
|
||||
let(:audit!) { auditor.audit(context) }
|
||||
|
||||
context 'when yaml definition is not defined' do
|
||||
before do
|
||||
allow(Gitlab::Audit::Type::Definition).to receive(:defined?).and_return(false)
|
||||
allow(Gitlab::AppLogger).to receive(:warn).and_return(app_logger)
|
||||
end
|
||||
|
||||
it 'logs a warning when YAML is not defined' do
|
||||
expected_warning = {
|
||||
message: 'Logging audit events without an event type definition will be deprecated soon ' \
|
||||
'(https://docs.gitlab.com/ee/development/audit_event_guide/#event-type-definitions)',
|
||||
event_type: name
|
||||
}
|
||||
|
||||
audit!
|
||||
|
||||
expect(Gitlab::AppLogger).to have_received(:warn).with(expected_warning)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when yaml definition is defined' do
|
||||
before do
|
||||
allow(Gitlab::Audit::Type::Definition).to receive(:defined?).and_return(true)
|
||||
allow(Gitlab::AppLogger).to receive(:warn).and_return(app_logger)
|
||||
end
|
||||
|
||||
it 'does not log a warning when YAML is defined' do
|
||||
audit!
|
||||
|
||||
expect(Gitlab::AppLogger).not_to have_received(:warn)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authentication event' do
|
||||
it 'creates an authentication event' do
|
||||
expect(AuthenticationEvent).to receive(:new).with(
|
||||
|
|
|
|||
|
|
@ -244,43 +244,6 @@ RSpec.describe Gitlab::Counters::BufferedCounter, :clean_gitlab_redis_shared_sta
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(project_statistics_bulk_increment: false)
|
||||
end
|
||||
|
||||
context 'when the counter is not undergoing refresh' do
|
||||
it 'sets a new key by the given value' do
|
||||
counter.increment(increment)
|
||||
|
||||
expect(counter.get).to eq(increment.amount)
|
||||
end
|
||||
|
||||
it 'increments an existing key by the given value' do
|
||||
counter.increment(other_increment)
|
||||
counter.increment(increment)
|
||||
|
||||
expect(counter.get).to eq(other_increment.amount + increment.amount)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the counter is undergoing refresh' do
|
||||
before do
|
||||
counter.initiate_refresh!
|
||||
end
|
||||
|
||||
context 'when it is a decrement (negative amount)' do
|
||||
let(:decrement) { Gitlab::Counters::Increment.new(amount: -123, ref: 3) }
|
||||
|
||||
it 'immediately decrements the counter key to negative' do
|
||||
counter.increment(decrement)
|
||||
|
||||
expect(counter.get).to eq(decrement.amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#bulk_increment' do
|
||||
|
|
@ -416,44 +379,6 @@ RSpec.describe Gitlab::Counters::BufferedCounter, :clean_gitlab_redis_shared_sta
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(project_statistics_bulk_increment: false)
|
||||
end
|
||||
|
||||
context 'when the counter is not undergoing refresh' do
|
||||
it 'sets a new key by the given value' do
|
||||
counter.bulk_increment(increments)
|
||||
|
||||
expect(counter.get).to eq(increments.sum(&:amount))
|
||||
end
|
||||
|
||||
it 'increments an existing key by the given value' do
|
||||
counter.increment(other_increment)
|
||||
|
||||
result = counter.bulk_increment(increments)
|
||||
|
||||
expect(result).to eq(other_increment.amount + increments.sum(&:amount))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the counter is undergoing refresh' do
|
||||
before do
|
||||
counter.initiate_refresh!
|
||||
end
|
||||
|
||||
context 'when it is a decrement (negative amount)' do
|
||||
let(:decrement) { Gitlab::Counters::Increment.new(amount: -123, ref: 3) }
|
||||
|
||||
it 'immediately decrements the counter key to negative' do
|
||||
counter.bulk_increment([decrement])
|
||||
|
||||
expect(counter.get).to eq(decrement.amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#initiate_refresh!' do
|
||||
|
|
|
|||
|
|
@ -635,22 +635,6 @@ RSpec.describe ProjectStatistics do
|
|||
let(:stat) { :build_artifacts_size }
|
||||
|
||||
it_behaves_like 'a statistic that increases storage_size asynchronously'
|
||||
|
||||
context 'when :project_statistics_bulk_increment flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(project_statistics_bulk_increment: false)
|
||||
end
|
||||
|
||||
it 'calls increment_statistic on once with the sum of the increments' do
|
||||
total_amount = increments.sum(&:amount)
|
||||
expect(statistics)
|
||||
.to receive(:increment_statistic).with(stat, have_attributes(amount: total_amount)).and_call_original
|
||||
|
||||
described_class.bulk_increment_statistic(project, stat, increments)
|
||||
end
|
||||
|
||||
it_behaves_like 'a statistic that increases storage_size asynchronously'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when adjusting :pipeline_artifacts_size' do
|
||||
|
|
|
|||
|
|
@ -42,5 +42,13 @@ RSpec.describe RuboCop::Cop::Migration::SchemaAdditionMethodsNoPost, feature_cat
|
|||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
it "allows forbidden method to be called within nested statement" do
|
||||
expect_no_offenses(<<~CODE)
|
||||
def down
|
||||
add_column(:table, :column, :boolean) unless column_exists?(:table, :column)
|
||||
end
|
||||
CODE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue