diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-24 21:08:03 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-24 21:08:03 +0000 |
commit | 0b5e5c78a9d7acbf773d7ba5fd5c2ce9b6ffdb52 (patch) | |
tree | 64e092630aca6e42462003414519f22266dcbc25 | |
parent | d48b87d4675d6b8b56dd9b40afa9eb2dce32ad3b (diff) | |
download | gitlab-ce-0b5e5c78a9d7acbf773d7ba5fd5c2ce9b6ffdb52.tar.gz |
Add latest changes from gitlab-org/gitlab@master
37 files changed, 306 insertions, 118 deletions
diff --git a/.gitlab/merge_request_templates/Revert To Resolve Incident.md b/.gitlab/merge_request_templates/Revert To Resolve Incident.md index 4e77846575a..c1980d70768 100644 --- a/.gitlab/merge_request_templates/Revert To Resolve Incident.md +++ b/.gitlab/merge_request_templates/Revert To Resolve Incident.md @@ -12,6 +12,7 @@ - [ ] Create an issue to reinstate the merge request and assign it to the author of the reverted merge request. - [ ] If the revert is to resolve a [broken 'master' incident](https://about.gitlab.com/handbook/engineering/workflow/#broken-master), please read through the [Responsibilities of the Broken `master` resolution DRI](https://about.gitlab.com/handbook/engineering/workflow/#responsibilities-of-the-resolution-dri). +- [ ] If the revert involves a database migration, please read through [Deleting existing migrations](https://docs.gitlab.com/ee/development/database/deleting_migrations.html). - [ ] Add the appropriate labels **before** the MR is created. We can skip CI/CD jobs only if the labels are added **before** the CI/CD pipeline is created. ### Milestone info diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 384ce8b6308..5f0bd4e7c8a 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -fb7ac6faa5b8e8cad4a66e597665eb12d398b84d +770edd2d7f8324da646df478eb271544393316df diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue index 10531e950f9..92ff06cd579 100644 --- a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue +++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue @@ -149,6 +149,7 @@ export default { :key="branch" is-check-item :is-checked="selectedRevision === branch" + data-testid="branches-dropdown-item" @click="onClick(branch)" > {{ branch }} @@ -161,6 +162,7 @@ export default { :key="tag" is-check-item :is-checked="selectedRevision === tag" + data-testid="tags-dropdown-item" @click="onClick(tag)" > {{ tag }} diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index f9d522f93bb..420ca6a2286 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -133,7 +133,10 @@ class RegistrationsController < Devise::RegistrationsController # after user confirms and comes back, he will be redirected store_location_for(:redirect, after_sign_up_path) - return identity_verification_redirect_path if custom_confirmation_enabled? + if custom_confirmation_enabled? + session[:verification_user_id] = resource.id # This is needed to find the user on the identity verification page + return identity_verification_redirect_path + end Gitlab::Tracking.event(self.class.name, 'render', user: resource) users_almost_there_path(email: resource.email) @@ -220,7 +223,7 @@ class RegistrationsController < Devise::RegistrationsController def resource @resource ||= Users::RegistrationsBuildService - .new(current_user, sign_up_params.merge({ skip_confirmation: registered_with_invite_email?, + .new(current_user, sign_up_params.merge({ skip_confirmation: skip_confirmation?, preferred_language: preferred_language })) .execute end @@ -229,6 +232,10 @@ class RegistrationsController < Devise::RegistrationsController @devise_mapping ||= Devise.mappings[:user] end + def skip_confirmation? + registered_with_invite_email? + end + def registered_with_invite_email? invite_email = session.delete(:invite_email) diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb index 1724e11a6f1..a9b7ad7a3e5 100644 --- a/app/helpers/registrations_helper.rb +++ b/app/helpers/registrations_helper.rb @@ -14,6 +14,10 @@ module RegistrationsHelper def arkose_labs_challenge_enabled? false end + + def signup_box_template + 'devise/shared/signup_box' + end end RegistrationsHelper.prepend_mod_with('RegistrationsHelper') diff --git a/app/mailers/emails/work_items.rb b/app/mailers/emails/work_items.rb new file mode 100644 index 00000000000..fe669fdbedc --- /dev/null +++ b/app/mailers/emails/work_items.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Emails + module WorkItems + def import_work_items_csv_email(user_id, project_id, results) + @user = User.find(user_id) + @project = Project.find(project_id) + @results = results + + email_with_layout( + to: @user.notification_email_for(@project), + subject: subject('Imported work items')) + end + end +end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 28ef6d8d6c6..0465887cdc6 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -25,6 +25,7 @@ class Notify < ApplicationMailer include Emails::AdminNotification include Emails::IdentityVerification include Emails::Imports + include Emails::WorkItems helper TimeboxesHelper helper MergeRequestsHelper diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb index 7ed594bf571..0d98c5a176a 100644 --- a/app/mailers/previews/notify_preview.rb +++ b/app/mailers/previews/notify_preview.rb @@ -84,6 +84,10 @@ class NotifyPreview < ActionMailer::Preview Notify.import_issues_csv_email(user.id, project.id, { success: 3, errors: [5, 6, 7], valid_file: true }) end + def import_work_items_csv_email + Notify.import_work_items_csv_email(user.id, project.id, { success: 4, error_lines: [2, 3, 4], parse_error: false }) + end + def issues_csv_email Notify.issues_csv_email(user, project, '1997,Ford,E350', { truncated: false, rows_expected: 3, rows_written: 3 }).message end diff --git a/app/services/work_items/import_csv_service.rb b/app/services/work_items/import_csv_service.rb index e93905b8ca5..4c00d14e9f4 100644 --- a/app/services/work_items/import_csv_service.rb +++ b/app/services/work_items/import_csv_service.rb @@ -6,6 +6,10 @@ module WorkItems NotAvailableError = StandardError.new('This feature is currently behind a feature flag and it is not available.') + def self.required_headers + %w[title].freeze + end + def execute raise NotAvailableError if ::Feature.disabled?(:import_export_work_items_csv, project) @@ -13,7 +17,7 @@ module WorkItems end def email_results_to_user - # todo as part of https://gitlab.com/gitlab-org/gitlab/-/issues/379153 + Notify.import_work_items_csv_email(user.id, project.id, results).deliver_later end private @@ -36,15 +40,13 @@ module WorkItems override :validate_headers_presence! def validate_headers_presence!(headers) - headers.downcase! if headers + required_headers = self.class.required_headers + + headers.downcase! return if headers && required_headers.all? { |rh| headers.include?(rh) } required_headers_message = "Required headers are missing. Required headers are #{required_headers.join(', ')}" raise CSV::MalformedCSVError.new(required_headers_message, 1) end - - def required_headers - %w[title].freeze - end end end diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 8a960602536..3bd7147f195 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -8,7 +8,7 @@ = render "layouts/google_tag_manager_body" .signup-page - = render 'devise/shared/signup_box', + = render signup_box_template, url: registration_path(resource_name, glm_tracking_params.to_hash), button_text: _('Register'), borderless: Feature.enabled?(:restyle_login_page, @project), diff --git a/app/views/notify/import_work_items_csv_email.html.haml b/app/views/notify/import_work_items_csv_email.html.haml new file mode 100644 index 00000000000..425cf42fbd0 --- /dev/null +++ b/app/views/notify/import_work_items_csv_email.html.haml @@ -0,0 +1,18 @@ +- text_style = 'font-size:16px; text-align:center; line-height:30px;' + +%p{ style: text_style } + - project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none;") + = s_('Notify|Your CSV import of work items for project %{project_link} has been completed.').html_safe % { project_link: project_link } + +%p{ style: text_style } + - work_items = n_('%d work item', '%d work items', @results[:success]) % @results[:success] + = s_('Notify|%{work_items} imported.') % { work_items: work_items } + +- if @results[:error_lines].present? + %p{ style: text_style } + = s_('Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check that these lines have the following fields: %{required_headers}.') % { singular_or_plural_line: n_('line', 'lines', @results[:error_lines].size), required_headers: WorkItems::ImportCsvService.required_headers.join(', '), + error_lines: @results[:error_lines].join(', ') } + +- if @results[:parse_error] + %p{ style: text_style } + = s_('Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values.') diff --git a/app/views/notify/import_work_items_csv_email.text.erb b/app/views/notify/import_work_items_csv_email.text.erb new file mode 100644 index 00000000000..5793131af89 --- /dev/null +++ b/app/views/notify/import_work_items_csv_email.text.erb @@ -0,0 +1,11 @@ +Your CSV import for project <%= @project.full_name %> (<%= project_url(@project) %>) has been completed. + +<%= pluralize(@results[:success], 'work item') %> imported. + +<% if @results[:error_lines].present? %> +Errors found on line <%= 'number'.pluralize(@results[:error_lines].size) %>: <%= @results[:error_lines].join(', ') %>. Please check that these lines have the following fields: <%= WorkItems::ImportCsvService.required_headers.join(', ') %>. +<% end %> + +<% if @results[:parse_error] %> +Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values. +<% end %> diff --git a/db/docs/postgres_async_foreign_key_validations.yml b/db/docs/postgres_async_foreign_key_validations.yml index 0b9608a3ace..587dd7d69a2 100644 --- a/db/docs/postgres_async_foreign_key_validations.yml +++ b/db/docs/postgres_async_foreign_key_validations.yml @@ -1,7 +1,7 @@ --- table_name: postgres_async_foreign_key_validations classes: -- Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValidation +- Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation feature_categories: - database description: >- diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index 9d15d4bbb46..28428f1eecc 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -218,7 +218,7 @@ configuration option in `gitlab.yml`. These metrics are served from the | `geo_lfs_objects_registry` | Gauge | 14.6 | Number of LFS objects in the registry | `url` | | `geo_lfs_objects_verified` | Gauge | 14.6 | Number of LFS objects verified on secondary | `url` | | `geo_lfs_objects_verification_failed` | Gauge | 14.6 | Number of LFS objects' verifications failed on secondary | `url` | -| `geo_lfs_objects_verification_total` | Gauge | 14.6 | Number of LFS objects' verifications tried on secondary | `url` |LFS objects failed to sync on secondary | `url` | +| `geo_lfs_objects_verification_total` | Gauge | 14.6 | Number of LFS objects' verifications tried on secondary | `url` | | `geo_attachments` | Gauge | 10.2 | Total number of file attachments available on primary | `url` | | `geo_attachments_synced` | Gauge | 10.2 | Number of attachments synced on secondary | `url` | | `geo_attachments_failed` | Gauge | 10.2 | Number of attachments failed to sync on secondary | `url` | diff --git a/doc/development/database/add_foreign_key_to_existing_column.md b/doc/development/database/add_foreign_key_to_existing_column.md index a64fc047a57..823fb49a9ab 100644 --- a/doc/development/database/add_foreign_key_to_existing_column.md +++ b/doc/development/database/add_foreign_key_to_existing_column.md @@ -252,7 +252,7 @@ validating a foreign key: 1. Enable the feature flag by running `Feature.enable(:database_async_foreign_key_validation)` in the Rails console. 1. Run `bundle exec rails db:migrate` so that it creates an entry in the async validation table. -1. Run `bundle exec rails gitlab:db:execute_async_fk_validations:all` so that the FK is validated +1. Run `bundle exec rails gitlab:db:validate_async_constraints:all` so that the FK is validated asynchronously on all databases. 1. To verify the foreign key, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md index 787b0062017..1d71f6ac511 100644 --- a/doc/user/clusters/agent/gitops.md +++ b/doc/user/clusters/agent/gitops.md @@ -12,6 +12,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/346585) to make the `id` attribute optional in GitLab 15.7. > - Specifying a branch, tag, or commit reference to fetch the Kubernetes manifest files [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4516) in GitLab 15.7. +NOTE: +From GitLab 15.10, you should use [Flux](gitops/flux.md) for GitOps. For more information, see +[this announcement blog post](https://about.gitlab.com/blog/2023/02/08/why-did-we-choose-to-integrate-fluxcd-with-gitlab/). + With GitOps, you can manage containerized clusters and applications from a Git repository that: - Is the single source of truth of your system. diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 8f4855a7f93..0d84a617808 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -12,6 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the GitLab agent became available on GitLab.com. > - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5. > - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab agent for Kubernetes" in GitLab 14.6. +> - Flux [recommended](https://gitlab.com/gitlab-org/gitlab/-/issues/357947#note_1253489000) as GitOps solution in GitLab 15.10. You can connect your Kubernetes cluster with GitLab to deploy, manage, and monitor your cloud-native solutions. @@ -33,20 +34,7 @@ You can choose from two primary workflows. The GitOps workflow is recommended. ### GitOps workflow -In a [**GitOps** workflow](gitops.md): - -- You keep your Kubernetes manifests in GitLab. -- You install a GitLab agent in your cluster. -- Any time you update your manifests, the agent updates the cluster. -- The cluster automatically cleans up unexpected changes. It uses - [server-side applies](https://kubernetes.io/docs/reference/using-api/server-side-apply/) - to fix any configuration inconsistencies that third parties introduce. - -This workflow is fully driven with Git and is considered **pull-based**, -because the cluster is pulling updates from your GitLab repository. - -GitLab recommends this workflow. We are actively investing in this workflow -so we can provide a first-class experience. +You should use Flux for GitOps. To get started, see the GitLab [Flux documentation](../../../user/clusters/agent/gitops/flux.md). ### GitLab CI/CD workflow diff --git a/lib/gitlab/database/async_foreign_keys.rb b/lib/gitlab/database/async_constraints.rb index 115ae9ba2e8..c4e05a88430 100644 --- a/lib/gitlab/database/async_foreign_keys.rb +++ b/lib/gitlab/database/async_constraints.rb @@ -2,11 +2,11 @@ module Gitlab module Database - module AsyncForeignKeys + module AsyncConstraints DEFAULT_ENTRIES_PER_INVOCATION = 2 def self.validate_pending_entries!(how_many: DEFAULT_ENTRIES_PER_INVOCATION) - PostgresAsyncForeignKeyValidation.ordered.limit(how_many).each do |record| + PostgresAsyncConstraintValidation.ordered.limit(how_many).each do |record| ForeignKeyValidator.new(record).perform end end diff --git a/lib/gitlab/database/async_foreign_keys/foreign_key_validator.rb b/lib/gitlab/database/async_constraints/foreign_key_validator.rb index 1eb8588405d..a535a86913c 100644 --- a/lib/gitlab/database/async_foreign_keys/foreign_key_validator.rb +++ b/lib/gitlab/database/async_constraints/foreign_key_validator.rb @@ -2,7 +2,7 @@ module Gitlab module Database - module AsyncForeignKeys + module AsyncConstraints class ForeignKeyValidator include AsyncDdlExclusiveLeaseGuard diff --git a/lib/gitlab/database/async_foreign_keys/migration_helpers.rb b/lib/gitlab/database/async_constraints/migration_helpers.rb index eb33b9dc1f6..f51bb015c88 100644 --- a/lib/gitlab/database/async_foreign_keys/migration_helpers.rb +++ b/lib/gitlab/database/async_constraints/migration_helpers.rb @@ -2,17 +2,17 @@ module Gitlab module Database - module AsyncForeignKeys + module AsyncConstraints module MigrationHelpers # Prepares a foreign key for asynchronous validation. # - # Stores the FK information in the postgres_async_foreign_key_validations + # Stores the FK information in the postgres_async_constraint_validations # table to be executed later. # def prepare_async_foreign_key_validation(table_name, column_name = nil, name: nil) Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode! - return unless async_fk_validation_available? + return unless async_constraint_validation_available? fk_name = name || concurrent_foreign_key_name(table_name, column_name) @@ -20,7 +20,7 @@ module Gitlab raise missing_schema_object_message(table_name, "foreign key", fk_name) end - async_validation = PostgresAsyncForeignKeyValidation + async_validation = PostgresAsyncConstraintValidation .find_or_create_by!(name: fk_name, table_name: table_name) Gitlab::AppLogger.info( @@ -34,11 +34,11 @@ module Gitlab def unprepare_async_foreign_key_validation(table_name, column_name = nil, name: nil) Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode! - return unless async_fk_validation_available? + return unless async_constraint_validation_available? fk_name = name || concurrent_foreign_key_name(table_name, column_name) - PostgresAsyncForeignKeyValidation + PostgresAsyncConstraintValidation .find_by(name: fk_name, table_name: table_name) .try(&:destroy!) end @@ -46,7 +46,7 @@ module Gitlab def prepare_partitioned_async_foreign_key_validation(table_name, column_name = nil, name: nil) Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode! - return unless async_fk_validation_available? + return unless async_constraint_validation_available? Gitlab::Database::PostgresPartitionedTable.each_partition(table_name) do |partition| prepare_async_foreign_key_validation(partition.identifier, column_name, name: name) @@ -56,7 +56,7 @@ module Gitlab def unprepare_partitioned_async_foreign_key_validation(table_name, column_name = nil, name: nil) Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode! - return unless async_fk_validation_available? + return unless async_constraint_validation_available? Gitlab::Database::PostgresPartitionedTable.each_partition(table_name) do |partition| unprepare_async_foreign_key_validation(partition.identifier, column_name, name: name) @@ -65,8 +65,8 @@ module Gitlab private - def async_fk_validation_available? - connection.table_exists?(:postgres_async_foreign_key_validations) + def async_constraint_validation_available? + PostgresAsyncConstraintValidation.table_available? end end end diff --git a/lib/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb b/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb index fb01c1e2025..ae996600f7c 100644 --- a/lib/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb +++ b/lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb @@ -2,8 +2,8 @@ module Gitlab module Database - module AsyncForeignKeys - class PostgresAsyncForeignKeyValidation < SharedModel + module AsyncConstraints + class PostgresAsyncConstraintValidation < SharedModel include QueueErrorHandlingConcern self.table_name = 'postgres_async_foreign_key_validations' @@ -15,6 +15,10 @@ module Gitlab validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH } scope :ordered, -> { order(attempts: :asc, id: :asc) } + + def self.table_available? + connection.table_exists?(table_name) + end end end end diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 08122875abc..271da2edbc9 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -14,7 +14,7 @@ module Gitlab include DynamicModelHelpers include RenameTableHelpers include AsyncIndexes::MigrationHelpers - include AsyncForeignKeys::MigrationHelpers + include AsyncConstraints::MigrationHelpers def define_batchable_model(table_name, connection: self.connection) super(table_name, connection: connection) diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb index 78de7161a0f..739e573b6c4 100644 --- a/lib/gitlab/database/reindexing.rb +++ b/lib/gitlab/database/reindexing.rb @@ -28,7 +28,7 @@ module Gitlab # Hack: Before we do actual reindexing work, create async indexes Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops) Gitlab::Database::AsyncIndexes.drop_pending_indexes! - Gitlab::Database::AsyncForeignKeys.validate_pending_entries! if Feature.enabled?(:database_async_foreign_key_validation, type: :ops) + Gitlab::Database::AsyncConstraints.validate_pending_entries! if Feature.enabled?(:database_async_foreign_key_validation, type: :ops) automatic_reindexing end diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake index 14d66816551..5a67e6cfa8c 100644 --- a/lib/tasks/gitlab/db.rake +++ b/lib/tasks/gitlab/db.rake @@ -300,7 +300,7 @@ namespace :gitlab do end end - namespace :execute_async_fk_validations do + namespace :validate_async_constraints do each_database(databases) do |database_name| task database_name, [:pick] => :environment do |_, args| args.with_defaults(pick: 2) @@ -315,7 +315,7 @@ namespace :gitlab do end Gitlab::Database::EachDatabase.each_database_connection(only: database_name) do - Gitlab::Database::AsyncForeignKeys.validate_pending_entries!(how_many: args[:pick].to_i) + Gitlab::Database::AsyncConstraints.validate_pending_entries!(how_many: args[:pick].to_i) end end end @@ -325,7 +325,7 @@ namespace :gitlab do args.with_defaults(pick: default_pick) each_database(databases) do |database_name| - Rake::Task["gitlab:db:execute_async_fk_validations:#{database_name}"].invoke(args[:pick]) + Rake::Task["gitlab:db:validate_async_constraints:#{database_name}"].invoke(args[:pick]) end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 800abad7e33..b1c9c318e54 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -466,6 +466,11 @@ msgid_plural "%d warnings found:" msgstr[0] "" msgstr[1] "" +msgid "%d work item" +msgid_plural "%d work items" +msgstr[0] "" +msgstr[1] "" + msgid "%s additional commit has been omitted to prevent performance issues." msgid_plural "%s additional commits have been omitted to prevent performance issues." msgstr[0] "" @@ -29011,6 +29016,9 @@ msgstr "" msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}" msgstr "" +msgid "Notify|%{work_items} imported." +msgstr "" + msgid "Notify|A new GPG key was added to your account:" msgstr "" @@ -29059,6 +29067,9 @@ msgstr "" msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title." msgstr "" +msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check that these lines have the following fields: %{required_headers}." +msgstr "" + msgid "Notify|Fingerprint: %{fingerprint}" msgstr "" @@ -29197,6 +29208,9 @@ msgstr "" msgid "Notify|Your CSV import for project %{project_link} has been completed." msgstr "" +msgid "Notify|Your CSV import of work items for project %{project_link} has been completed." +msgstr "" + msgid "Notify|Your account has been created successfully." msgstr "" diff --git a/spec/factories/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb b/spec/factories/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb index a61b5cde7a0..23f4049f1cb 100644 --- a/spec/factories/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb +++ b/spec/factories/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true FactoryBot.define do - factory :postgres_async_foreign_key_validation, - class: 'Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValidation' do + factory :postgres_async_constraint_validation, + class: 'Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation' do sequence(:name) { |n| "fk_users_id_#{n}" } table_name { "users" } end diff --git a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb index 6e6c2cddfbf..06276d2a933 100644 --- a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb @@ -52,7 +52,7 @@ RSpec.describe 'Merge request > User sees discussions navigation', :js, feature_ expect(page).to have_selector(second_discussion_selector, obscured: false) end - it 'navigates through active threads' do + it 'navigates through active threads', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391912' do goto_next_thread goto_next_thread expect(page).to have_selector(second_discussion_selector, obscured: false) diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js index db4a1158996..50779063d6b 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js @@ -2,6 +2,7 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; +import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK } from '~/lib/utils/http_status'; @@ -38,6 +39,10 @@ describe('RevisionDropdown component', () => { const findGlDropdown = () => wrapper.findComponent(GlDropdown); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); + const findBranchesDropdownItem = () => + wrapper.findAllComponents('[data-testid="branches-dropdown-item"]'); + const findTagsDropdownItem = () => + wrapper.findAllComponents('[data-testid="tags-dropdown-item"]'); it('sets hidden input', () => { createComponent(); @@ -57,17 +62,29 @@ describe('RevisionDropdown component', () => { createComponent(); - await axios.waitForAll(); - expect(wrapper.vm.branches).toEqual(Branches); - expect(wrapper.vm.tags).toEqual(Tags); + expect(findBranchesDropdownItem()).toHaveLength(0); + expect(findTagsDropdownItem()).toHaveLength(0); + + await waitForPromises(); + + expect(findBranchesDropdownItem()).toHaveLength(Branches.length); + expect(findTagsDropdownItem()).toHaveLength(Tags.length); + + Branches.forEach((branch, index) => { + expect(findBranchesDropdownItem().at(index).text()).toBe(branch); + }); + + Tags.forEach((tag, index) => { + expect(findTagsDropdownItem().at(index).text()).toBe(tag); + }); }); it('shows flash message on error', async () => { axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); createComponent(); + await waitForPromises(); - await wrapper.vm.fetchBranchesAndTags(); expect(createAlert).toHaveBeenCalled(); }); @@ -83,7 +100,7 @@ describe('RevisionDropdown component', () => { refsProjectPath: newRefsProjectPath, }); - await axios.waitForAll(); + await waitForPromises(); expect(axios.get).toHaveBeenLastCalledWith(newRefsProjectPath); }); @@ -92,8 +109,8 @@ describe('RevisionDropdown component', () => { axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); createComponent(); + await waitForPromises(); - await wrapper.vm.searchBranchesAndTags(); expect(createAlert).toHaveBeenCalled(); }); @@ -108,7 +125,7 @@ describe('RevisionDropdown component', () => { const mockSearchTerm = 'foobar'; createComponent(); findSearchBox().vm.$emit('input', mockSearchTerm); - await axios.waitForAll(); + await waitForPromises(); expect(axios.get).toHaveBeenCalledWith( defaultProps.refsProjectPath, @@ -141,8 +158,14 @@ describe('RevisionDropdown component', () => { }); it('emits `selectRevision` event when another revision is selected', async () => { + jest.spyOn(axios, 'get').mockResolvedValue({ + data: { + Branches: ['some-branch'], + Tags: [], + }, + }); + createComponent(); - wrapper.vm.branches = ['some-branch']; await nextTick(); findGlDropdown().findAllComponents(GlDropdownItem).at(0).vm.$emit('click'); diff --git a/spec/lib/gitlab/database/async_foreign_keys/foreign_key_validator_spec.rb b/spec/lib/gitlab/database/async_constraints/foreign_key_validator_spec.rb index 90137e259f5..15474912d9a 100644 --- a/spec/lib/gitlab/database/async_foreign_keys/foreign_key_validator_spec.rb +++ b/spec/lib/gitlab/database/async_constraints/foreign_key_validator_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::AsyncForeignKeys::ForeignKeyValidator, feature_category: :database do +RSpec.describe Gitlab::Database::AsyncConstraints::ForeignKeyValidator, feature_category: :database do include ExclusiveLeaseHelpers describe '#perform' do @@ -10,10 +10,10 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::ForeignKeyValidator, feature_ let(:lease_key) { "gitlab/database/asyncddl/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" } let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION } - let(:fk_model) { Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValidation } + let(:fk_model) { Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation } let(:table_name) { '_test_async_fks' } let(:fk_name) { 'fk_parent_id' } - let(:validation) { create(:postgres_async_foreign_key_validation, table_name: table_name, name: fk_name) } + let(:validation) { create(:postgres_async_constraint_validation, table_name: table_name, name: fk_name) } let(:connection) { validation.connection } subject { described_class.new(validation) } @@ -38,7 +38,7 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::ForeignKeyValidator, feature_ context 'with fully qualified table names' do let(:validation) do - create(:postgres_async_foreign_key_validation, + create(:postgres_async_constraint_validation, table_name: "public.#{table_name}", name: fk_name ) diff --git a/spec/lib/gitlab/database/async_foreign_keys/migration_helpers_spec.rb b/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb index 0bd0e8045ff..ab06c7c7e82 100644 --- a/spec/lib/gitlab/database/async_foreign_keys/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/async_constraints/migration_helpers_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_category: :database do +RSpec.describe Gitlab::Database::AsyncConstraints::MigrationHelpers, feature_category: :database do let(:migration) { Gitlab::Database::Migration[2.1].new } let(:connection) { ApplicationRecord.connection } - let(:fk_model) { Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValidation } + let(:constraint_model) { Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation } let(:table_name) { '_test_async_fks' } let(:column_name) { 'parent_id' } let(:fk_name) { nil } @@ -28,9 +28,9 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_cat it 'creates the record for the async FK validation' do expect do migration.prepare_async_foreign_key_validation(table_name, column_name) - end.to change { fk_model.where(table_name: table_name).count }.by(1) + end.to change { constraint_model.where(table_name: table_name).count }.by(1) - record = fk_model.find_by(table_name: table_name) + record = constraint_model.find_by(table_name: table_name) expect(record.name).to start_with('fk_') end @@ -41,9 +41,9 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_cat it 'creates the record with the given name' do expect do migration.prepare_async_foreign_key_validation(table_name, name: fk_name) - end.to change { fk_model.where(name: fk_name).count }.by(1) + end.to change { constraint_model.where(name: fk_name).count }.by(1) - record = fk_model.find_by(name: fk_name) + record = constraint_model.find_by(name: fk_name) expect(record.table_name).to eq(table_name) end @@ -61,19 +61,19 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_cat let(:fk_name) { 'my_fk_name' } it 'does attempt to create the record' do - create(:postgres_async_foreign_key_validation, table_name: table_name, name: fk_name) + create(:postgres_async_constraint_validation, table_name: table_name, name: fk_name) expect do migration.prepare_async_foreign_key_validation(table_name, name: fk_name) - end.not_to change { fk_model.where(name: fk_name).count } + end.not_to change { constraint_model.where(name: fk_name).count } end end context 'when the async FK validation table does not exist' do it 'does not raise an error' do - connection.drop_table(:postgres_async_foreign_key_validations) + connection.drop_table(constraint_model.table_name) - expect(fk_model).not_to receive(:safe_find_or_create_by!) + expect(constraint_model).not_to receive(:safe_find_or_create_by!) expect { migration.prepare_async_foreign_key_validation(table_name, column_name) }.not_to raise_error end @@ -88,7 +88,7 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_cat it 'destroys the record' do expect do migration.unprepare_async_foreign_key_validation(table_name, column_name) - end.to change { fk_model.where(table_name: table_name).count }.by(-1) + end.to change { constraint_model.where(table_name: table_name).count }.by(-1) end context 'when an explicit name is given' do @@ -97,15 +97,15 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::MigrationHelpers, feature_cat it 'destroys the record' do expect do migration.unprepare_async_foreign_key_validation(table_name, name: fk_name) - end.to change { fk_model.where(name: fk_name).count }.by(-1) + end.to change { constraint_model.where(name: fk_name).count }.by(-1) end end context 'when the async fk validation table does not exist' do it 'does not raise an error' do - connection.drop_table(:postgres_async_foreign_key_validations) + connection.drop_table(constraint_model.table_name) - expect(fk_model).not_to receive(:find_by) + expect(constraint_model).not_to receive(:find_by) expect { migration.unprepare_async_foreign_key_validation(table_name, column_name) }.not_to raise_error end diff --git a/spec/lib/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation_spec.rb b/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb index 40ab9cb2dd2..a8e136dd22c 100644 --- a/spec/lib/gitlab/database/async_foreign_keys/postgres_async_foreign_key_validation_spec.rb +++ b/spec/lib/gitlab/database/async_constraints/postgres_async_constraint_validation_spec.rb @@ -2,16 +2,16 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValidation, type: :model, +RSpec.describe Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation, type: :model, feature_category: :database do it { is_expected.to be_a Gitlab::Database::SharedModel } describe 'validations' do - let_it_be(:fk_validation) { create(:postgres_async_foreign_key_validation) } + let_it_be(:constraint_validation) { create(:postgres_async_constraint_validation) } let(:identifier_limit) { described_class::MAX_IDENTIFIER_LENGTH } let(:last_error_limit) { described_class::MAX_LAST_ERROR_LENGTH } - subject { fk_validation } + subject { constraint_validation } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).scoped_to(:table_name) } @@ -22,8 +22,8 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValida end describe 'scopes' do - let!(:failed_validation) { create(:postgres_async_foreign_key_validation, attempts: 1) } - let!(:new_validation) { create(:postgres_async_foreign_key_validation) } + let!(:failed_validation) { create(:postgres_async_constraint_validation, attempts: 1) } + let!(:new_validation) { create(:postgres_async_constraint_validation) } describe '.ordered' do subject { described_class.ordered } @@ -32,21 +32,37 @@ RSpec.describe Gitlab::Database::AsyncForeignKeys::PostgresAsyncForeignKeyValida end end + describe '.table_available?' do + subject { described_class.table_available? } + + it { is_expected.to be_truthy } + + context 'when the table does not exist' do + before do + described_class + .connection + .drop_table(described_class.table_name) + end + + it { is_expected.to be_falsy } + end + end + describe '#handle_exception!' do - let_it_be_with_reload(:fk_validation) { create(:postgres_async_foreign_key_validation) } + let_it_be_with_reload(:constraint_validation) { create(:postgres_async_constraint_validation) } let(:error) { instance_double(StandardError, message: 'Oups', backtrace: %w[this that]) } - subject { fk_validation.handle_exception!(error) } + subject { constraint_validation.handle_exception!(error) } it 'increases the attempts number' do - expect { subject }.to change { fk_validation.reload.attempts }.by(1) + expect { subject }.to change { constraint_validation.reload.attempts }.by(1) end it 'saves error details' do subject - expect(fk_validation.reload.last_error).to eq("Oups\nthis\nthat") + expect(constraint_validation.reload.last_error).to eq("Oups\nthis\nthat") end end end diff --git a/spec/lib/gitlab/database/async_foreign_keys_spec.rb b/spec/lib/gitlab/database/async_constraints_spec.rb index f15eb364929..2141131479d 100644 --- a/spec/lib/gitlab/database/async_foreign_keys_spec.rb +++ b/spec/lib/gitlab/database/async_constraints_spec.rb @@ -2,16 +2,16 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::AsyncForeignKeys, feature_category: :database do +RSpec.describe Gitlab::Database::AsyncConstraints, feature_category: :database do describe '.validate_pending_entries!' do subject { described_class.validate_pending_entries! } before do - create_list(:postgres_async_foreign_key_validation, 3) + create_list(:postgres_async_constraint_validation, 3) end it 'takes 2 pending FK validations and executes them' do - validations = described_class::PostgresAsyncForeignKeyValidation.ordered.limit(2).to_a + validations = described_class::PostgresAsyncConstraintValidation.ordered.limit(2).to_a expect_next_instances_of(described_class::ForeignKeyValidator, 2, validations) do |validator| expect(validator).to receive(:perform) diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb index a8af9bb5a38..4d0e58b0937 100644 --- a/spec/lib/gitlab/database/reindexing_spec.rb +++ b/spec/lib/gitlab/database/reindexing_spec.rb @@ -71,7 +71,7 @@ RSpec.describe Gitlab::Database::Reindexing, feature_category: :database, time_t context 'when async FK validation is enabled' do it 'executes FK validation for each database prior to any reindexing actions' do - expect(Gitlab::Database::AsyncForeignKeys).to receive(:validate_pending_entries!).ordered.exactly(databases_count).times + expect(Gitlab::Database::AsyncConstraints).to receive(:validate_pending_entries!).ordered.exactly(databases_count).times expect(described_class).to receive(:automatic_reindexing).ordered.exactly(databases_count).times described_class.invoke @@ -82,7 +82,7 @@ RSpec.describe Gitlab::Database::Reindexing, feature_category: :database, time_t it 'does not execute FK validation' do stub_feature_flags(database_async_foreign_key_validation: false) - expect(Gitlab::Database::AsyncForeignKeys).not_to receive(:validate_pending_entries!) + expect(Gitlab::Database::AsyncConstraints).not_to receive(:validate_pending_entries!) described_class.invoke end diff --git a/spec/services/work_items/import_csv_service_spec.rb b/spec/services/work_items/import_csv_service_spec.rb index 658062ecdbe..83530c87c99 100644 --- a/spec/services/work_items/import_csv_service_spec.rb +++ b/spec/services/work_items/import_csv_service_spec.rb @@ -17,6 +17,7 @@ RSpec.describe WorkItems::ImportCsvService, feature_category: :team_planning do let_it_be(:issue_type) { ::WorkItems::Type.default_issue_type } let(:work_items) { ::WorkItems::WorkItemsFinder.new(user, project: project).execute } + let(:email_method) { :import_work_items_csv_email } subject { service.execute } @@ -26,6 +27,8 @@ RSpec.describe WorkItems::ImportCsvService, feature_category: :team_planning do project.add_guest(user) end + it_behaves_like 'importer with email notification' + context 'when file is valid' do it 'creates the expected number of work items' do expect { subject }.to change { work_items.count }.by 2 @@ -96,4 +99,14 @@ RSpec.describe WorkItems::ImportCsvService, feature_category: :team_planning do end end end + + context 'when user does not have permission' do + it 'errors on those lines', :aggregate_failures do + result = subject + + expect(result[:success]).to eq(0) + expect(result[:error_lines]).to eq([2, 3]) + expect(result[:parse_error]).to eq(false) + end + end end diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb index ddfdf50a31b..f43106959b0 100644 --- a/spec/tasks/gitlab/db_rake_spec.rb +++ b/spec/tasks/gitlab/db_rake_spec.rb @@ -841,65 +841,65 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor end end - describe 'execute_async_fk_validations' do + describe 'validate_async_constraints' do before do skip_if_multiple_databases_not_setup end - it 'delegates ci task to Gitlab::Database::AsyncForeignKeys' do - expect(Gitlab::Database::AsyncForeignKeys).to receive(:validate_pending_entries!).with(how_many: 2) + it 'delegates ci task to Gitlab::Database::AsyncConstraints' do + expect(Gitlab::Database::AsyncConstraints).to receive(:validate_pending_entries!).with(how_many: 2) - run_rake_task('gitlab:db:execute_async_fk_validations:ci') + run_rake_task('gitlab:db:validate_async_constraints:ci') end - it 'delegates ci task to Gitlab::Database::AsyncForeignKeys with specified argument' do - expect(Gitlab::Database::AsyncForeignKeys).to receive(:validate_pending_entries!).with(how_many: 5) + it 'delegates ci task to Gitlab::Database::AsyncConstraints with specified argument' do + expect(Gitlab::Database::AsyncConstraints).to receive(:validate_pending_entries!).with(how_many: 5) - run_rake_task('gitlab:db:execute_async_fk_validations:ci', '[5]') + run_rake_task('gitlab:db:validate_async_constraints:ci', '[5]') end - it 'delegates main task to Gitlab::Database::AsyncForeignKeys' do - expect(Gitlab::Database::AsyncForeignKeys).to receive(:validate_pending_entries!).with(how_many: 2) + it 'delegates main task to Gitlab::Database::AsyncConstraints' do + expect(Gitlab::Database::AsyncConstraints).to receive(:validate_pending_entries!).with(how_many: 2) - run_rake_task('gitlab:db:execute_async_fk_validations:main') + run_rake_task('gitlab:db:validate_async_constraints:main') end - it 'delegates main task to Gitlab::Database::AsyncForeignKeys with specified argument' do - expect(Gitlab::Database::AsyncForeignKeys).to receive(:validate_pending_entries!).with(how_many: 7) + it 'delegates main task to Gitlab::Database::AsyncConstraints with specified argument' do + expect(Gitlab::Database::AsyncConstraints).to receive(:validate_pending_entries!).with(how_many: 7) - run_rake_task('gitlab:db:execute_async_fk_validations:main', '[7]') + run_rake_task('gitlab:db:validate_async_constraints:main', '[7]') end it 'delegates all task to every database with higher default for dev' do - expect(Rake::Task['gitlab:db:execute_async_fk_validations:ci']).to receive(:invoke).with(1000) - expect(Rake::Task['gitlab:db:execute_async_fk_validations:main']).to receive(:invoke).with(1000) + expect(Rake::Task['gitlab:db:validate_async_constraints:ci']).to receive(:invoke).with(1000) + expect(Rake::Task['gitlab:db:validate_async_constraints:main']).to receive(:invoke).with(1000) - run_rake_task('gitlab:db:execute_async_fk_validations:all') + run_rake_task('gitlab:db:validate_async_constraints:all') end it 'delegates all task to every database with lower default for prod' do allow(Gitlab).to receive(:dev_or_test_env?).and_return(false) - expect(Rake::Task['gitlab:db:execute_async_fk_validations:ci']).to receive(:invoke).with(2) - expect(Rake::Task['gitlab:db:execute_async_fk_validations:main']).to receive(:invoke).with(2) + expect(Rake::Task['gitlab:db:validate_async_constraints:ci']).to receive(:invoke).with(2) + expect(Rake::Task['gitlab:db:validate_async_constraints:main']).to receive(:invoke).with(2) - run_rake_task('gitlab:db:execute_async_fk_validations:all') + run_rake_task('gitlab:db:validate_async_constraints:all') end it 'delegates all task to every database with specified argument' do - expect(Rake::Task['gitlab:db:execute_async_fk_validations:ci']).to receive(:invoke).with('50') - expect(Rake::Task['gitlab:db:execute_async_fk_validations:main']).to receive(:invoke).with('50') + expect(Rake::Task['gitlab:db:validate_async_constraints:ci']).to receive(:invoke).with('50') + expect(Rake::Task['gitlab:db:validate_async_constraints:main']).to receive(:invoke).with('50') - run_rake_task('gitlab:db:execute_async_fk_validations:all', '[50]') + run_rake_task('gitlab:db:validate_async_constraints:all', '[50]') end context 'when feature is not enabled' do it 'is a no-op' do stub_feature_flags(database_async_foreign_key_validation: false) - expect(Gitlab::Database::AsyncForeignKeys).not_to receive(:validate_pending_entries!) + expect(Gitlab::Database::AsyncConstraints).not_to receive(:validate_pending_entries!) - expect { run_rake_task('gitlab:db:execute_async_fk_validations:main') }.to raise_error(SystemExit) + expect { run_rake_task('gitlab:db:validate_async_constraints:main') }.to raise_error(SystemExit) end end @@ -909,8 +909,8 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor end it 'does not create a task for the geo database' do - expect { run_rake_task('gitlab:db:execute_async_fk_validations:geo') } - .to raise_error(/Don't know how to build task 'gitlab:db:execute_async_fk_validations:geo'/) + expect { run_rake_task('gitlab:db:validate_async_constraints:geo') } + .to raise_error(/Don't know how to build task 'gitlab:db:validate_async_constraints:geo'/) end end end diff --git a/spec/views/notify/import_issues_csv_email.html.haml_spec.rb b/spec/views/notify/import_issues_csv_email.html.haml_spec.rb index 43dfab87ac9..c3d320a837b 100644 --- a/spec/views/notify/import_issues_csv_email.html.haml_spec.rb +++ b/spec/views/notify/import_issues_csv_email.html.haml_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' RSpec.describe 'notify/import_issues_csv_email.html.haml' do let(:user) { create(:user) } let(:project) { create(:project) } - let(:correct_results) { { success: 3, valid_file: true } } - let(:errored_results) { { success: 3, error_lines: [5, 6, 7], valid_file: true } } + let(:correct_results) { { success: 3, parse_error: false } } + let(:errored_results) { { success: 3, error_lines: [5, 6, 7], parse_error: false } } let(:parse_error_results) { { success: 0, parse_error: true } } before do diff --git a/spec/views/notify/import_work_items_csv_email.html.haml_spec.rb b/spec/views/notify/import_work_items_csv_email.html.haml_spec.rb new file mode 100644 index 00000000000..8a01c11646a --- /dev/null +++ b/spec/views/notify/import_work_items_csv_email.html.haml_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'notify/import_work_items_csv_email.html.haml', feature_category: :team_planning do + let_it_be(:user) { create(:user) } # rubocop:disable RSpec/FactoryBot/AvoidCreate + let_it_be(:project) { create(:project) } # rubocop:disable RSpec/FactoryBot/AvoidCreate + let_it_be(:correct_results) { { success: 3, parse_error: false } } + let_it_be(:errored_results) { { success: 3, error_lines: [5, 6, 7], parse_error: false } } + let_it_be(:parse_error_results) { { success: 0, parse_error: true } } + + before do + assign(:user, user) + assign(:project, project) + end + + context 'when no errors found while importing' do + before do + assign(:results, correct_results) + end + + it 'renders correctly' do + render + + expect(rendered).to have_link(project.full_name, href: project_url(project)) + expect(rendered).to have_content("3 work items imported") + expect(rendered).not_to have_content("Errors found on line") + expect(rendered).not_to have_content( + "Error parsing CSV file. Please make sure it has the correct format: \ +a delimited text file that uses a comma to separate values.") + end + end + + context 'when import errors reported' do + before do + assign(:results, errored_results) + end + + it 'renders correctly' do + render + + expect(rendered).to have_content("Errors found on lines: #{errored_results[:error_lines].join(', ')}. \ +Please check that these lines have the following fields: title") + expect(rendered).not_to have_content("Error parsing CSV file. Please make sure it has the correct format: \ +a delimited text file that uses a comma to separate values.") + end + end + + context 'when parse error reported while importing' do + before do + assign(:results, parse_error_results) + end + + it 'renders with parse error' do + render + + expect(rendered).to have_content("Error parsing CSV file. \ +Please make sure it has the correct format: a delimited text file that uses a comma to separate values.") + end + end +end |