Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ea413f31cf
commit
277496b843
|
|
@ -63,7 +63,7 @@ and cross-posted (with the command results) to the responsible team's Slack chan
|
|||
Cross link the issue here if it does.
|
||||
- [ ] Ensure that you or a representative in development can be available for at least 2 hours after feature flag updates in production.
|
||||
If a different developer will be covering, or an exception is needed, please inform the oncall SRE by using the `@sre-oncall` Slack alias.
|
||||
- [ ] Ensure that [documentation has been updated](https://docs.gitlab.com/ee/development/documentation/feature_flags.html).
|
||||
- [ ] Ensure that documentation exists for the feature, and the [version history text](https://docs.gitlab.com/ee/development/documentation/feature_flags.html#add-version-history-text) has been updated.
|
||||
- [ ] Leave a comment on [the feature issue][main-issue] announcing estimated time when this feature flag will be enabled on GitLab.com.
|
||||
- [ ] Ensure that any breaking changes have been announced following the [release post process](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes) to ensure GitLab customers are aware.
|
||||
- [ ] Notify the [`#support_gitlab-com` Slack channel](https://gitlab.slack.com/archives/C4XFU81LG) and your team channel ([more guidance when this is necessary in the dev docs](https://docs.gitlab.com/ee/development/feature_flags/controls.html#communicate-the-change)).
|
||||
|
|
|
|||
|
|
@ -483,9 +483,9 @@ BackgroundMigration/FeatureCategory:
|
|||
Include:
|
||||
- 'lib/gitlab/background_migration/*.rb'
|
||||
|
||||
BackgroundMigration/MissingDictionaryFile:
|
||||
BackgroundMigration/DictionaryFile:
|
||||
Enabled: true
|
||||
EnforcedSince: 20230307160251
|
||||
EnforcedSince: 20231018100907
|
||||
Include:
|
||||
- 'db/post_migrate/*.rb'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
# Grace period will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/428931
|
||||
BackgroundMigration/DictionaryFile:
|
||||
Details: grace period
|
||||
|
|
@ -36,8 +36,7 @@ export default function initDiffsApp(store = notesStore) {
|
|||
iid: dataset.iid || '',
|
||||
endpointCoverage: dataset.endpointCoverage || '',
|
||||
endpointCodequality: dataset.endpointCodequality || '',
|
||||
// This is a workaround which will be solved in: https://gitlab.com/gitlab-org/gitlab/-/issues/428758
|
||||
sastReportAvailable: Boolean(dataset.endpointSast),
|
||||
sastReportAvailable: dataset.endpointSast,
|
||||
helpPagePath: dataset.helpPagePath,
|
||||
currentUser: JSON.parse(dataset.currentUserData) || {},
|
||||
changesEmptyStateIllustration: dataset.changesEmptyStateIllustration,
|
||||
|
|
|
|||
|
|
@ -657,7 +657,6 @@ $discord: #5865f2;
|
|||
$linkedin: #2867b2;
|
||||
$mastodon: #6364ff;
|
||||
$skype: #0078d7;
|
||||
$twitter: #1d9bf0;
|
||||
|
||||
/*
|
||||
* Award emoji
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@
|
|||
}
|
||||
|
||||
.twitter-icon {
|
||||
color: $twitter;
|
||||
color: var(--gl-text-color, $gl-text-color);
|
||||
}
|
||||
|
||||
.discord-icon {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AcmeChallengesController < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class AcmeChallengesController < ActionController::Base
|
||||
def show
|
||||
if acme_order
|
||||
render plain: acme_order.challenge_file_content, content_type: 'text/plain'
|
||||
|
|
@ -15,3 +16,4 @@ class AcmeChallengesController < BaseActionController
|
|||
@acme_order ||= PagesDomainAcmeOrder.find_by_domain_and_token(params[:domain], params[:token])
|
||||
end
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'gon'
|
||||
require 'fogbugz'
|
||||
|
||||
class ApplicationController < BaseActionController
|
||||
class ApplicationController < ActionController::Base
|
||||
include Gitlab::GonHelper
|
||||
include Gitlab::NoCacheHeaders
|
||||
include GitlabRoutingHelper
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# GitLab lightweight base action controller
|
||||
#
|
||||
# This class should be limited to content that
|
||||
# is desired/required for *all* controllers in
|
||||
# GitLab.
|
||||
#
|
||||
# Most controllers inherit from `ApplicationController`.
|
||||
# Some controllers don't want or need all of that
|
||||
# logic and instead inherit from `ActionController::Base`.
|
||||
# This makes it difficult to set security headers and
|
||||
# handle other critical logic across *all* controllers.
|
||||
#
|
||||
# Between this controller and `ApplicationController`
|
||||
# no controller should ever inherit directly from
|
||||
# `ActionController::Base`
|
||||
#
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
# rubocop:disable Gitlab/NamespacedClass
|
||||
class BaseActionController < ActionController::Base
|
||||
before_action :security_headers
|
||||
|
||||
private
|
||||
|
||||
def security_headers
|
||||
headers['Cross-Origin-Opener-Policy'] = 'same-origin' if ::Feature.enabled?(:coop_header)
|
||||
end
|
||||
end
|
||||
# rubocop:enable Gitlab/NamespacedClass
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ChaosController < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class ChaosController < ActionController::Base
|
||||
before_action :validate_chaos_secret, unless: :development_or_test?
|
||||
|
||||
def leakmem
|
||||
|
|
@ -94,3 +95,4 @@ class ChaosController < BaseActionController
|
|||
Rails.env.development? || Rails.env.test?
|
||||
end
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class HealthController < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class HealthController < ActionController::Base
|
||||
protect_from_forgery with: :exception, prepend: true
|
||||
include RequiresAllowlistedMonitoringClient
|
||||
|
||||
|
|
@ -39,3 +40,4 @@ class HealthController < BaseActionController
|
|||
render json: result.json, status: result.http_status
|
||||
end
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MetricsController < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class MetricsController < ActionController::Base
|
||||
include RequiresAllowlistedMonitoringClient
|
||||
|
||||
protect_from_forgery with: :exception, prepend: true
|
||||
|
|
@ -35,3 +36,4 @@ class MetricsController < BaseActionController
|
|||
)
|
||||
end
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%p.text-center
|
||||
%p{ class: local_assigns.fetch(:wrapper_class, 'gl-text-center') }
|
||||
%span.light
|
||||
= _('Already have an account?')
|
||||
- path_params = { redirect_to_referer: 'yes' }
|
||||
|
|
|
|||
|
|
@ -1,77 +1,10 @@
|
|||
- max_first_name_length = max_last_name_length = 127
|
||||
- borderless ||= false
|
||||
- form_resource_name = "new_#{resource_name}"
|
||||
|
||||
.gl-mb-3.gl-p-4{ class: (borderless ? '' : 'gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base') }
|
||||
= yield :omniauth_providers_top if show_omniauth_providers
|
||||
|
||||
= gitlab_ui_form_for(resource, as: form_resource_name, url: url, html: { class: 'gl-show-field-errors js-arkose-labs-form', aria: { live: 'assertive' }}, data: { testid: 'signup-form' }) do |f|
|
||||
.devise-errors
|
||||
= render 'devise/shared/error_messages', resource: resource
|
||||
- if Gitlab::CurrentSettings.invisible_captcha_enabled
|
||||
= invisible_captcha nonce: true, autocomplete: SecureRandom.alphanumeric(12)
|
||||
.name.form-row
|
||||
.col.form-group
|
||||
= f.label :first_name, _('First name'), for: 'new_user_first_name'
|
||||
= f.text_field :first_name,
|
||||
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
|
||||
data: { max_length: max_first_name_length,
|
||||
max_length_message: s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length },
|
||||
testid: 'new-user-first-name-field' },
|
||||
required: true,
|
||||
title: _('This field is required.')
|
||||
.col.form-group
|
||||
= f.label :last_name, _('Last name'), for: 'new_user_last_name'
|
||||
= f.text_field :last_name,
|
||||
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
|
||||
data: { max_length: max_last_name_length,
|
||||
max_length_message: s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length },
|
||||
testid: 'new-user-last-name-field' },
|
||||
required: true,
|
||||
title: _('This field is required.')
|
||||
.username.form-group
|
||||
= f.label :username, _('Username')
|
||||
= f.text_field :username,
|
||||
class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username',
|
||||
data: signup_username_data_attributes,
|
||||
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
|
||||
required: true,
|
||||
title: _('Please create a username with only alphanumeric characters.')
|
||||
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
|
||||
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
|
||||
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
|
||||
.form-group
|
||||
= f.label :email, _('Email')
|
||||
= f.email_field :email,
|
||||
class: 'form-control gl-form-input middle js-validate-email',
|
||||
data: { testid: 'new-user-email-field' },
|
||||
required: true,
|
||||
title: _('Please provide a valid email address.')
|
||||
%p.validation-hint.gl-field-hint.text-secondary= _('We recommend a work email address.')
|
||||
%p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
|
||||
-# This is used for providing entry to Jihu on email verification
|
||||
= render_if_exists 'devise/shared/signup_email_additional_info'
|
||||
.form-group.gl-mb-5
|
||||
= f.label :password, _('Password')
|
||||
%input.form-control.gl-form-input.js-password{ data: { id: "#{form_resource_name}_password",
|
||||
title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length },
|
||||
minimum_password_length: @minimum_password_length,
|
||||
testid: 'new-user-password-field',
|
||||
autocomplete: 'new-password',
|
||||
name: "#{form_resource_name}[password]" } }
|
||||
%p.gl-field-hint-valid.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
|
||||
= render_if_exists 'shared/password_requirements_list'
|
||||
= render_if_exists 'devise/shared/phone_verification', form: f
|
||||
= render 'devise/shared/signup_box_form',
|
||||
button_text: button_text,
|
||||
url: url,
|
||||
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
|
||||
|
||||
.form-group
|
||||
- if arkose_labs_enabled?
|
||||
= render_if_exists 'devise/registrations/arkose_labs'
|
||||
- elsif show_recaptcha_sign_up?
|
||||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { data: { testid: 'new-user-register-button' }}) do
|
||||
= button_text
|
||||
|
||||
= render 'devise/shared/terms_of_service_notice', button_text: button_text
|
||||
|
||||
= yield :omniauth_providers_bottom if show_omniauth_providers
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
- max_first_name_length = max_last_name_length = 127
|
||||
- form_resource_name = "new_#{resource_name}"
|
||||
|
||||
= gitlab_ui_form_for(resource, as: form_resource_name, url: url, html: { class: 'gl-show-field-errors js-arkose-labs-form', aria: { live: 'assertive' }}, data: { testid: 'signup-form' }) do |f|
|
||||
.devise-errors
|
||||
= render 'devise/shared/error_messages', resource: resource
|
||||
- if Gitlab::CurrentSettings.invisible_captcha_enabled
|
||||
= invisible_captcha nonce: true, autocomplete: SecureRandom.alphanumeric(12)
|
||||
.name.form-row
|
||||
.col.form-group
|
||||
= f.label :first_name, _('First name'), for: 'new_user_first_name'
|
||||
= f.text_field :first_name,
|
||||
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
|
||||
data: { max_length: max_first_name_length,
|
||||
max_length_message: s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length },
|
||||
testid: 'new-user-first-name-field' },
|
||||
required: true,
|
||||
title: _('This field is required.')
|
||||
.col.form-group
|
||||
= f.label :last_name, _('Last name'), for: 'new_user_last_name'
|
||||
= f.text_field :last_name,
|
||||
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
|
||||
data: { max_length: max_last_name_length,
|
||||
max_length_message: s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length },
|
||||
testid: 'new-user-last-name-field' },
|
||||
required: true,
|
||||
title: _('This field is required.')
|
||||
.username.form-group
|
||||
= f.label :username, _('Username')
|
||||
= f.text_field :username,
|
||||
class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username',
|
||||
data: signup_username_data_attributes,
|
||||
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
|
||||
required: true,
|
||||
title: _('Please create a username with only alphanumeric characters.')
|
||||
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
|
||||
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
|
||||
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
|
||||
.form-group
|
||||
= f.label :email, _('Email')
|
||||
= f.email_field :email,
|
||||
class: 'form-control gl-form-input middle js-validate-email',
|
||||
data: { testid: 'new-user-email-field' },
|
||||
required: true,
|
||||
title: _('Please provide a valid email address.')
|
||||
%p.validation-hint.gl-field-hint.text-secondary= _('We recommend a work email address.')
|
||||
%p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
|
||||
-# This is used for providing entry to Jihu on email verification
|
||||
= render_if_exists 'devise/shared/signup_email_additional_info'
|
||||
.form-group.gl-mb-5
|
||||
= f.label :password, _('Password')
|
||||
%input.form-control.gl-form-input.js-password{ data: { id: "#{form_resource_name}_password",
|
||||
title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length },
|
||||
minimum_password_length: @minimum_password_length,
|
||||
testid: 'new-user-password-field',
|
||||
autocomplete: 'new-password',
|
||||
name: "#{form_resource_name}[password]" } }
|
||||
%p.gl-field-hint-valid.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
|
||||
= render_if_exists 'shared/password_requirements_list'
|
||||
= render_if_exists 'devise/shared/phone_verification', form: f
|
||||
|
||||
.form-group
|
||||
- if arkose_labs_enabled?
|
||||
= render_if_exists 'devise/registrations/arkose_labs'
|
||||
- elsif show_recaptcha_sign_up?
|
||||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true, button_options: { data: { testid: 'new-user-register-button' }}) do
|
||||
= button_text
|
||||
|
||||
= render 'devise/shared/terms_of_service_notice', button_text: button_text
|
||||
|
||||
= yield :omniauth_providers_bottom if show_omniauth_providers
|
||||
|
|
@ -14,7 +14,10 @@
|
|||
= _("Create an account using:")
|
||||
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
|
||||
- providers.each do |provider|
|
||||
= button_to omniauth_authorize_path(:user, provider, register_omniauth_params(local_assigns)), class: "btn gl-button btn-default gl-w-full gl-mb-4 js-oauth-login #{qa_selector_for_provider(provider)}", data: { provider: provider, track_action: "#{provider}_sso", track_label: tracking_label }, id: "oauth-login-#{provider}" do
|
||||
= button_to omniauth_authorize_path(:user, provider, register_omniauth_params(local_assigns)),
|
||||
class: "btn gl-button btn-default gl-w-full gl-mb-4 js-oauth-login #{qa_selector_for_provider(provider)}",
|
||||
data: { provider: provider, track_action: "#{provider}_sso", track_label: tracking_label },
|
||||
id: "oauth-login-#{provider}" do
|
||||
- if provider_has_icon?(provider)
|
||||
= provider_image_tag(provider)
|
||||
%span.gl-button-text
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: coop_header
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131571
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/425701
|
||||
milestone: '16.5'
|
||||
type: development
|
||||
group: group::authentication
|
||||
default_enabled: false
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# rubocop: disable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop: disable BackgroundMigration/DictionaryFile
|
||||
|
||||
class RescheduleMigrationForRemediation < Gitlab::Database::Migration[2.1]
|
||||
MIGRATION = 'MigrateRemediationsForVulnerabilityFindings'
|
||||
|
|
@ -29,4 +29,4 @@ class RescheduleMigrationForRemediation < Gitlab::Database::Migration[2.1]
|
|||
delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
|
||||
end
|
||||
end
|
||||
# rubocop: enable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop: enable BackgroundMigration/DictionaryFile
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop:disable BackgroundMigration/DictionaryFile
|
||||
class RequeueBackfillProjectWikiRepositories < Gitlab::Database::Migration[2.1]
|
||||
MIGRATION = "BackfillProjectWikiRepositories"
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
|
@ -26,4 +26,4 @@ class RequeueBackfillProjectWikiRepositories < Gitlab::Database::Migration[2.1]
|
|||
delete_batched_background_migration(MIGRATION, :projects, :id, [])
|
||||
end
|
||||
end
|
||||
# rubocop:enable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop:enable BackgroundMigration/DictionaryFile
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop:disable BackgroundMigration/DictionaryFile
|
||||
|
||||
class RescheduleEvidencesHandlingUnicode < Gitlab::Database::Migration[2.1]
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
|
@ -29,4 +29,4 @@ class RescheduleEvidencesHandlingUnicode < Gitlab::Database::Migration[2.1]
|
|||
delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
|
||||
end
|
||||
end
|
||||
# rubocop:enable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop:enable BackgroundMigration/DictionaryFile
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# rubocop: disable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop: disable BackgroundMigration/DictionaryFile
|
||||
|
||||
class RescheduleMigrationForLinksFromMetadata < Gitlab::Database::Migration[2.1]
|
||||
MIGRATION = 'MigrateLinksForVulnerabilityFindings'
|
||||
|
|
@ -29,4 +29,4 @@ class RescheduleMigrationForLinksFromMetadata < Gitlab::Database::Migration[2.1]
|
|||
delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
|
||||
end
|
||||
end
|
||||
# rubocop: enable BackgroundMigration/MissingDictionaryFile
|
||||
# rubocop: enable BackgroundMigration/DictionaryFile
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CleanupBigintConversionForCiProjectMonthlyUsagesSharedRunnersDuration < Gitlab::Database::Migration[2.1]
|
||||
enable_lock_retries!
|
||||
|
||||
TABLE = :ci_project_monthly_usages
|
||||
COLUMNS = [:shared_runners_duration]
|
||||
|
||||
def up
|
||||
cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS)
|
||||
end
|
||||
|
||||
def down
|
||||
restore_conversion_of_integer_to_bigint(TABLE, COLUMNS)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CleanupBigintConversionForCiNamespaceMonthlyUsagesSharedRunnersDuration < Gitlab::Database::Migration[2.1]
|
||||
enable_lock_retries!
|
||||
|
||||
TABLE = :ci_namespace_monthly_usages
|
||||
COLUMNS = [:shared_runners_duration]
|
||||
|
||||
def up
|
||||
cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS)
|
||||
end
|
||||
|
||||
def down
|
||||
restore_conversion_of_integer_to_bigint(TABLE, COLUMNS)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveRedundantGroupStagesIndex < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
milestone '16.6'
|
||||
|
||||
INDEX_NAME = 'index_analytics_ca_group_stages_on_group_id'
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name(:analytics_cycle_analytics_group_stages, INDEX_NAME)
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index(:analytics_cycle_analytics_group_stages, :group_id, name: INDEX_NAME)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveRedundantMrMetricsIndexOnTargetProjectId < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
milestone '16.6'
|
||||
|
||||
INDEX_NAME = 'index_merge_request_metrics_on_target_project_id'
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index(:merge_request_metrics, :target_project_id, name: INDEX_NAME)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
1bd136e7d4fb7c34030cea6c915a2eeae619ea5ae1a701cb4d5d4bb069df7113
|
||||
|
|
@ -0,0 +1 @@
|
|||
bf03b09c6247d2f5c3543f4046b48763dfc7e6fb2cdaedc52d8cfc8777f70e71
|
||||
|
|
@ -0,0 +1 @@
|
|||
add7ce4f9fb56221512227d5aa3697245d537cd5c975978b7dc6dab992890e4e
|
||||
|
|
@ -0,0 +1 @@
|
|||
08275dacbe6b1bd44cc67834fc77d6615e43ebd1b9a85edc9e7237cbecc57315
|
||||
|
|
@ -335,15 +335,6 @@ BEGIN
|
|||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_bbb95b2d6929() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW."shared_runners_duration_convert_to_bigint" := NEW."shared_runners_duration";
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_bfad0e2b9c86() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -353,15 +344,6 @@ BEGIN
|
|||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_c0353bbb6145() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW."shared_runners_duration_convert_to_bigint" := NEW."shared_runners_duration";
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION unset_has_issues_on_vulnerability_reads() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -13788,7 +13770,6 @@ CREATE TABLE ci_namespace_monthly_usages (
|
|||
namespace_id bigint NOT NULL,
|
||||
date date NOT NULL,
|
||||
notification_level smallint DEFAULT 100 NOT NULL,
|
||||
shared_runners_duration_convert_to_bigint integer DEFAULT 0 NOT NULL,
|
||||
created_at timestamp with time zone,
|
||||
amount_used numeric(18,4) DEFAULT 0.0 NOT NULL,
|
||||
shared_runners_duration bigint DEFAULT 0 NOT NULL,
|
||||
|
|
@ -14074,7 +14055,6 @@ CREATE TABLE ci_project_monthly_usages (
|
|||
id bigint NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
date date NOT NULL,
|
||||
shared_runners_duration_convert_to_bigint integer DEFAULT 0 NOT NULL,
|
||||
created_at timestamp with time zone,
|
||||
amount_used numeric(18,4) DEFAULT 0.0 NOT NULL,
|
||||
shared_runners_duration bigint DEFAULT 0 NOT NULL,
|
||||
|
|
@ -31413,8 +31393,6 @@ CREATE INDEX index_allowed_email_domains_on_group_id ON allowed_email_domains US
|
|||
|
||||
CREATE INDEX index_analytics_ca_group_stages_on_end_event_label_id ON analytics_cycle_analytics_group_stages USING btree (end_event_label_id);
|
||||
|
||||
CREATE INDEX index_analytics_ca_group_stages_on_group_id ON analytics_cycle_analytics_group_stages USING btree (group_id);
|
||||
|
||||
CREATE INDEX index_analytics_ca_group_stages_on_relative_position ON analytics_cycle_analytics_group_stages USING btree (relative_position);
|
||||
|
||||
CREATE INDEX index_analytics_ca_group_stages_on_start_event_label_id ON analytics_cycle_analytics_group_stages USING btree (start_event_label_id);
|
||||
|
|
@ -33129,8 +33107,6 @@ CREATE INDEX index_merge_request_metrics_on_merged_by_id ON merge_request_metric
|
|||
|
||||
CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics USING btree (pipeline_id);
|
||||
|
||||
CREATE INDEX index_merge_request_metrics_on_target_project_id ON merge_request_metrics USING btree (target_project_id);
|
||||
|
||||
CREATE INDEX index_merge_request_review_llm_summaries_on_mr_diff_id ON merge_request_review_llm_summaries USING btree (merge_request_diff_id);
|
||||
|
||||
CREATE INDEX index_merge_request_review_llm_summaries_on_review_id ON merge_request_review_llm_summaries USING btree (review_id);
|
||||
|
|
@ -36779,12 +36755,8 @@ CREATE TRIGGER trigger_7f3d66a7d7f5 BEFORE INSERT OR UPDATE ON ci_pipeline_varia
|
|||
|
||||
CREATE TRIGGER trigger_b2d852e1e2cb BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_b2d852e1e2cb();
|
||||
|
||||
CREATE TRIGGER trigger_bbb95b2d6929 BEFORE INSERT OR UPDATE ON ci_project_monthly_usages FOR EACH ROW EXECUTE FUNCTION trigger_bbb95b2d6929();
|
||||
|
||||
CREATE TRIGGER trigger_bfad0e2b9c86 BEFORE INSERT OR UPDATE ON ci_pipeline_messages FOR EACH ROW EXECUTE FUNCTION trigger_bfad0e2b9c86();
|
||||
|
||||
CREATE TRIGGER trigger_c0353bbb6145 BEFORE INSERT OR UPDATE ON ci_namespace_monthly_usages FOR EACH ROW EXECUTE FUNCTION trigger_c0353bbb6145();
|
||||
|
||||
CREATE TRIGGER trigger_delete_project_namespace_on_project_delete AFTER DELETE ON projects FOR EACH ROW WHEN ((old.project_namespace_id IS NOT NULL)) EXECUTE FUNCTION delete_associated_project_namespace();
|
||||
|
||||
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON integrations FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ To install `agentk`:
|
|||
kind: Secret
|
||||
metadata:
|
||||
name: gitlab-agent-token
|
||||
namespace: gitlab
|
||||
type: Opaque
|
||||
stringData:
|
||||
token: "<your-token-here>"
|
||||
|
|
|
|||
|
|
@ -94,37 +94,6 @@ module API
|
|||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
helpers do
|
||||
def commit
|
||||
strong_memoize(:commit) do
|
||||
user_project.commit(params[:sha])
|
||||
end
|
||||
end
|
||||
|
||||
def all_matching_pipelines
|
||||
pipelines = user_project.ci_pipelines.newest_first(sha: commit.sha)
|
||||
pipelines = pipelines.for_ref(params[:ref]) if params[:ref]
|
||||
pipelines = pipelines.id_in(params[:pipeline_id]) if params[:pipeline_id]
|
||||
pipelines
|
||||
end
|
||||
|
||||
def apply_job_state!(job)
|
||||
case params[:state]
|
||||
when 'pending'
|
||||
job.enqueue!
|
||||
when 'running'
|
||||
job.enqueue
|
||||
job.run!
|
||||
when 'success'
|
||||
job.success!
|
||||
when 'failed'
|
||||
job.drop!(:api_failure)
|
||||
when 'canceled'
|
||||
job.cancel!
|
||||
else
|
||||
render_api_error!('invalid state', 400)
|
||||
end
|
||||
end
|
||||
|
||||
def optional_commit_status_params
|
||||
updatable_optional_attributes = %w[target_url description coverage]
|
||||
attributes_for_keys(updatable_optional_attributes)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
# This is a base controller for doorkeeper.
|
||||
# It adds the `can?` helper used in the views.
|
||||
module Gitlab
|
||||
class BaseDoorkeeperController < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class BaseDoorkeeperController < ActionController::Base
|
||||
include Gitlab::Allowable
|
||||
include EnforcesTwoFactorAuthentication
|
||||
include SessionsHelper
|
||||
|
|
@ -12,4 +13,5 @@ module Gitlab
|
|||
|
||||
helper_method :can?
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
module Gitlab
|
||||
module RequestForgeryProtection
|
||||
class Controller < BaseActionController
|
||||
# rubocop:disable Rails/ApplicationController
|
||||
class Controller < ActionController::Base
|
||||
protect_from_forgery with: :exception, prepend: true
|
||||
|
||||
def initialize
|
||||
|
|
@ -39,5 +40,6 @@ module Gitlab
|
|||
rescue ActionController::InvalidAuthenticityToken
|
||||
false
|
||||
end
|
||||
# rubocop:enable Rails/ApplicationController
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24739,12 +24739,21 @@ msgstr ""
|
|||
msgid "InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|%{upper_start}Start your 30-day free trial of%{upper_end} %{lower_start}GitLab Ultimate%{lower_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Accelerate your digital transform"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Built-in security"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Deliver software faster"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Ensure compliance"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -24760,12 +24769,18 @@ msgstr ""
|
|||
msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Improve collaboration and visibility"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Invite unlimited colleagues"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|No credit card required"
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|No credit card required."
|
||||
msgstr ""
|
||||
|
||||
msgid "InProductMarketing|Start a Self-Managed trial"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33224,6 +33239,9 @@ msgstr ""
|
|||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Or create your own GitLab account:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ordered list"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42651,6 +42669,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Branch types don't match any existing branches."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Cannot create an empty policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Choose a project"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42726,6 +42747,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Failed to load images."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|For any MR that matches this policy's rules, only the override project approval settings apply. No additional approvals are required."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|For any merge request on %{branches}%{commitType}%{branchExceptionsString}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42806,6 +42830,9 @@ msgid_plural "SecurityOrchestration|On runners with the tags:"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "SecurityOrchestration|Only overriding settings will take effect"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42971,6 +42998,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|This is a project-level policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|This policy doesn't contain any actions or override project approval settings. You cannot create an empty policy."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|This policy is inherited"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -44720,6 +44750,9 @@ msgstr ""
|
|||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sign up for your free trial with:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sign up was successful! Please confirm your email to sign in."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ ENV GITLAB_LICENSE_MODE=test \
|
|||
|
||||
# Clone GDK at specific sha and bootstrap packages
|
||||
#
|
||||
ARG GDK_SHA=65cf4576208b9f79c54c0042c44024c0008deafc
|
||||
ARG GDK_SHA=d843a4d237bbb9c2f04d2cbddc89fd6dadeb86cf
|
||||
RUN set -eux; \
|
||||
git clone --depth 1 https://gitlab.com/gitlab-org/gitlab-development-kit.git && cd gitlab-development-kit; \
|
||||
git fetch --depth 1 origin ${GDK_SHA} && git -c advice.detachedHead=false checkout ${GDK_SHA}; \
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module QA
|
|||
module Page
|
||||
module Registration
|
||||
class SignUp < Page::Base
|
||||
view 'app/views/devise/shared/_signup_box.html.haml' do
|
||||
view 'app/views/devise/shared/_signup_box_form.html.haml' do
|
||||
element 'new-user-first-name-field'
|
||||
element 'new-user-last-name-field'
|
||||
element 'new-user-email-field'
|
||||
|
|
|
|||
|
|
@ -11,8 +11,11 @@ module QA
|
|||
# This *could* be different than the api_client.user or the api_user provided by the QA::Resource::ApiFabricator
|
||||
attr_writer :user
|
||||
|
||||
attribute :id
|
||||
attribute :token
|
||||
attributes :id, :token
|
||||
|
||||
attribute :expires_at do
|
||||
Time.now.utc.to_date + 2
|
||||
end
|
||||
|
||||
# Only Admins can create PAT via the API.
|
||||
# If Runtime::Env.admin_personal_access_token is provided, fabricate via the API,
|
||||
|
|
@ -49,7 +52,7 @@ module QA
|
|||
api_client = Runtime::API::Client.new(:gitlab,
|
||||
is_new_session: false,
|
||||
user: user,
|
||||
personal_access_token: self.token)
|
||||
personal_access_token: token)
|
||||
request_url = Runtime::API::Request.new(api_client,
|
||||
"/personal_access_tokens?user_id=#{user.id}",
|
||||
per_page: '100').url
|
||||
|
|
@ -88,12 +91,7 @@ module QA
|
|||
end
|
||||
|
||||
def cache_token
|
||||
QA::Resource::PersonalAccessTokenCache.set_token_for_username(user.username, self.token) if @user && self.token
|
||||
end
|
||||
|
||||
# Expire in 2 days just in case the token is created just before midnight
|
||||
def expires_at
|
||||
@expires_at || Time.now.utc.to_date + 2
|
||||
QA::Resource::PersonalAccessTokenCache.set_token_for_username(user.username, token) if @user && token
|
||||
end
|
||||
|
||||
def fabricate!
|
||||
|
|
@ -115,7 +113,7 @@ module QA
|
|||
|
||||
cache_token
|
||||
|
||||
self.token
|
||||
token
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,6 +18,21 @@ module QA
|
|||
tags: { import_type: ENV["QA_IMPORT_TYPE"], import_repo: ENV["QA_LARGE_IMPORT_REPO"] || "rspec/rspec-core" }
|
||||
} do
|
||||
describe 'Project import', product_group: :import_and_integrate do # rubocop:disable RSpec/MultipleMemoizedHelpers
|
||||
let!(:api_client) { Runtime::API::Client.as_admin }
|
||||
let!(:user) { create(:user, api_client: api_client) }
|
||||
let!(:user_api_client) do
|
||||
Runtime::API::Client.new(
|
||||
user: user,
|
||||
is_new_session: false,
|
||||
personal_access_token: Resource::PersonalAccessToken.fabricate_via_api! do |pat|
|
||||
pat.user = user
|
||||
# importing very large project can take multiple days
|
||||
# token must not expire while we still poll for import result
|
||||
pat.expires_at = (Time.now.to_date + 5)
|
||||
end.token
|
||||
)
|
||||
end
|
||||
|
||||
# Full object comparison is a fairly heavy operation
|
||||
# Importer itself returns counts of objects it fetched and counts it imported
|
||||
# We can use that for a lightweight comparison for very large projects
|
||||
|
|
@ -103,10 +118,6 @@ module QA
|
|||
]
|
||||
end
|
||||
|
||||
let(:api_client) { Runtime::API::Client.as_admin }
|
||||
|
||||
let(:user) { create(:user, api_client: api_client) }
|
||||
|
||||
let(:github_client) do
|
||||
Octokit::Client.new(
|
||||
access_token: ENV['QA_LARGE_IMPORT_GH_TOKEN'] || Runtime::Env.github_access_token,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
class BatchedBackgroundMigrations
|
||||
class BatchedBackgroundMigrationsDictionary
|
||||
DICTIONARY_BASE_DIR = 'db/docs/batched_background_migrations'
|
||||
|
||||
attr_reader :queued_migration_version
|
||||
|
|
@ -14,6 +14,7 @@ module RuboCop
|
|||
next unless dictionary['queued_migration_version'].present?
|
||||
|
||||
data[dictionary['queued_migration_version'].to_s] = {
|
||||
introduced_by_url: dictionary['introduced_by_url'],
|
||||
finalize_after: dictionary['finalize_after'],
|
||||
finalized_by: dictionary['finalized_by'].to_s
|
||||
}
|
||||
|
|
@ -26,7 +27,21 @@ module RuboCop
|
|||
end
|
||||
|
||||
def finalized_by
|
||||
self.class.dictionary_data.dig(queued_migration_version.to_s, :finalized_by)
|
||||
dictionary_data&.dig(:finalized_by)
|
||||
end
|
||||
|
||||
def finalize_after
|
||||
dictionary_data&.dig(:finalize_after)
|
||||
end
|
||||
|
||||
def introduced_by_url
|
||||
dictionary_data&.dig(:introduced_by_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def dictionary_data
|
||||
@dictionary_data ||= self.class.dictionary_data[queued_migration_version.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,17 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../migration_helpers'
|
||||
require_relative '../../batched_background_migrations_dictionary'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module BackgroundMigration
|
||||
# Checks the batched background migration has the corresponding dictionary file
|
||||
class MissingDictionaryFile < RuboCop::Cop::Base
|
||||
class DictionaryFile < RuboCop::Cop::Base
|
||||
include MigrationHelpers
|
||||
|
||||
MSG = "Missing %{file_name}. " \
|
||||
"Use the generator 'batched_background_migration' to create dictionary files automatically. " \
|
||||
"For more details refer: https://docs.gitlab.com/ee/development/database/batched_background_migrations.html#generator"
|
||||
MSG = {
|
||||
missing_key: "Mandatory key '%{key}' is missing from the dictionary. Please add with an appropriate value.",
|
||||
missing_dictionary: <<-MESSAGE.delete("\n").squeeze(' ').strip
|
||||
Missing %{file_name}.
|
||||
Use the generator 'batched_background_migration' to create dictionary files automatically.
|
||||
For more details refer: https://docs.gitlab.com/ee/development/database/batched_background_migrations.html#generator
|
||||
MESSAGE
|
||||
}.freeze
|
||||
|
||||
DICTIONARY_DIR = "db/docs/batched_background_migrations"
|
||||
|
||||
|
|
@ -35,9 +41,10 @@ module RuboCop
|
|||
migration_name_node.value
|
||||
end
|
||||
|
||||
return if dictionary_file?(migration_name)
|
||||
error_code, msg_params = validate_dictionary_file(migration_name, node)
|
||||
return unless error_code.present?
|
||||
|
||||
add_offense(node, message: format(MSG, file_name: dictionary_file_path(migration_name)))
|
||||
add_offense(node, message: format(MSG[error_code], msg_params))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -50,6 +57,18 @@ module RuboCop
|
|||
File.join(rails_root, DICTIONARY_DIR, "#{migration_class_name.underscore}.yml")
|
||||
end
|
||||
|
||||
def validate_dictionary_file(migration_name, node)
|
||||
unless dictionary_file?(migration_name)
|
||||
return [:missing_dictionary, { file_name: dictionary_file_path(migration_name) }]
|
||||
end
|
||||
|
||||
bbm_dictionary = RuboCop::BatchedBackgroundMigrationsDictionary.new(version(node))
|
||||
|
||||
return [:missing_key, { key: :finalize_after }] unless bbm_dictionary.finalize_after.present?
|
||||
|
||||
return [:missing_key, { key: :introduced_by_url }] unless bbm_dictionary.introduced_by_url.present?
|
||||
end
|
||||
|
||||
def rails_root
|
||||
@rails_root ||= File.expand_path('../../..', __dir__)
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../migration_helpers'
|
||||
require_relative '../../batched_background_migrations'
|
||||
require_relative '../../batched_background_migrations_dictionary'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
|
|
@ -43,7 +43,7 @@ module RuboCop
|
|||
private
|
||||
|
||||
def fetch_finalized_by(queued_migration_version)
|
||||
BatchedBackgroundMigrations.new(queued_migration_version).finalized_by
|
||||
BatchedBackgroundMigrationsDictionary.new(queued_migration_version).finalized_by
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AcmeChallengesController, type: :request, feature_category: :pages do
|
||||
it_behaves_like 'Base action controller' do
|
||||
subject(:request) { get acme_challenge_path }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ApplicationController, type: :request, feature_category: :shared do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it_behaves_like 'Base action controller' do
|
||||
subject(:request) { get root_path }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ChaosController, type: :request, feature_category: :tooling do
|
||||
it_behaves_like 'Base action controller' do
|
||||
before do
|
||||
# Stub leak_mem so we don't actually leak memory for the base action controller tests.
|
||||
allow(Gitlab::Chaos).to receive(:leak_mem).with(100, 30.seconds)
|
||||
end
|
||||
|
||||
subject(:request) { get leakmem_chaos_path }
|
||||
end
|
||||
end
|
||||
|
|
@ -73,9 +73,7 @@ RSpec.describe HealthController, feature_category: :database do
|
|||
end
|
||||
|
||||
describe 'GET /-/readiness' do
|
||||
subject(:request) { get readiness_path, params: params, headers: headers }
|
||||
|
||||
it_behaves_like 'Base action controller'
|
||||
subject { get '/-/readiness', params: params, headers: headers }
|
||||
|
||||
shared_context 'endpoint responding with readiness data' do
|
||||
context 'when requesting instance-checks' do
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MetricsController, type: :request, feature_category: :metrics do
|
||||
it_behaves_like 'Base action controller' do
|
||||
subject(:request) { get metrics_path }
|
||||
end
|
||||
end
|
||||
|
|
@ -20,10 +20,6 @@ RSpec.describe Oauth::AuthorizationsController, feature_category: :system_access
|
|||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
it_behaves_like 'Base action controller' do
|
||||
subject(:request) { get oauth_authorization_path }
|
||||
end
|
||||
|
||||
context 'when application redirect URI has a custom scheme' do
|
||||
context 'when CSP is disabled' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ RSpec.describe RegistrationsController, type: :request, feature_category: :syste
|
|||
describe 'POST #create' do
|
||||
let_it_be(:user_attrs) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
|
||||
|
||||
subject(:request) { post user_registration_path, params: { user: user_attrs } }
|
||||
|
||||
it_behaves_like 'Base action controller'
|
||||
subject(:create_user) { post user_registration_path, params: { user: user_attrs } }
|
||||
|
||||
context 'when email confirmation is required' do
|
||||
before do
|
||||
|
|
@ -17,7 +15,7 @@ RSpec.describe RegistrationsController, type: :request, feature_category: :syste
|
|||
end
|
||||
|
||||
it 'redirects to the `users_almost_there_path`', unless: Gitlab.ee? do
|
||||
request
|
||||
create_user
|
||||
|
||||
expect(response).to redirect_to(users_almost_there_path(email: user_attrs[:email]))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ RSpec.describe 'Sessions', feature_category: :system_access do
|
|||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it_behaves_like 'Base action controller' do
|
||||
subject(:request) { get new_user_session_path }
|
||||
end
|
||||
|
||||
context 'for authentication', :allow_forgery_protection do
|
||||
it 'logout does not require a csrf token' do
|
||||
login_as(user)
|
||||
|
|
|
|||
|
|
@ -2,20 +2,24 @@
|
|||
|
||||
require 'rubocop_spec_helper'
|
||||
|
||||
require_relative '../../rubocop/batched_background_migrations'
|
||||
require_relative '../../rubocop/batched_background_migrations_dictionary'
|
||||
|
||||
RSpec.describe RuboCop::BatchedBackgroundMigrations, feature_category: :database do
|
||||
RSpec.describe RuboCop::BatchedBackgroundMigrationsDictionary, feature_category: :database do
|
||||
let(:bbm_dictionary_file_name) { "#{described_class::DICTIONARY_BASE_DIR}/test_migration.yml" }
|
||||
let(:migration_version) { 20230307160250 }
|
||||
let(:finalized_by_version) { 20230307160255 }
|
||||
let(:introduced_by_url) { 'https://test_url' }
|
||||
let(:finalize_after) { '202312011212' }
|
||||
|
||||
let(:bbm_dictionary_data) do
|
||||
{
|
||||
migration_job_name: 'TestMigration',
|
||||
feature_category: :database,
|
||||
introduced_by_url: 'https://test_url',
|
||||
introduced_by_url: introduced_by_url,
|
||||
milestone: 16.5,
|
||||
queued_migration_version: migration_version,
|
||||
finalized_by: finalized_by_version
|
||||
finalized_by: finalized_by_version,
|
||||
finalize_after: finalize_after
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -40,4 +44,24 @@ RSpec.describe RuboCop::BatchedBackgroundMigrations, feature_category: :database
|
|||
expect(described_class.new('random').finalized_by).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#introduced_by_url' do
|
||||
it 'returns the introduced_by_url of the bbm with given version' do
|
||||
expect(batched_background_migration.introduced_by_url).to eq(introduced_by_url)
|
||||
end
|
||||
|
||||
it 'returns nothing for non-existing bbm dictionary' do
|
||||
expect(described_class.new('random').introduced_by_url).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#finalize_after' do
|
||||
it 'returns the finalize_after timestamp of the bbm with given version' do
|
||||
expect(batched_background_migration.finalize_after).to eq(finalize_after)
|
||||
end
|
||||
|
||||
it 'returns nothing for non-existing bbm dictionary' do
|
||||
expect(described_class.new('random').finalize_after).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,17 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/background_migration/missing_dictionary_file'
|
||||
require_relative '../../../../rubocop/cop/background_migration/dictionary_file'
|
||||
|
||||
RSpec.describe RuboCop::Cop::BackgroundMigration::MissingDictionaryFile, feature_category: :database do
|
||||
RSpec.describe RuboCop::Cop::BackgroundMigration::DictionaryFile, feature_category: :database do
|
||||
let(:config) do
|
||||
RuboCop::Config.new(
|
||||
'BackgroundMigration/MissingDictionaryFile' => {
|
||||
'EnforcedSince' => 20230307160251
|
||||
'BackgroundMigration/DictionaryFile' => {
|
||||
'EnforcedSince' => 20231018100907
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
shared_examples 'migration with missing dictionary keys offense' do |missing_key|
|
||||
it 'registers an offense' do
|
||||
expect_offense(<<~RUBY)
|
||||
class QueueMyMigration < Gitlab::Database::Migration[2.1]
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(described_class::MSG[:missing_key], key: missing_key)}
|
||||
MIGRATION = 'MyMigration'
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:users,
|
||||
:id
|
||||
)
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context 'for non post migrations' do
|
||||
before do
|
||||
allow(cop).to receive(:in_post_deployment_migration?).and_return(false)
|
||||
|
|
@ -57,7 +76,7 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::MissingDictionaryFile, feature
|
|||
|
||||
context 'for migrations before enforced time' do
|
||||
before do
|
||||
allow(cop).to receive(:version).and_return(20230307160250)
|
||||
allow(cop).to receive(:version).and_return(20230918100907)
|
||||
end
|
||||
|
||||
it 'does not throw any offenses' do
|
||||
|
|
@ -79,7 +98,7 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::MissingDictionaryFile, feature
|
|||
|
||||
context 'for migrations after enforced time' do
|
||||
before do
|
||||
allow(cop).to receive(:version).and_return(20230307160252)
|
||||
allow(cop).to receive(:version).and_return(20231118100907)
|
||||
end
|
||||
|
||||
it 'throws offense on not having the appropriate dictionary file with migration name as a constant' do
|
||||
|
|
@ -114,22 +133,48 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::MissingDictionaryFile, feature
|
|||
RUBY
|
||||
end
|
||||
|
||||
it 'does not throw offense with appropriate dictionary file' do
|
||||
expect(File).to receive(:exist?).with(dictionary_file_path).and_return(true)
|
||||
context 'with dictionary file' do
|
||||
let(:introduced_by_url) { 'https://test_url' }
|
||||
let(:finalize_after) { '20230507160251' }
|
||||
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class QueueMyMigration < Gitlab::Database::Migration[2.1]
|
||||
MIGRATION = 'MyMigration'
|
||||
before do
|
||||
allow(File).to receive(:exist?).with(dictionary_file_path).and_return(true)
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:users,
|
||||
:id
|
||||
)
|
||||
end
|
||||
allow_next_instance_of(RuboCop::BatchedBackgroundMigrationsDictionary) do |dictionary|
|
||||
allow(dictionary).to receive(:finalize_after).and_return(finalize_after)
|
||||
allow(dictionary).to receive(:introduced_by_url).and_return(introduced_by_url)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
context 'without introduced_by_url' do
|
||||
it_behaves_like 'migration with missing dictionary keys offense', :introduced_by_url do
|
||||
let(:introduced_by_url) { nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without finalize_after' do
|
||||
it_behaves_like 'migration with missing dictionary keys offense', :finalize_after do
|
||||
let(:finalize_after) { nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with required dictionary keys' do
|
||||
it 'does not throw offense with appropriate dictionary file' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class QueueMyMigration < Gitlab::Database::Migration[2.1]
|
||||
MIGRATION = 'MyMigration'
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:users,
|
||||
:id
|
||||
)
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -99,7 +99,7 @@ RSpec.describe RuboCop::Cop::Migration::UnfinishedDependencies, feature_category
|
|||
|
||||
context 'with properly finalized dependent background migrations' do
|
||||
before do
|
||||
allow_next_instance_of(RuboCop::BatchedBackgroundMigrations) do |bbms|
|
||||
allow_next_instance_of(RuboCop::BatchedBackgroundMigrationsDictionary) do |bbms|
|
||||
allow(bbms).to receive(:finalized_by).and_return(version - 5)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ abuse_reports:
|
|||
alert_management_http_integrations:
|
||||
index_http_integrations_on_project_and_endpoint:
|
||||
- index_alert_management_http_integrations_on_project_id
|
||||
analytics_cycle_analytics_group_stages:
|
||||
index_group_stages_on_group_id_group_value_stream_id_and_name:
|
||||
- index_analytics_ca_group_stages_on_group_id
|
||||
approval_project_rules_users:
|
||||
index_approval_project_rules_users_1:
|
||||
- index_approval_project_rules_users_on_approval_project_rule_id
|
||||
|
|
@ -111,9 +108,6 @@ members:
|
|||
merge_request_assignees:
|
||||
index_merge_request_assignees_on_merge_request_id_and_user_id:
|
||||
- index_merge_request_assignees_on_merge_request_id
|
||||
merge_request_metrics:
|
||||
index_mr_metrics_on_target_project_id_merged_at_nulls_last:
|
||||
- index_merge_request_metrics_on_target_project_id
|
||||
merge_requests:
|
||||
index_merge_requests_on_author_id_and_created_at:
|
||||
- index_merge_requests_on_author_id
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Requires `request` subject to be defined
|
||||
#
|
||||
# subject(:request) { get root_path }
|
||||
RSpec.shared_examples 'Base action controller' do
|
||||
describe 'security headers' do
|
||||
describe 'Cross-Origin-Opener-Policy' do
|
||||
it 'sets the header' do
|
||||
request
|
||||
|
||||
expect(response.headers['Cross-Origin-Opener-Policy']).to eq('same-origin')
|
||||
end
|
||||
|
||||
context 'when coop_header feature flag is disabled' do
|
||||
it 'does not set the header' do
|
||||
stub_feature_flags(coop_header: false)
|
||||
|
||||
request
|
||||
|
||||
expect(response.headers['Cross-Origin-Opener-Policy']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue