diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 692e41b2a7f..2d98644a9c5 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -072f01c9a020b2b49c222a338349555b2e807384 +b799d0b98f26e3de2fc408bf2b83eb86fb330858 diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 17812aed3ff..5b4c3d8b781 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -48,6 +48,16 @@ module FormHelper end end + def dropdown_max_select(data) + return data[:'max-select'] unless Feature.enabled?(:limit_reviewer_and_assignee_size) + + if data[:'max-select'] && data[:'max-select'] < MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + data[:'max-select'] + else + MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + end + end + def assignees_dropdown_options(issuable_type) dropdown_data = { toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data', @@ -165,7 +175,12 @@ module FormHelper new_options[:title] = _('Select reviewer(s)') new_options[:data][:'dropdown-header'] = _('Reviewer(s)') - new_options[:data].delete(:'max-select') + + if Feature.enabled?(:limit_reviewer_and_assignee_size) + new_options[:data][:'max-select'] = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + else + new_options[:data].delete(:'max-select') + end new_options end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index aab861648d6..3d789035b9a 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -41,6 +41,8 @@ class MergeRequest < ApplicationRecord 'Ci::CompareCodequalityReportsService' => ->(project) { true } }.freeze + MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 100 + belongs_to :target_project, class_name: "Project" belongs_to :source_project, class_name: "Project" belongs_to :merge_user, class_name: "User" @@ -263,6 +265,7 @@ class MergeRequest < ApplicationRecord validate :validate_branches, unless: [:allow_broken, :importing?, :closed_or_merged_without_fork?] validate :validate_fork, unless: :closed_or_merged_without_fork? validate :validate_target_project, on: :create + validate :validate_reviewer_and_assignee_size_length, unless: :importing? scope :by_source_or_target_branch, ->(branch_name) do where("source_branch = :branch OR target_branch = :branch", branch: branch_name) @@ -992,6 +995,20 @@ class MergeRequest < ApplicationRecord 'Source project is not a fork of the target project' end + def self.max_number_of_assignees_or_reviewers_message + # Assignees will be included in https://gitlab.com/gitlab-org/gitlab/-/issues/368936 + _("total must be less than or equal to %{size}") % { size: MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS } + end + + def validate_reviewer_and_assignee_size_length + # Assigness will be added in a subsequent MR https://gitlab.com/gitlab-org/gitlab/-/issues/368936 + return true unless Feature.enabled?(:limit_reviewer_and_assignee_size) + return true unless reviewers.size > MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + + errors.add :reviewers, + -> (_object, _data) { MergeRequest.max_number_of_assignees_or_reviewers_message } + end + def merge_ongoing? # While the MergeRequest is locked, it should present itself as 'merge ongoing'. # The unlocking process is handled by StuckMergeJobsWorker scheduled in Cron. diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 4074b1d1182..90edeacf633 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -88,8 +88,13 @@ module Notes return if quick_actions_service.commands_executed_count.to_i == 0 if update_params.present? - quick_actions_service.apply_updates(update_params, note) - note.commands_changes = update_params + if check_for_reviewer_validity(message, update_params) + quick_actions_service.apply_updates(update_params, note) + note.commands_changes = update_params + else + message = "Reviewers #{MergeRequest.max_number_of_assignees_or_reviewers_message}" + note.errors.add(:validation, message) + end end # We must add the error after we call #save because errors are reset @@ -109,6 +114,18 @@ module Notes } end + def check_for_reviewer_validity(message, update_params) + return true unless Feature.enabled?(:limit_reviewer_and_assignee_size) + + if update_params.key?(:reviewer_ids) + possible_reviewers = update_params[:reviewer_ids]&.uniq&.size + + return false if possible_reviewers > MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + end + + true + end + def track_event(note, user) track_note_creation_usage_for_issues(note) if note.for_issue? track_note_creation_usage_for_merge_requests(note) if note.for_merge_request? diff --git a/app/views/shared/issuable/_sidebar_reviewers.html.haml b/app/views/shared/issuable/_sidebar_reviewers.html.haml index ce252e74570..cd976b88304 100644 --- a/app/views/shared/issuable/_sidebar_reviewers.html.haml +++ b/app/views/shared/issuable/_sidebar_reviewers.html.haml @@ -36,7 +36,7 @@ - data[:multi_select] = true - data['dropdown-title'] = title - data['dropdown-header'] = dropdown_options[:data][:'dropdown-header'] - - data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select'] + - data['max-select'] = dropdown_max_select(dropdown_options[:data]) - options[:data].merge!(data) = render 'shared/issuable/sidebar_user_dropdown', diff --git a/config/environments/production.rb b/config/environments/production.rb index 943307bde44..202f6205c7f 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -65,8 +65,14 @@ Rails.application.configure do # Enable threaded mode # config.threadsafe! unless $rails_rake_task - # Send deprecation notices to registered listeners - config.active_support.deprecation = :notify + # Silence deprecation notices on production. + # See also config/initializers/00_deprecations.rb. + # + # Logging to `log/deprecation_json.log` can be enabled with + # `GITLAB_LOG_DEPRECATIONS=1`. + # + # See https://gitlab.com/gitlab-org/gitlab/-/issues/368379 + config.active_support.deprecation = :silence # Silence disallowed deprecations. config.active_support.disallowed_deprecation = :silence diff --git a/config/feature_flags/development/ci_retry_downstream_pipeline.yml b/config/feature_flags/development/limit_reviewer_and_assignee_size.yml similarity index 61% rename from config/feature_flags/development/ci_retry_downstream_pipeline.yml rename to config/feature_flags/development/limit_reviewer_and_assignee_size.yml index 69a2821c86e..b2a762cc583 100644 --- a/config/feature_flags/development/ci_retry_downstream_pipeline.yml +++ b/config/feature_flags/development/limit_reviewer_and_assignee_size.yml @@ -1,8 +1,8 @@ --- -name: ci_retry_downstream_pipeline -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76115 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347424 -milestone: '14.6' +name: limit_reviewer_and_assignee_size +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91406 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366485 +milestone: '15.3' type: development -group: group::pipeline authoring +group: group::code review default_enabled: false diff --git a/config/initializers/00_deprecations.rb b/config/initializers/00_deprecations.rb index c768cf8d414..9cba0a90541 100644 --- a/config/initializers/00_deprecations.rb +++ b/config/initializers/00_deprecations.rb @@ -10,7 +10,10 @@ # # In Rails 7 we will use `config.active_support.report_deprecations = false` # instead of this early return. -return if Rails.env.production? +if Rails.env.production? + ActiveSupport::Deprecation.silenced = true + return +end # Ban the following deprecation warnings and turn them into runtime errors # in `development` and `test` environments. diff --git a/config/initializers/0_log_deprecations.rb b/config/initializers/0_log_deprecations.rb index 6ba18ea1136..b3ef391053e 100644 --- a/config/initializers/0_log_deprecations.rb +++ b/config/initializers/0_log_deprecations.rb @@ -6,6 +6,18 @@ def log_deprecations? via_env_var.nil? ? Rails.env.development? : via_env_var end +# Add `:notify` behavior only if not already added. +# +# See https://github.com/Shopify/deprecation_toolkit/blob/1d0e6f5b99785806f715ce2e9a13dc50f453d1e1/lib/deprecation_toolkit.rb#L21 +def add_notify_behavior + notify = ActiveSupport::Deprecation::DEFAULT_BEHAVIORS.fetch(:notify) + behaviors = ActiveSupport::Deprecation.behavior + + return if behaviors.find { |behavior| behavior == notify } + + ActiveSupport::Deprecation.behavior = behaviors << notify +end + if log_deprecations? # Log deprecation warnings emitted through Kernel#warn, such as from gems or # the Ruby VM. @@ -19,6 +31,13 @@ if log_deprecations? Warning.process('', actions) + # We may have silenced deprecations warnings in 00_deprecations.rb on production. + # Unsilence them again. + ActiveSupport::Deprecation.silenced = false + + # If we want to consume emitted warnings from Rails we need to attach a notifier first. + add_notify_behavior + # Log deprecation warnings emitted from Rails (see ActiveSupport::Deprecation). ActiveSupport::Notifications.subscribe('deprecation.rails') do |name, start, finish, id, payload| Gitlab::DeprecationJsonLogger.info(message: payload[:message].strip, source: 'rails') diff --git a/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb b/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb new file mode 100644 index 00000000000..92ca0998bae --- /dev/null +++ b/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class ScheduleMigrateSharedVulnerabilityScanners < Gitlab::Database::Migration[2.0] + MIGRATION = "MigrateSharedVulnerabilityScanners" + TABLE_NAME = :vulnerability_occurrences + BATCH_COLUMN = :id + DELAY_INTERVAL = 5.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + BATCH_MIN_VALUE = 23658505 + BATCH_MAX_VALUE = 204428752 + + disable_ddl_transaction! + restrict_gitlab_migration gitlab_schema: :gitlab_main + + def up + queue_batched_background_migration( + MIGRATION, + TABLE_NAME, + BATCH_COLUMN, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + max_batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE, + batch_min_value: BATCH_MIN_VALUE, + batch_max_value: BATCH_MAX_VALUE + ) + end + + def down + delete_batched_background_migration(MIGRATION, TABLE_NAME, BATCH_COLUMN, []) + end +end diff --git a/db/schema_migrations/20220802112102 b/db/schema_migrations/20220802112102 new file mode 100644 index 00000000000..b37b29b5800 --- /dev/null +++ b/db/schema_migrations/20220802112102 @@ -0,0 +1 @@ +e5728437ae659e14906f5c0c36eea80d66e1ca056b037934b24d5a3f5489d8b7 \ No newline at end of file diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md index 8dfa832a103..2c315e8ec49 100644 --- a/doc/administration/auth/crowd.md +++ b/doc/administration/auth/crowd.md @@ -68,24 +68,24 @@ this provider also allows Crowd authentication for Git-over-https requests. application_password: 'YOUR_APP_PASSWORD' } } ``` -1. Change `CROWD_SERVER_URL` to the URL of your Crowd server. +1. Change `CROWD_SERVER_URL` to the [base URL of your Crowd server](https://confluence.atlassian.com/crowdkb/how-to-change-the-crowd-base-url-245827278.html). 1. Change `YOUR_APP_NAME` to the application name from Crowd applications page. 1. Change `YOUR_APP_PASSWORD` to the application password you've set. 1. Save the configuration file. -1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../restart_gitlab.md#installations-from-source) for the changes to take effect if you - installed GitLab via Omnibus or from source respectively. +1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) (Omnibus GitLab) or [restart](../restart_gitlab.md#installations-from-source) (source installations) for + the changes to take effect. On the sign in page there should now be a Crowd tab in the sign in form. ## Troubleshooting -If you see an error message like the one below when you sign in after Crowd authentication is configured, you may want to consult the Crowd administrator for the Crowd log file to know the exact cause: +### Error: "could not authorize you from Crowd because invalid credentials" -```plaintext -could not authorize you from Crowd because invalid credentials -``` +This error sometimes occurs when a user attempts to authenticate with Crowd. The +Crowd administrator should consult the Crowd log file to know the exact cause of +this error message. -Ensure the Crowd users who need to sign in to GitLab are authorized to the +Ensure the Crowd users who must sign in to GitLab are authorized to the [application](#configure-a-new-crowd-application) in the **Authorization** step. This could be verified by trying "Authentication test" for Crowd (as of 2.11). diff --git a/doc/administration/package_information/deprecation_policy.md b/doc/administration/package_information/deprecation_policy.md index 422339c014c..73059514e1c 100644 --- a/doc/administration/package_information/deprecation_policy.md +++ b/doc/administration/package_information/deprecation_policy.md @@ -4,7 +4,7 @@ group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Deprecation policy **(FREE SELF)** +# Omnibus GitLab deprecation policy **(FREE SELF)** The Omnibus GitLab packages come with number of different libraries and services which offers users plethora of configuration options. diff --git a/doc/development/database/avoiding_downtime_in_migrations.md b/doc/development/database/avoiding_downtime_in_migrations.md index bc264177324..7a3ae6bd9a0 100644 --- a/doc/development/database/avoiding_downtime_in_migrations.md +++ b/doc/development/database/avoiding_downtime_in_migrations.md @@ -142,9 +142,13 @@ the `remove_after` date has passed. ## Renaming Columns Renaming columns the normal way requires downtime as an application may continue -using the old column name during/after a database migration. To rename a column -without requiring downtime we need two migrations: a regular migration, and a -post-deployment migration. Both these migration can go in the same release. +to use the old column names during or after a database migration. To rename a column +without requiring downtime, we need two migrations: a regular migration and a +post-deployment migration. Both these migrations can go in the same release. + +NOTE: +It's not possible to rename columns with default values. For more details, see +[this merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52032#default-values). ### Step 1: Add The Regular Migration diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md index f547e5f146f..272db662a8c 100644 --- a/doc/user/compliance/compliance_report/index.md +++ b/doc/user/compliance/compliance_report/index.md @@ -105,17 +105,22 @@ To download the Chain of Custody report: 1. On the left sidebar, select **Security & Compliance > Compliance report**. 1. Select **List of all merge commits**. -### Commit-specific Chain of Custody Report +### Commit-specific Chain of Custody report > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267629) in GitLab 13.6. -You can generate a commit-specific Chain of Custody report for a given commit SHA. +Authenticated group owners can generate a commit-specific Chain of Custody report for a given commit SHA, either: -1. On the top bar, select **Menu > Groups** and find your group. -1. On the left sidebar, select **Security & Compliance > Compliance report**. -1. At the top of the compliance report, to the right of **List of all merge commits**, select the down arrow (**{chevron-lg-down}**). -1. Enter the merge commit SHA, and then select **Export commit custody report**. - SHA and then select **Export commit custody report**. +- Using the GitLab UI: + + 1. On the top bar, select **Menu > Groups** and find your group. + 1. On the left sidebar, select **Security & Compliance > Compliance report**. + 1. At the top of the compliance report, to the right of **List of all merge commits**, select the down arrow (**{chevron-lg-down}**). + 1. Enter the merge commit SHA, and then select **Export commit custody report**. + SHA and then select **Export commit custody report**. + +- Using a direct link: `https://gitlab.com/groups//-/security/merge_commit_reports.csv?commit_sha={optional_commit_sha}`, passing in an optional value to the + `commit_sha` query parameter. NOTE: The Chain of Custody report download is a CSV file, with a maximum size of 15 MB. diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index a442e909557..fef080d9e0e 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -99,7 +99,7 @@ After you set up your identity provider to work with GitLab, you must configure ![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_12.png) NOTE: -The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider, use a secure signature algorithm. +The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm. ### SSO enforcement @@ -191,7 +191,7 @@ with the notes below for consideration. NOTE: Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for [configuring SAML](#configure-gitlab), download the certificate and calculate -the SHA1 certificate fingerprint. +the SHA1 certificate fingerprint using this sample command: `openssl x509 -noout -fingerprint -sha1 -inform pem -in "GoogleIDPCertificate-domain.com.pem"`. The recommended attributes and claims settings are: diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md index 4563cfe5648..e1131d47276 100644 --- a/doc/user/profile/account/two_factor_authentication.md +++ b/doc/user/profile/account/two_factor_authentication.md @@ -59,15 +59,12 @@ To enable 2FA with a one-time password: 1. Select **Enable Two-factor Authentication**. 1. **On your device (usually your phone):** 1. Install a compatible application. For example: - - [Aegis](https://getaegis.app/) - - [Raivo OTP](https://apps.apple.com/us/app/raivo-otp/id1459042137#platform=iphone) - - [Authy](https://authy.com/) - - [Duo Mobile](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app) - - [LastPass Authenticator](https://lastpass.com/auth/) - - [Authenticator](https://mattrubin.me/authenticator/) - - [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en) - - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app) - - [SailOTP](https://openrepos.net/content/seiichiro0185/sailotp) + - Cloud-based (recommended because you can restore access if you lose the hardware device): + - [Authy](https://authy.com/) + - [Duo Mobile](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app) + - Other: + - [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en) + - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app) 1. In the application, add a new entry in one of two ways: - Scan the code displayed by GitLab with your device's camera to add the entry automatically. - Enter the details provided to add the entry manually. diff --git a/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb b/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb new file mode 100644 index 00000000000..6b6fa1cc848 --- /dev/null +++ b/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop: disable Style/Documentation + class MigrateSharedVulnerabilityScanners < BatchedMigrationJob + def perform + end + end + end +end + +# rubocop: disable Layout/LineLength +Gitlab::BackgroundMigration::MigrateSharedVulnerabilityScanners.prepend_mod_with("Gitlab::BackgroundMigration::MigrateSharedVulnerabilityScanners") diff --git a/lib/gitlab/ci/status/bridge/common.rb b/lib/gitlab/ci/status/bridge/common.rb index 263fd9d1052..d66d4b20bba 100644 --- a/lib/gitlab/ci/status/bridge/common.rb +++ b/lib/gitlab/ci/status/bridge/common.rb @@ -16,11 +16,7 @@ module Gitlab def details_path return unless can?(user, :read_pipeline, downstream_pipeline) - if Feature.enabled?(:ci_retry_downstream_pipeline, subject.project) - project_job_path(subject.project, subject) - else - project_pipeline_path(downstream_project, downstream_pipeline) - end + project_pipeline_path(downstream_project, downstream_pipeline) end def has_action? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d5dfa3c6d73..33677c2bd47 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -47226,6 +47226,9 @@ msgstr "" msgid "toggle collapse" msgstr "" +msgid "total must be less than or equal to %{size}" +msgstr "" + msgid "triggered" msgstr "" diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb index 667dbc03fc3..d1cfdfbc16c 100644 --- a/qa/qa/resource/api_fabricator.rb +++ b/qa/qa/resource/api_fabricator.rb @@ -74,6 +74,13 @@ module QA response.code == HTTP_STATUS_OK end + # Parameters included in the query URL + # + # @return [Hash] + def query_parameters + @query_parameters ||= {} + end + private def resource_web_url(resource) @@ -87,7 +94,8 @@ module QA end def api_get_from(get_path) - request = Runtime::API::Request.new(api_client, get_path) + path = "#{get_path}#{query_parameters_to_string}" + request = Runtime::API::Request.new(api_client, path) response = get(request.url) if response.code == HTTP_STATUS_SERVER_ERROR @@ -101,6 +109,15 @@ module QA response end + # Query parameters formatted as `?key1=value1&key2=value2...` + # + # @return [String] + def query_parameters_to_string + query_parameters.each_with_object([]) do |(k, v), arr| + arr << "#{k}=#{v}" + end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank + end + def api_post process_api_response(api_post_to(api_post_path, api_post_body)) end diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb index 8a830303b56..60f6cbdfc51 100644 --- a/qa/qa/resource/group.rb +++ b/qa/qa/resource/group.rb @@ -61,6 +61,13 @@ module QA "/groups/#{CGI.escape(determine_full_path)}" end + # Parameters included in the query URL + # + # @return [Hash] + def query_parameters + super.merge({ with_projects: false }) + end + def api_post_body { parent_id: sandbox.id, diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb index 8e7527bccd4..12ecce1ce9a 100644 --- a/qa/qa/resource/sandbox.rb +++ b/qa/qa/resource/sandbox.rb @@ -57,6 +57,13 @@ module QA "/groups/#{path}" end + # Parameters included in the query URL + # + # @return [Hash] + def query_parameters + super.merge({ with_projects: false }) + end + def api_post_body { path: path, diff --git a/spec/helpers/form_helper_spec.rb b/spec/helpers/form_helper_spec.rb index c9c8c6b13b6..7c6a2b58ef9 100644 --- a/spec/helpers/form_helper_spec.rb +++ b/spec/helpers/form_helper_spec.rb @@ -3,6 +3,82 @@ require 'spec_helper' RSpec.describe FormHelper do + include Devise::Test::ControllerHelpers + + describe '#dropdown_max_select' do + context "with the :limit_reviewer_and_assignee_size feature flag on" do + it 'correctly returns the max amount of reviewers or assignees to allow' do + max = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS + + expect(helper.dropdown_max_select({})) + .to eq(max) + expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 })) + .to eq(5) + expect(helper.dropdown_max_select({ 'max-select'.to_sym => max + 5 })) + .to eq(max) + end + end + + context "with the :limit_reviewer_and_assignee_size feature flag off" do + before do + stub_feature_flags(limit_reviewer_and_assignee_size: false) + end + + it 'correctly returns the max amount of reviewers or assignees to allow' do + expect(helper.dropdown_max_select({})) + .to eq(nil) + expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 })) + .to eq(5) + expect(helper.dropdown_max_select({ 'max-select'.to_sym => 120 })) + .to eq(120) + end + end + end + + describe '#reviewers_dropdown_options' do + let(:merge_request) { build(:merge_request) } + + context "with the :limit_reviewer_and_assignee_size feature flag on" do + context "with multiple reviewers" do + it 'correctly returns the max amount of reviewers or assignees to allow' do + allow(helper).to receive(:merge_request_supports_multiple_reviewers?).and_return(true) + + expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select']) + .to eq(MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS) + end + end + + context "with only 1 reviewer" do + it 'correctly returns the max amount of reviewers or assignees to allow' do + expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select']) + .to eq(1) + end + end + end + + context "with the :limit_reviewer_and_assignee_size feature flag off" do + before do + stub_feature_flags(limit_reviewer_and_assignee_size: false) + end + + context "with multiple reviewers" do + it 'correctly returns the max amount of reviewers or assignees to allow' do + allow(helper).to receive(:merge_request_supports_multiple_reviewers?).and_return(true) + + expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select']) + .to eq(nil) + end + end + + context "with only 1 reviewer" do + it 'correctly returns the max amount of reviewers or assignees to allow' do + expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select']) + .to eq(1) + end + end + end + end + describe 'form_errors' do it 'returns nil when model has no errors' do model = double(errors: []) diff --git a/spec/initializers/0_log_deprecations_spec.rb b/spec/initializers/0_log_deprecations_spec.rb index f5065126eaf..d34be32f7d0 100644 --- a/spec/initializers/0_log_deprecations_spec.rb +++ b/spec/initializers/0_log_deprecations_spec.rb @@ -11,6 +11,15 @@ RSpec.describe '0_log_deprecations' do load Rails.root.join('config/initializers/0_log_deprecations.rb') end + def with_deprecation_behavior + behavior = ActiveSupport::Deprecation.behavior + ActiveSupport::Deprecation.behavior = deprecation_behavior + yield + ensure + ActiveSupport::Deprecation.behavior = behavior + end + + let(:deprecation_behavior) { :stderr } let(:env_var) { '1' } before do @@ -24,19 +33,39 @@ RSpec.describe '0_log_deprecations' do end around do |example| - # reset state changed by initializer - Warning.clear(&example) + with_deprecation_behavior do + # reset state changed by initializer + Warning.clear(&example) + end end describe 'Ruby deprecations' do - context 'when catching deprecations through Kernel#warn' do - it 'also logs them to deprecation logger' do + shared_examples 'deprecation logger' do + it 'logs them to deprecation logger once and to stderr' do expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( message: 'ABC gem is deprecated', source: 'ruby' ) - expect { warn('ABC gem is deprecated') }.to output.to_stderr + expect { subject }.to output.to_stderr + end + end + + context 'when catching deprecations through Kernel#warn' do + subject { warn('ABC gem is deprecated') } + + include_examples 'deprecation logger' + + context 'with non-notify deprecation behavior' do + let(:deprecation_behavior) { :silence } + + include_examples 'deprecation logger' + end + + context 'with notify deprecation behavior' do + let(:deprecation_behavior) { :notify } + + include_examples 'deprecation logger' end end @@ -60,13 +89,40 @@ RSpec.describe '0_log_deprecations' do end describe 'Rails deprecations' do - it 'logs them to deprecation logger' do - expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( - message: match(/^DEPRECATION WARNING: ABC will be removed/), - source: 'rails' - ) + subject { ActiveSupport::Deprecation.warn('ABC will be removed') } - expect { ActiveSupport::Deprecation.warn('ABC will be removed') }.to output.to_stderr + shared_examples 'deprecation logger' do + it 'logs them to deprecation logger once' do + expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( + message: match(/^DEPRECATION WARNING: ABC will be removed/), + source: 'rails' + ) + + subject + end + end + + context 'with non-notify deprecation behavior' do + let(:deprecation_behavior) { :silence } + + include_examples 'deprecation logger' + end + + context 'with notify deprecation behavior' do + let(:deprecation_behavior) { :notify } + + include_examples 'deprecation logger' + end + + context 'when deprecations were silenced' do + around do |example| + silenced = ActiveSupport::Deprecation.silenced + ActiveSupport::Deprecation.silenced = true + example.run + ActiveSupport::Deprecation.silenced = silenced + end + + include_examples 'deprecation logger' end context 'when disabled via environment' do diff --git a/spec/lib/gitlab/ci/status/bridge/common_spec.rb b/spec/lib/gitlab/ci/status/bridge/common_spec.rb index 30e6ad234a0..37524afc83d 100644 --- a/spec/lib/gitlab/ci/status/bridge/common_spec.rb +++ b/spec/lib/gitlab/ci/status/bridge/common_spec.rb @@ -29,15 +29,7 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Common do end it { expect(subject).to have_details } - it { expect(subject.details_path).to include "jobs/#{bridge.id}" } - - context 'with ci_retry_downstream_pipeline ff disabled' do - before do - stub_feature_flags(ci_retry_downstream_pipeline: false) - end - - it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" } - end + it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" } end context 'when user does not have access to read downstream pipeline' do diff --git a/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb b/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb new file mode 100644 index 00000000000..f00d6568b67 --- /dev/null +++ b/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" + +require_migration! + +RSpec.describe ScheduleMigrateSharedVulnerabilityScanners, :migration do + describe "#up" do + before do + migrate! + end + + it "schedules" do + expect(described_class::MIGRATION).to have_scheduled_batched_migration( + table_name: described_class::TABLE_NAME, + column_name: described_class::BATCH_COLUMN, + interval: described_class::DELAY_INTERVAL, + batch_size: described_class::BATCH_SIZE, + max_batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE, + gitlab_schema: :gitlab_main + ) + end + + describe "ID range" do + let(:expected_range) do + { min_value: described_class::BATCH_MIN_VALUE, + max_value: described_class::BATCH_MAX_VALUE } + end + + subject do + Gitlab::Database::BackgroundMigration::BatchedMigration + .for_configuration(:gitlab_main, + described_class::MIGRATION, + described_class::TABLE_NAME, + described_class::BATCH_COLUMN, + []) + end + + it "is set" do + # The `have_scheduled_batched_migration` matcher accepts the + # `batch_min_value` and `batch_max_value` keywords. However the respective + # column names are `min_value` and `max_value`. Hence the matcher cannot + # be used in this case, as it asserts the wrong attributes. + expect(subject).to all(have_attributes(expected_range)) + end + end + end + + describe '#down' do + before do + schema_migrate_down! + end + + it "deletes" do + expect(described_class::MIGRATION).not_to have_scheduled_batched_migration + end + end +end