From 04cc87ee46c1c0b6b4eb7df964b3115dd2578877 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 13 Jun 2023 21:09:09 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/rspec/be.yml | 21 -- app/models/abuse/event.rb | 18 ++ app/models/abuse_report.rb | 2 + app/models/commit_user_mention.rb | 2 +- app/models/concerns/enums/abuse/category.rb | 16 ++ app/models/design_user_mention.rb | 2 +- app/models/issue_user_mention.rb | 2 +- app/models/merge_request_user_mention.rb | 2 +- app/models/note_diff_file.rb | 2 +- app/models/snippet_user_mention.rb | 2 +- app/models/suggestion.rb | 2 +- app/models/system_note_metadata.rb | 2 +- app/models/timelog.rb | 2 +- app/models/todo.rb | 2 +- app/models/user.rb | 1 + app/models/work_item.rb | 7 +- app/presenters/work_item_presenter.rb | 4 + app/services/notes/create_service.rb | 27 ++- app/services/notes/quick_actions_service.rb | 16 +- .../json_schemas/abuse_event_metadata.json | 7 + app/views/devise/passwords/new.html.haml | 18 +- ...10346_i_quickactions_promote_to_weekly.yml | 26 +++ db/docs/abuse_events.yml | 10 + .../20230522180913_create_abuse_events.rb | 24 ++ ...foreign_key_constraints_to_abuse_events.rb | 15 ++ ..._fk_ci_build_pending_states_p_ci_builds.rb | 11 + ...te_fk_ci_build_trace_chunks_p_ci_builds.rb | 11 + ...te_fk_ci_unit_test_failures_p_ci_builds.rb | 11 + ...ate_fk_ci_sources_pipelines_p_ci_builds.rb | 11 + ...46_validate_fk_ci_resources_p_ci_builds.rb | 11 + ..._fk_ci_build_report_results_p_ci_builds.rb | 11 + ..._validate_fk_ci_build_needs_p_ci_builds.rb | 11 + ...fk_ci_builds_runner_session_p_ci_builds.rb | 11 + ...lidate_fk_ci_pending_builds_p_ci_builds.rb | 11 + ..._fk_ci_build_trace_metadata_p_ci_builds.rb | 11 + ...int_conversion_for_todos_for_gitlab_com.rb | 28 +++ ...for_system_note_metadata_for_gitlab_com.rb | 28 +++ ...n_for_epic_user_mentions_for_gitlab_com.rb | 28 +++ ...nversion_for_suggestions_for_gitlab_com.rb | 28 +++ ..._for_issue_user_mentions_for_gitlab_com.rb | 28 +++ ...sion_for_note_diff_files_for_gitlab_com.rb | 28 +++ ...or_snippet_user_mentions_for_gitlab_com.rb | 28 +++ ...for_design_user_mentions_for_gitlab_com.rb | 28 +++ ...nerability_user_mentions_for_gitlab_com.rb | 28 +++ ...for_commit_user_mentions_for_gitlab_com.rb | 28 +++ ...ge_request_user_mentions_for_gitlab_com.rb | 28 +++ ..._conversion_for_timelogs_for_gitlab_com.rb | 28 +++ ...nversion_for_award_emoji_for_gitlab_com.rb | 28 +++ db/schema_migrations/20230522180913 | 1 + db/schema_migrations/20230522181134 | 1 + db/schema_migrations/20230530140456 | 1 + db/schema_migrations/20230530140509 | 1 + db/schema_migrations/20230530140521 | 1 + db/schema_migrations/20230530140534 | 1 + db/schema_migrations/20230530140546 | 1 + db/schema_migrations/20230530140558 | 1 + db/schema_migrations/20230530140611 | 1 + db/schema_migrations/20230530140623 | 1 + db/schema_migrations/20230530140634 | 1 + db/schema_migrations/20230530140646 | 1 + db/schema_migrations/20230608231452 | 1 + db/schema_migrations/20230608232452 | 1 + db/schema_migrations/20230608233452 | 1 + db/schema_migrations/20230608234452 | 1 + db/schema_migrations/20230608235452 | 1 + db/schema_migrations/20230609000452 | 1 + db/schema_migrations/20230609001452 | 1 + db/schema_migrations/20230609002452 | 1 + db/schema_migrations/20230609003452 | 1 + db/schema_migrations/20230609004452 | 1 + db/schema_migrations/20230609005452 | 1 + db/schema_migrations/20230609010452 | 1 + db/schema_migrations/20230609011452 | 1 + db/structure.sql | 213 ++++-------------- doc/administration/pages/index.md | 24 +- doc/user/clusters/agent/ci_cd_workflow.md | 4 +- doc/user/clusters/agent/install/index.md | 4 +- doc/user/clusters/agent/vulnerabilities.md | 4 +- doc/user/clusters/agent/work_with_agent.md | 20 +- doc/user/clusters/management_project.md | 5 +- .../clusters/management_project_template.md | 3 +- doc/user/okrs.md | 5 +- doc/user/project/quick_actions.md | 1 + .../project/repository/code_suggestions.md | 8 + doc/user/tasks.md | 10 + lib/gitlab/quick_actions/work_item_actions.rb | 85 +++++-- .../known_events/quickactions.yml | 2 + locale/gitlab.pot | 20 +- spec/factories/abuse/event.rb | 13 ++ .../common/pipelines/boards_pipeline_spec.rb | 4 +- .../backfill_snippet_repositories_spec.rb | 10 +- spec/lib/gitlab/lets_encrypt/client_spec.rb | 2 +- .../lib/gitlab/search_context/builder_spec.rb | 2 +- spec/models/abuse/event_spec.rb | 48 ++++ spec/models/concerns/issuable_spec.rb | 2 +- spec/models/identity_spec.rb | 2 +- spec/models/snippet_repository_spec.rb | 2 +- spec/models/user_spec.rb | 1 + spec/models/work_item_spec.rb | 11 +- spec/presenters/work_item_presenter_spec.rb | 14 ++ .../graphql/mutations/snippets/create_spec.rb | 2 +- .../mutations/work_items/update_spec.rb | 2 +- spec/requests/api/pages_domains_spec.rb | 4 +- spec/services/notes/create_service_spec.rb | 13 ++ .../notes/quick_actions_service_spec.rb | 121 ++++++++++ spec/services/pages/delete_service_spec.rb | 2 +- ...igrate_from_legacy_storage_service_spec.rb | 2 +- .../projects/update_pages_service_spec.rb | 2 +- .../quick_actions/interpret_service_spec.rb | 71 ++---- .../work_items_type_change_shared_context.rb | 25 ++ ..._actions_for_work_items_shared_examples.rb | 19 ++ ...pe_change_quick_actions_shared_examples.rb | 93 ++++++++ .../requests/api/packages_shared_examples.rb | 2 +- spec/uploaders/file_uploader_spec.rb | 4 +- .../uploaders/namespace_file_uploader_spec.rb | 4 +- 115 files changed, 1274 insertions(+), 342 deletions(-) delete mode 100644 .rubocop_todo/rspec/be.yml create mode 100644 app/models/abuse/event.rb create mode 100644 app/models/concerns/enums/abuse/category.rb create mode 100644 app/presenters/work_item_presenter.rb create mode 100644 app/validators/json_schemas/abuse_event_metadata.json create mode 100644 config/metrics/counts_7d/20230607110346_i_quickactions_promote_to_weekly.yml create mode 100644 db/docs/abuse_events.yml create mode 100644 db/migrate/20230522180913_create_abuse_events.rb create mode 100644 db/migrate/20230522181134_add_foreign_key_constraints_to_abuse_events.rb create mode 100644 db/post_migrate/20230530140456_validate_fk_ci_build_pending_states_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140509_validate_fk_ci_build_trace_chunks_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140521_validate_fk_ci_unit_test_failures_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140534_validate_fk_ci_sources_pipelines_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140546_validate_fk_ci_resources_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140558_validate_fk_ci_build_report_results_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140611_validate_fk_ci_build_needs_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140623_validate_fk_ci_builds_runner_session_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140634_validate_fk_ci_pending_builds_p_ci_builds.rb create mode 100644 db/post_migrate/20230530140646_validate_fk_ci_build_trace_metadata_p_ci_builds.rb create mode 100644 db/post_migrate/20230608231452_cleanup_bigint_conversion_for_todos_for_gitlab_com.rb create mode 100644 db/post_migrate/20230608232452_cleanup_bigint_conversion_for_system_note_metadata_for_gitlab_com.rb create mode 100644 db/post_migrate/20230608233452_cleanup_bigint_conversion_for_epic_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230608234452_cleanup_bigint_conversion_for_suggestions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230608235452_cleanup_bigint_conversion_for_issue_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609000452_cleanup_bigint_conversion_for_note_diff_files_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609001452_cleanup_bigint_conversion_for_snippet_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609002452_cleanup_bigint_conversion_for_design_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609003452_cleanup_bigint_conversion_for_vulnerability_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609004452_cleanup_bigint_conversion_for_commit_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609005452_cleanup_bigint_conversion_for_merge_request_user_mentions_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609010452_cleanup_bigint_conversion_for_timelogs_for_gitlab_com.rb create mode 100644 db/post_migrate/20230609011452_cleanup_bigint_conversion_for_award_emoji_for_gitlab_com.rb create mode 100644 db/schema_migrations/20230522180913 create mode 100644 db/schema_migrations/20230522181134 create mode 100644 db/schema_migrations/20230530140456 create mode 100644 db/schema_migrations/20230530140509 create mode 100644 db/schema_migrations/20230530140521 create mode 100644 db/schema_migrations/20230530140534 create mode 100644 db/schema_migrations/20230530140546 create mode 100644 db/schema_migrations/20230530140558 create mode 100644 db/schema_migrations/20230530140611 create mode 100644 db/schema_migrations/20230530140623 create mode 100644 db/schema_migrations/20230530140634 create mode 100644 db/schema_migrations/20230530140646 create mode 100644 db/schema_migrations/20230608231452 create mode 100644 db/schema_migrations/20230608232452 create mode 100644 db/schema_migrations/20230608233452 create mode 100644 db/schema_migrations/20230608234452 create mode 100644 db/schema_migrations/20230608235452 create mode 100644 db/schema_migrations/20230609000452 create mode 100644 db/schema_migrations/20230609001452 create mode 100644 db/schema_migrations/20230609002452 create mode 100644 db/schema_migrations/20230609003452 create mode 100644 db/schema_migrations/20230609004452 create mode 100644 db/schema_migrations/20230609005452 create mode 100644 db/schema_migrations/20230609010452 create mode 100644 db/schema_migrations/20230609011452 create mode 100644 spec/factories/abuse/event.rb create mode 100644 spec/models/abuse/event_spec.rb create mode 100644 spec/presenters/work_item_presenter_spec.rb create mode 100644 spec/support/shared_contexts/quick_actions/work_items_type_change_shared_context.rb create mode 100644 spec/support/shared_examples/quick_actions/work_item/type_change_quick_actions_shared_examples.rb diff --git a/.rubocop_todo/rspec/be.yml b/.rubocop_todo/rspec/be.yml deleted file mode 100644 index 17f857d0677..00000000000 --- a/.rubocop_todo/rspec/be.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -RSpec/Be: - Exclude: - - 'ee/spec/services/groups/transfer_service_spec.rb' - - 'spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb' - - 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb' - - 'spec/lib/gitlab/lets_encrypt/client_spec.rb' - - 'spec/lib/gitlab/search_context/builder_spec.rb' - - 'spec/migrations/20220503035221_add_gitlab_schema_to_batched_background_migrations_spec.rb' - - 'spec/models/concerns/issuable_spec.rb' - - 'spec/models/identity_spec.rb' - - 'spec/models/snippet_repository_spec.rb' - - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb' - - 'spec/requests/api/graphql/mutations/snippets/create_spec.rb' - - 'spec/requests/api/pages_domains_spec.rb' - - 'spec/services/pages/delete_service_spec.rb' - - 'spec/services/pages/migrate_from_legacy_storage_service_spec.rb' - - 'spec/services/projects/update_pages_service_spec.rb' - - 'spec/support/shared_examples/requests/api/packages_shared_examples.rb' - - 'spec/uploaders/file_uploader_spec.rb' - - 'spec/uploaders/namespace_file_uploader_spec.rb' diff --git a/app/models/abuse/event.rb b/app/models/abuse/event.rb new file mode 100644 index 00000000000..5700c1c73e6 --- /dev/null +++ b/app/models/abuse/event.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Abuse + class Event < ApplicationRecord + self.table_name = 'abuse_events' + + validates :category, presence: true + validates :source, presence: true + validates :user, presence: true, on: :create + validates :metadata, json_schema: { filename: 'abuse_event_metadata' }, allow_blank: true + + belongs_to :user, inverse_of: :abuse_events + belongs_to :abuse_report, inverse_of: :abuse_events + + enum category: Enums::Abuse::Category.categories + enum source: Enums::Abuse::Source.sources + end +end diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index 236eaf92546..1d2eee82827 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -19,6 +19,8 @@ class AbuseReport < ApplicationRecord has_many :events, class_name: 'ResourceEvents::AbuseReportEvent', inverse_of: :abuse_report + has_many :abuse_events, class_name: 'Abuse::Event', inverse_of: :abuse_report + validates :reporter, presence: true, on: :create validates :user, presence: true, on: :create validates :message, presence: true diff --git a/app/models/commit_user_mention.rb b/app/models/commit_user_mention.rb index 4d464f353ee..9215e15f07d 100644 --- a/app/models/commit_user_mention.rb +++ b/app/models/commit_user_mention.rb @@ -3,7 +3,7 @@ class CommitUserMention < UserMention include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' belongs_to :note end diff --git a/app/models/concerns/enums/abuse/category.rb b/app/models/concerns/enums/abuse/category.rb new file mode 100644 index 00000000000..e024ed17e32 --- /dev/null +++ b/app/models/concerns/enums/abuse/category.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Enums + module Abuse + module Category + def self.categories + { + spam: 0, # spamcheck + virus: 1, # VirusTotal + fraud: 2, # Arkos, Telesign + ci_cd: 3 # PVS + } + end + end + end +end diff --git a/app/models/design_user_mention.rb b/app/models/design_user_mention.rb index 87899f65cb1..7d0cd72e9eb 100644 --- a/app/models/design_user_mention.rb +++ b/app/models/design_user_mention.rb @@ -3,7 +3,7 @@ class DesignUserMention < UserMention include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' belongs_to :design, class_name: 'DesignManagement::Design' belongs_to :note diff --git a/app/models/issue_user_mention.rb b/app/models/issue_user_mention.rb index bb13b83d3ba..ad0df0dca78 100644 --- a/app/models/issue_user_mention.rb +++ b/app/models/issue_user_mention.rb @@ -5,5 +5,5 @@ class IssueUserMention < UserMention belongs_to :note include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' end diff --git a/app/models/merge_request_user_mention.rb b/app/models/merge_request_user_mention.rb index d946fd14628..3157f1ca2aa 100644 --- a/app/models/merge_request_user_mention.rb +++ b/app/models/merge_request_user_mention.rb @@ -3,7 +3,7 @@ class MergeRequestUserMention < UserMention include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' belongs_to :merge_request belongs_to :note diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb index e4936de7b40..b0f6af0d853 100644 --- a/app/models/note_diff_file.rb +++ b/app/models/note_diff_file.rb @@ -4,7 +4,7 @@ class NoteDiffFile < ApplicationRecord include DiffFile include IgnorableColumns - ignore_column :diff_note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :diff_note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' scope :referencing_sha, -> (oids, project_id:) do joins(:diff_note).where(notes: { project_id: project_id, commit_id: oids }) diff --git a/app/models/snippet_user_mention.rb b/app/models/snippet_user_mention.rb index 138feb6ab29..8ef2c579a5a 100644 --- a/app/models/snippet_user_mention.rb +++ b/app/models/snippet_user_mention.rb @@ -3,7 +3,7 @@ class SnippetUserMention < UserMention include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' belongs_to :snippet belongs_to :note diff --git a/app/models/suggestion.rb b/app/models/suggestion.rb index 267be5fe5c2..58a154b8986 100644 --- a/app/models/suggestion.rb +++ b/app/models/suggestion.rb @@ -5,7 +5,7 @@ class Suggestion < ApplicationRecord include Suggestible include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' belongs_to :note, inverse_of: :suggestions validates :note, presence: true, unless: :importing? diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb index 0e0534d45ae..4e71a13a3a1 100644 --- a/app/models/system_note_metadata.rb +++ b/app/models/system_note_metadata.rb @@ -4,7 +4,7 @@ class SystemNoteMetadata < ApplicationRecord include Importable include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' # These notes's action text might contain a reference that is external. # We should always force a deep validation upon references that are found diff --git a/app/models/timelog.rb b/app/models/timelog.rb index 7f9cc2a99df..eb72456b435 100644 --- a/app/models/timelog.rb +++ b/app/models/timelog.rb @@ -5,7 +5,7 @@ class Timelog < ApplicationRecord include IgnorableColumns include Sortable - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' before_save :set_project diff --git a/app/models/todo.rb b/app/models/todo.rb index e1b5076e3d8..724f97c4812 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -6,7 +6,7 @@ class Todo < ApplicationRecord include EachBatch include IgnorableColumns - ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' + ignore_column :note_id_convert_to_bigint, remove_with: '16.2', remove_after: '2023-07-22' # Time to wait for todos being removed when not visible for user anymore. # Prevents TODOs being removed by mistake, for example, removing access from a user diff --git a/app/models/user.rb b/app/models/user.rb index 74c053c336d..8afe4a9c704 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -223,6 +223,7 @@ class User < ApplicationRecord has_many :reported_abuse_reports, dependent: :nullify, foreign_key: :reporter_id, class_name: "AbuseReport", inverse_of: :reporter # rubocop:disable Cop/ActiveRecordDependent has_many :assigned_abuse_reports, foreign_key: :assignee_id, class_name: "AbuseReport", inverse_of: :assignee has_many :resolved_abuse_reports, foreign_key: :resolved_by_id, class_name: "AbuseReport", inverse_of: :resolved_by + has_many :abuse_events, foreign_key: :user_id, class_name: 'Abuse::Event', inverse_of: :user has_many :spam_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :abuse_trust_scores, class_name: 'Abuse::TrustScore', foreign_key: :user_id has_many :builds, class_name: 'Ci::Build' diff --git a/app/models/work_item.rb b/app/models/work_item.rb index 24d1078516e..9f28ffbf7b6 100644 --- a/app/models/work_item.rb +++ b/app/models/work_item.rb @@ -4,7 +4,7 @@ class WorkItem < Issue include Gitlab::Utils::StrongMemoize COMMON_QUICK_ACTIONS_COMMANDS = [ - :title, :reopen, :close, :cc, :tableflip, :shrug, :type + :title, :reopen, :close, :cc, :tableflip, :shrug, :type, :promote_to ].freeze self.table_name = 'issues' @@ -168,8 +168,9 @@ class WorkItem < Issue errors.add( :work_item_type_id, format( - _('cannot be changed to %{new_type} with %{parent_type} as parent type.'), - new_type: work_item_type.name, parent_type: parent_link.work_item_parent.work_item_type.name + _('cannot be changed to %{new_type} when linked to a parent %{parent_type}.'), + new_type: work_item_type.name.downcase, + parent_type: parent_link.work_item_parent.work_item_type.name.downcase ) ) end diff --git a/app/presenters/work_item_presenter.rb b/app/presenters/work_item_presenter.rb new file mode 100644 index 00000000000..995f2d02156 --- /dev/null +++ b/app/presenters/work_item_presenter.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class WorkItemPresenter < IssuePresenter # rubocop:todo Gitlab/NamespacedClass +end diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 968d0414392..fdab2a07990 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -107,16 +107,10 @@ module Notes def do_commands(note, update_params, message, command_names, only_commands) return if quick_actions_service.commands_executed_count.to_i == 0 - if update_params.present? - invalid_message = validate_commands(note, update_params) - - if invalid_message - note.errors.add(:validation, invalid_message) - message = invalid_message - else - quick_actions_service.apply_updates(update_params, note) - note.commands_changes = update_params - end + update_error = quick_actions_update_errors(note, update_params) + if update_error + note.errors.add(:validation, update_error) + message = update_error end # We must add the error after we call #save because errors are reset @@ -129,6 +123,19 @@ module Notes end end + def quick_actions_update_errors(note, params) + return unless params.present? + + invalid_message = validate_commands(note, params) + return invalid_message if invalid_message + + service_response = quick_actions_service.apply_updates(params, note) + note.commands_changes = params + return if service_response.success? + + service_response.message.join(', ') + end + def quick_action_options { merge_request_diff_head_sha: params[:merge_request_diff_head_sha], diff --git a/app/services/notes/quick_actions_service.rb b/app/services/notes/quick_actions_service.rb index 38f7a23ce29..cba7398ebc0 100644 --- a/app/services/notes/quick_actions_service.rb +++ b/app/services/notes/quick_actions_service.rb @@ -50,7 +50,21 @@ module Notes update_params[:spend_time][:note_id] = note.id end - noteable_update_service(note, update_params).execute(note.noteable) + execute_update_service(note, update_params) + end + + private + + def execute_update_service(note, params) + service_response = noteable_update_service(note, params).execute(note.noteable) + + service_errors = if service_response.respond_to?(:errors) + service_response.errors.full_messages + elsif service_response.respond_to?(:[]) && service_response[:status] == :error + service_response[:message] + end + + service_errors.blank? ? ServiceResponse.success : ServiceResponse.error(message: service_errors) end def noteable_update_service(note, update_params) diff --git a/app/validators/json_schemas/abuse_event_metadata.json b/app/validators/json_schemas/abuse_event_metadata.json new file mode 100644 index 00000000000..b24ec93f877 --- /dev/null +++ b/app/validators/json_schemas/abuse_event_metadata.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Metadata to support an abuse event", + "type": "object", + "properties": { + } +} diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml index b8022f8a780..8e55977fe7a 100644 --- a/app/views/devise/passwords/new.html.haml +++ b/app/views/devise/passwords/new.html.haml @@ -1,21 +1,23 @@ .login-box .login-body - = gitlab_ui_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f| + = gitlab_ui_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'gl-p-5 gl-show-field-errors', aria: { live: 'assertive' }}) do |f| .devise-errors = render "devise/shared/error_messages", resource: resource - .form-group.gl-px-5.gl-pt-5 - = f.label :email, class: ("gl-mb-1" if Feature.enabled?(:restyle_login_page)) + .form-group + = f.label :email, _('Email') = f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.') .form-text.text-muted = _('Requires a verified GitLab email address.') - if recaptcha_enabled? - .gl-px-5 + .gl-mb-5 = recaptcha_tags nonce: content_security_policy_nonce - .gl-p-5 - = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true) do - = _('Reset password') + = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true) do + = _('Reset password') -.clearfix.prepend-top-20 +- if Feature.enabled?(:restyle_login_page, @project) = render 'devise/shared/sign_in_link' +- else + .gl-mt-3 + = render 'devise/shared/sign_in_link' diff --git a/config/metrics/counts_7d/20230607110346_i_quickactions_promote_to_weekly.yml b/config/metrics/counts_7d/20230607110346_i_quickactions_promote_to_weekly.yml new file mode 100644 index 00000000000..995e579e4f6 --- /dev/null +++ b/config/metrics/counts_7d/20230607110346_i_quickactions_promote_to_weekly.yml @@ -0,0 +1,26 @@ +--- +key_path: redis_hll_counters.quickactions.i_quickactions_promote_to_weekly +name: quickactions_promote_to_weekly +description: Count of WAU using the `/promote_to` quick action +product_section: dev +product_stage: plan +product_group: product_planning +value_type: number +status: active +milestone: "16.1" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122911 +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_quickactions_promote_to +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/db/docs/abuse_events.yml b/db/docs/abuse_events.yml new file mode 100644 index 00000000000..b399c957316 --- /dev/null +++ b/db/docs/abuse_events.yml @@ -0,0 +1,10 @@ +--- +table_name: abuse_events +classes: +- Abuse::Event +feature_categories: +- insider_threat +description: Captures events of potential abuse +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115258 +milestone: '16.1' +gitlab_schema: gitlab_main diff --git a/db/migrate/20230522180913_create_abuse_events.rb b/db/migrate/20230522180913_create_abuse_events.rb new file mode 100644 index 00000000000..8bda96bba50 --- /dev/null +++ b/db/migrate/20230522180913_create_abuse_events.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class CreateAbuseEvents < Gitlab::Database::Migration[2.1] + INDEX_NAME = 'index_abuse_events_on_category_and_source' + + enable_lock_retries! + + def up + create_table :abuse_events do |t| + t.bigint :user_id, null: true, index: true + t.timestamps_with_timezone null: false + t.references :abuse_report, foreign_key: true, on_delete: :nullify, null: true, index: true + t.integer :source, null: false, limit: 2 + t.integer :category, null: true, limit: 2 + t.jsonb :metadata, null: true + end + + add_index :abuse_events, [:category, :source], name: INDEX_NAME + end + + def down + drop_table :abuse_events + end +end diff --git a/db/migrate/20230522181134_add_foreign_key_constraints_to_abuse_events.rb b/db/migrate/20230522181134_add_foreign_key_constraints_to_abuse_events.rb new file mode 100644 index 00000000000..98927ad3ec5 --- /dev/null +++ b/db/migrate/20230522181134_add_foreign_key_constraints_to_abuse_events.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddForeignKeyConstraintsToAbuseEvents < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + add_concurrent_foreign_key :abuse_events, :users, column: :user_id, on_delete: :nullify, null: true + end + + def down + with_lock_retries do + remove_foreign_key_if_exists :abuse_events, column: :user_id + end + end +end diff --git a/db/post_migrate/20230530140456_validate_fk_ci_build_pending_states_p_ci_builds.rb b/db/post_migrate/20230530140456_validate_fk_ci_build_pending_states_p_ci_builds.rb new file mode 100644 index 00000000000..6104731152d --- /dev/null +++ b/db/post_migrate/20230530140456_validate_fk_ci_build_pending_states_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildPendingStatesPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_build_pending_states, nil, name: :temp_fk_861cd17da3_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140509_validate_fk_ci_build_trace_chunks_p_ci_builds.rb b/db/post_migrate/20230530140509_validate_fk_ci_build_trace_chunks_p_ci_builds.rb new file mode 100644 index 00000000000..40cef0428cf --- /dev/null +++ b/db/post_migrate/20230530140509_validate_fk_ci_build_trace_chunks_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildTraceChunksPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_build_trace_chunks, nil, name: :temp_fk_89e29fa5ee_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140521_validate_fk_ci_unit_test_failures_p_ci_builds.rb b/db/post_migrate/20230530140521_validate_fk_ci_unit_test_failures_p_ci_builds.rb new file mode 100644 index 00000000000..948d9a837a5 --- /dev/null +++ b/db/post_migrate/20230530140521_validate_fk_ci_unit_test_failures_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiUnitTestFailuresPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_unit_test_failures, nil, name: :temp_fk_9e0fc58930_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140534_validate_fk_ci_sources_pipelines_p_ci_builds.rb b/db/post_migrate/20230530140534_validate_fk_ci_sources_pipelines_p_ci_builds.rb new file mode 100644 index 00000000000..7e92026f21f --- /dev/null +++ b/db/post_migrate/20230530140534_validate_fk_ci_sources_pipelines_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiSourcesPipelinesPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_sources_pipelines, nil, name: :temp_fk_be5624bf37_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140546_validate_fk_ci_resources_p_ci_builds.rb b/db/post_migrate/20230530140546_validate_fk_ci_resources_p_ci_builds.rb new file mode 100644 index 00000000000..7cb58aed2ed --- /dev/null +++ b/db/post_migrate/20230530140546_validate_fk_ci_resources_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiResourcesPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_resources, nil, name: :temp_fk_e169a8e3d5_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140558_validate_fk_ci_build_report_results_p_ci_builds.rb b/db/post_migrate/20230530140558_validate_fk_ci_build_report_results_p_ci_builds.rb new file mode 100644 index 00000000000..f5188ab6bfe --- /dev/null +++ b/db/post_migrate/20230530140558_validate_fk_ci_build_report_results_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildReportResultsPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_build_report_results, nil, name: :temp_fk_rails_16cb1ff064_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140611_validate_fk_ci_build_needs_p_ci_builds.rb b/db/post_migrate/20230530140611_validate_fk_ci_build_needs_p_ci_builds.rb new file mode 100644 index 00000000000..6988e1027e5 --- /dev/null +++ b/db/post_migrate/20230530140611_validate_fk_ci_build_needs_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildNeedsPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_build_needs, nil, name: :temp_fk_rails_3cf221d4ed_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140623_validate_fk_ci_builds_runner_session_p_ci_builds.rb b/db/post_migrate/20230530140623_validate_fk_ci_builds_runner_session_p_ci_builds.rb new file mode 100644 index 00000000000..892df3ae00b --- /dev/null +++ b/db/post_migrate/20230530140623_validate_fk_ci_builds_runner_session_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildsRunnerSessionPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_builds_runner_session, nil, name: :temp_fk_rails_70707857d3_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140634_validate_fk_ci_pending_builds_p_ci_builds.rb b/db/post_migrate/20230530140634_validate_fk_ci_pending_builds_p_ci_builds.rb new file mode 100644 index 00000000000..8f6113aea31 --- /dev/null +++ b/db/post_migrate/20230530140634_validate_fk_ci_pending_builds_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiPendingBuildsPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_pending_builds, nil, name: :temp_fk_rails_725a2644a3_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230530140646_validate_fk_ci_build_trace_metadata_p_ci_builds.rb b/db/post_migrate/20230530140646_validate_fk_ci_build_trace_metadata_p_ci_builds.rb new file mode 100644 index 00000000000..00c015321ba --- /dev/null +++ b/db/post_migrate/20230530140646_validate_fk_ci_build_trace_metadata_p_ci_builds.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ValidateFkCiBuildTraceMetadataPCiBuilds < Gitlab::Database::Migration[2.1] + def up + validate_foreign_key :ci_build_trace_metadata, nil, name: :temp_fk_rails_aebc78111f_p + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230608231452_cleanup_bigint_conversion_for_todos_for_gitlab_com.rb b/db/post_migrate/20230608231452_cleanup_bigint_conversion_for_todos_for_gitlab_com.rb new file mode 100644 index 00000000000..281b5f926fa --- /dev/null +++ b/db/post_migrate/20230608231452_cleanup_bigint_conversion_for_todos_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForTodosForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :todos + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230608232452_cleanup_bigint_conversion_for_system_note_metadata_for_gitlab_com.rb b/db/post_migrate/20230608232452_cleanup_bigint_conversion_for_system_note_metadata_for_gitlab_com.rb new file mode 100644 index 00000000000..e52dd3e5da8 --- /dev/null +++ b/db/post_migrate/20230608232452_cleanup_bigint_conversion_for_system_note_metadata_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForSystemNoteMetadataForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :system_note_metadata + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230608233452_cleanup_bigint_conversion_for_epic_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230608233452_cleanup_bigint_conversion_for_epic_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..733aaa62b31 --- /dev/null +++ b/db/post_migrate/20230608233452_cleanup_bigint_conversion_for_epic_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForEpicUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :epic_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230608234452_cleanup_bigint_conversion_for_suggestions_for_gitlab_com.rb b/db/post_migrate/20230608234452_cleanup_bigint_conversion_for_suggestions_for_gitlab_com.rb new file mode 100644 index 00000000000..90f175bd35e --- /dev/null +++ b/db/post_migrate/20230608234452_cleanup_bigint_conversion_for_suggestions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForSuggestionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :suggestions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230608235452_cleanup_bigint_conversion_for_issue_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230608235452_cleanup_bigint_conversion_for_issue_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..094a8f43eef --- /dev/null +++ b/db/post_migrate/20230608235452_cleanup_bigint_conversion_for_issue_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForIssueUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :issue_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609000452_cleanup_bigint_conversion_for_note_diff_files_for_gitlab_com.rb b/db/post_migrate/20230609000452_cleanup_bigint_conversion_for_note_diff_files_for_gitlab_com.rb new file mode 100644 index 00000000000..bdb6ef83ea7 --- /dev/null +++ b/db/post_migrate/20230609000452_cleanup_bigint_conversion_for_note_diff_files_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForNoteDiffFilesForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :note_diff_files + COLUMNS = [:diff_note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609001452_cleanup_bigint_conversion_for_snippet_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230609001452_cleanup_bigint_conversion_for_snippet_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..f4b7724567b --- /dev/null +++ b/db/post_migrate/20230609001452_cleanup_bigint_conversion_for_snippet_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForSnippetUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :snippet_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609002452_cleanup_bigint_conversion_for_design_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230609002452_cleanup_bigint_conversion_for_design_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..2314cb4ac00 --- /dev/null +++ b/db/post_migrate/20230609002452_cleanup_bigint_conversion_for_design_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForDesignUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :design_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609003452_cleanup_bigint_conversion_for_vulnerability_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230609003452_cleanup_bigint_conversion_for_vulnerability_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..4722d3d24e8 --- /dev/null +++ b/db/post_migrate/20230609003452_cleanup_bigint_conversion_for_vulnerability_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForVulnerabilityUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :vulnerability_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609004452_cleanup_bigint_conversion_for_commit_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230609004452_cleanup_bigint_conversion_for_commit_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..b7399f3a6db --- /dev/null +++ b/db/post_migrate/20230609004452_cleanup_bigint_conversion_for_commit_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForCommitUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :commit_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609005452_cleanup_bigint_conversion_for_merge_request_user_mentions_for_gitlab_com.rb b/db/post_migrate/20230609005452_cleanup_bigint_conversion_for_merge_request_user_mentions_for_gitlab_com.rb new file mode 100644 index 00000000000..b4b66d218f0 --- /dev/null +++ b/db/post_migrate/20230609005452_cleanup_bigint_conversion_for_merge_request_user_mentions_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForMergeRequestUserMentionsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :merge_request_user_mentions + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609010452_cleanup_bigint_conversion_for_timelogs_for_gitlab_com.rb b/db/post_migrate/20230609010452_cleanup_bigint_conversion_for_timelogs_for_gitlab_com.rb new file mode 100644 index 00000000000..6a9d5532716 --- /dev/null +++ b/db/post_migrate/20230609010452_cleanup_bigint_conversion_for_timelogs_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForTimelogsForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :timelogs + COLUMNS = [:note_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/post_migrate/20230609011452_cleanup_bigint_conversion_for_award_emoji_for_gitlab_com.rb b/db/post_migrate/20230609011452_cleanup_bigint_conversion_for_award_emoji_for_gitlab_com.rb new file mode 100644 index 00000000000..5edbd8ed212 --- /dev/null +++ b/db/post_migrate/20230609011452_cleanup_bigint_conversion_for_award_emoji_for_gitlab_com.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CleanupBigintConversionForAwardEmojiForGitlabCom < Gitlab::Database::Migration[2.1] + include Gitlab::Database::MigrationHelpers::ConvertToBigint + + enable_lock_retries! + + TABLE = :award_emoji + COLUMNS = [:awardable_id] + + def up + return unless should_run? + + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + return unless should_run? + + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + private + + def should_run? + com_or_dev_or_test_but_not_jh? + end +end diff --git a/db/schema_migrations/20230522180913 b/db/schema_migrations/20230522180913 new file mode 100644 index 00000000000..efae214ea6b --- /dev/null +++ b/db/schema_migrations/20230522180913 @@ -0,0 +1 @@ +a050f273e3582d5e651f691631dae28a3e1c60a3f95d1f6f05b0ea47be609e8b \ No newline at end of file diff --git a/db/schema_migrations/20230522181134 b/db/schema_migrations/20230522181134 new file mode 100644 index 00000000000..b37e66a370a --- /dev/null +++ b/db/schema_migrations/20230522181134 @@ -0,0 +1 @@ +746360d5f65be831e1225d343983ca870464eaa5a84f619d6b28975ecfc4a876 \ No newline at end of file diff --git a/db/schema_migrations/20230530140456 b/db/schema_migrations/20230530140456 new file mode 100644 index 00000000000..c0655e8c696 --- /dev/null +++ b/db/schema_migrations/20230530140456 @@ -0,0 +1 @@ +21784b0f64cadd7e042ef1f749734f36a9c75dab191b52b54abdf446ef0165ae \ No newline at end of file diff --git a/db/schema_migrations/20230530140509 b/db/schema_migrations/20230530140509 new file mode 100644 index 00000000000..f841985a028 --- /dev/null +++ b/db/schema_migrations/20230530140509 @@ -0,0 +1 @@ +4331529950dc93a211f0e367aa9b24beef89406c55f86d37848cad082d10cc4c \ No newline at end of file diff --git a/db/schema_migrations/20230530140521 b/db/schema_migrations/20230530140521 new file mode 100644 index 00000000000..3217b3d5f79 --- /dev/null +++ b/db/schema_migrations/20230530140521 @@ -0,0 +1 @@ +14e7ccf0a930dde1369c7dcd0fc6a8719daccf461efbb2f6abb9ddc33beef670 \ No newline at end of file diff --git a/db/schema_migrations/20230530140534 b/db/schema_migrations/20230530140534 new file mode 100644 index 00000000000..50232dfe0ca --- /dev/null +++ b/db/schema_migrations/20230530140534 @@ -0,0 +1 @@ +2ffca5ebb17dacbea2ec15ba6496db4c1cf02501dcc420a5e2853792c78c1e61 \ No newline at end of file diff --git a/db/schema_migrations/20230530140546 b/db/schema_migrations/20230530140546 new file mode 100644 index 00000000000..9e7a59023a8 --- /dev/null +++ b/db/schema_migrations/20230530140546 @@ -0,0 +1 @@ +3be698933e9c19c8723bb02950bda4948fa2ba70782aee59e4103566cb38804f \ No newline at end of file diff --git a/db/schema_migrations/20230530140558 b/db/schema_migrations/20230530140558 new file mode 100644 index 00000000000..66d3798b6d9 --- /dev/null +++ b/db/schema_migrations/20230530140558 @@ -0,0 +1 @@ +f8f4a9cc99a61bc5d9ab630e9d240470a7584e755277b73d8b434a1348b6063a \ No newline at end of file diff --git a/db/schema_migrations/20230530140611 b/db/schema_migrations/20230530140611 new file mode 100644 index 00000000000..a34c2af3643 --- /dev/null +++ b/db/schema_migrations/20230530140611 @@ -0,0 +1 @@ +8ef2b55c4da3b3c5b975b9cc3e8d71c6db90a7f9288e6edb4fd828f82c545e11 \ No newline at end of file diff --git a/db/schema_migrations/20230530140623 b/db/schema_migrations/20230530140623 new file mode 100644 index 00000000000..5a98eaf1236 --- /dev/null +++ b/db/schema_migrations/20230530140623 @@ -0,0 +1 @@ +b0384e0289bb98ffde357520d553484146be9e1a91abc916a1ad5ecf41e57ae8 \ No newline at end of file diff --git a/db/schema_migrations/20230530140634 b/db/schema_migrations/20230530140634 new file mode 100644 index 00000000000..81d15a8b790 --- /dev/null +++ b/db/schema_migrations/20230530140634 @@ -0,0 +1 @@ +fe8957b8fa9ecc302f622a6282633f6dc1b93c007f1d66a5bfc88154bbbf9e24 \ No newline at end of file diff --git a/db/schema_migrations/20230530140646 b/db/schema_migrations/20230530140646 new file mode 100644 index 00000000000..f52e19736b1 --- /dev/null +++ b/db/schema_migrations/20230530140646 @@ -0,0 +1 @@ +08044e26d8e3d1c721665541179a8d968db6b62d479d0761e66421df9e4c64d9 \ No newline at end of file diff --git a/db/schema_migrations/20230608231452 b/db/schema_migrations/20230608231452 new file mode 100644 index 00000000000..5fabdf1da3b --- /dev/null +++ b/db/schema_migrations/20230608231452 @@ -0,0 +1 @@ +23a2b03a241a52dd898d55b4440195dee84d1bf638176a1c56d5ea27ecf895e4 \ No newline at end of file diff --git a/db/schema_migrations/20230608232452 b/db/schema_migrations/20230608232452 new file mode 100644 index 00000000000..16d8725ff86 --- /dev/null +++ b/db/schema_migrations/20230608232452 @@ -0,0 +1 @@ +525048a3306c63d37d30d93377e4210c0bf65d680d0191b6981f464829e502bb \ No newline at end of file diff --git a/db/schema_migrations/20230608233452 b/db/schema_migrations/20230608233452 new file mode 100644 index 00000000000..5a87b7fd027 --- /dev/null +++ b/db/schema_migrations/20230608233452 @@ -0,0 +1 @@ +d87c28da8a8155060b2913e7e2fea95353c6512bc013a50f6b3360332307c930 \ No newline at end of file diff --git a/db/schema_migrations/20230608234452 b/db/schema_migrations/20230608234452 new file mode 100644 index 00000000000..5cace1b6335 --- /dev/null +++ b/db/schema_migrations/20230608234452 @@ -0,0 +1 @@ +2d03e7e6d73f655b164251c7b504d695179a345f88cdea9304dc0efec94b573d \ No newline at end of file diff --git a/db/schema_migrations/20230608235452 b/db/schema_migrations/20230608235452 new file mode 100644 index 00000000000..34ed071830c --- /dev/null +++ b/db/schema_migrations/20230608235452 @@ -0,0 +1 @@ +570b154e7c912e75b7ffb899b809eb5aeead6c6fc8b427db8342a5df25a0734b \ No newline at end of file diff --git a/db/schema_migrations/20230609000452 b/db/schema_migrations/20230609000452 new file mode 100644 index 00000000000..acd2130c554 --- /dev/null +++ b/db/schema_migrations/20230609000452 @@ -0,0 +1 @@ +4ebf7479ab3d40be6b8dbcfad034c62ce6cd66a9118da85f8344e68b5bfc08b5 \ No newline at end of file diff --git a/db/schema_migrations/20230609001452 b/db/schema_migrations/20230609001452 new file mode 100644 index 00000000000..1173e2f9cbe --- /dev/null +++ b/db/schema_migrations/20230609001452 @@ -0,0 +1 @@ +ed093ce5b064fbd7f5ac99ae8add45a2ccf1e4a4911086a11517d0f99644299d \ No newline at end of file diff --git a/db/schema_migrations/20230609002452 b/db/schema_migrations/20230609002452 new file mode 100644 index 00000000000..e9a16c956c7 --- /dev/null +++ b/db/schema_migrations/20230609002452 @@ -0,0 +1 @@ +d516424bba378d9857c5807b9cef648ee4fe13531207c9aae91ece58894151d8 \ No newline at end of file diff --git a/db/schema_migrations/20230609003452 b/db/schema_migrations/20230609003452 new file mode 100644 index 00000000000..e920a9ef97c --- /dev/null +++ b/db/schema_migrations/20230609003452 @@ -0,0 +1 @@ +a3a08d3d10ca4e0e2a0d382a222ca4438313d4ee9a8998cbe2348a37517ef3ff \ No newline at end of file diff --git a/db/schema_migrations/20230609004452 b/db/schema_migrations/20230609004452 new file mode 100644 index 00000000000..f79d7a39587 --- /dev/null +++ b/db/schema_migrations/20230609004452 @@ -0,0 +1 @@ +a5e5bc6b56f1134d94d46b084172961869bb6f7d5d5d828ba5f076dd9cf9a2ad \ No newline at end of file diff --git a/db/schema_migrations/20230609005452 b/db/schema_migrations/20230609005452 new file mode 100644 index 00000000000..d2f249b31bd --- /dev/null +++ b/db/schema_migrations/20230609005452 @@ -0,0 +1 @@ +c66905576a5cdbf1f299fa6af77414ef889b108e0212f7ce9e6e9f132c134af9 \ No newline at end of file diff --git a/db/schema_migrations/20230609010452 b/db/schema_migrations/20230609010452 new file mode 100644 index 00000000000..2d5e64b037f --- /dev/null +++ b/db/schema_migrations/20230609010452 @@ -0,0 +1 @@ +c4f9c35213d69b2285fecf253bd3d50c962c55a3cfc4b50c3905571e6c99e9b6 \ No newline at end of file diff --git a/db/schema_migrations/20230609011452 b/db/schema_migrations/20230609011452 new file mode 100644 index 00000000000..826750c912f --- /dev/null +++ b/db/schema_migrations/20230609011452 @@ -0,0 +1 @@ +32adffeb44d662bb83d3685820bf2d149963b09ff25488586cbb0ad81fe5672f \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 8ef1d016c40..a4bbe2033d0 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -255,24 +255,6 @@ BEGIN END; $$; -CREATE FUNCTION trigger_0e214b8a14f2() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_17c3a95ee58a() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - CREATE FUNCTION trigger_1a857e8db6cd() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -282,51 +264,6 @@ BEGIN END; $$; -CREATE FUNCTION trigger_3dc62927cae8() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_428d92773fe7() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_482bac5ec48a() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_775287b6d67a() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."diff_note_id_convert_to_bigint" := NEW."diff_note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_909cf0a06094() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."awardable_id_convert_to_bigint" := NEW."awardable_id"; - RETURN NEW; -END; -$$; - CREATE FUNCTION trigger_b2d852e1e2cb() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -336,42 +273,6 @@ BEGIN END; $$; -CREATE FUNCTION trigger_bfc6e47be8cc() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_bfcbace4260d() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_c2051020aa8b() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_c5a5f48f12b0() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - CREATE FUNCTION trigger_cd1aeb22b34a() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -381,24 +282,6 @@ BEGIN END; $$; -CREATE FUNCTION trigger_dca935e3a712() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - -CREATE FUNCTION trigger_ee7956d805e6() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."note_id_convert_to_bigint" := NEW."note_id"; - RETURN NEW; -END; -$$; - CREATE FUNCTION unset_has_issues_on_vulnerability_reads() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -10758,6 +10641,26 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_63 ( ); ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63 FOR VALUES WITH (modulus 64, remainder 63); +CREATE TABLE abuse_events ( + id bigint NOT NULL, + user_id bigint, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + abuse_report_id bigint, + source smallint NOT NULL, + category smallint, + metadata jsonb +); + +CREATE SEQUENCE abuse_events_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE abuse_events_id_seq OWNED BY abuse_events.id; + CREATE TABLE abuse_report_events ( id bigint NOT NULL, abuse_report_id bigint NOT NULL, @@ -12356,7 +12259,6 @@ CREATE TABLE award_emoji ( id integer NOT NULL, name character varying, user_id integer, - awardable_id_convert_to_bigint integer, awardable_type character varying, created_at timestamp without time zone, updated_at timestamp without time zone, @@ -14501,7 +14403,6 @@ ALTER SEQUENCE clusters_kubernetes_namespaces_id_seq OWNED BY clusters_kubernete CREATE TABLE commit_user_mentions ( id bigint NOT NULL, - note_id_convert_to_bigint integer DEFAULT 0 NOT NULL, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -15446,7 +15347,6 @@ ALTER SEQUENCE design_management_versions_id_seq OWNED BY design_management_vers CREATE TABLE design_user_mentions ( id bigint NOT NULL, design_id integer NOT NULL, - note_id_convert_to_bigint integer DEFAULT 0 NOT NULL, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -15797,7 +15697,6 @@ ALTER SEQUENCE epic_metrics_id_seq OWNED BY epic_metrics.id; CREATE TABLE epic_user_mentions ( id bigint NOT NULL, epic_id integer NOT NULL, - note_id_convert_to_bigint integer, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -17462,7 +17361,6 @@ ALTER SEQUENCE issue_tracker_data_id_seq OWNED BY issue_tracker_data.id; CREATE TABLE issue_user_mentions ( id bigint NOT NULL, issue_id integer NOT NULL, - note_id_convert_to_bigint integer, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -18302,7 +18200,6 @@ ALTER SEQUENCE merge_request_reviewers_id_seq OWNED BY merge_request_reviewers.i CREATE TABLE merge_request_user_mentions ( id bigint NOT NULL, merge_request_id integer NOT NULL, - note_id_convert_to_bigint integer, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -18924,7 +18821,6 @@ ALTER SEQUENCE namespaces_sync_events_id_seq OWNED BY namespaces_sync_events.id; CREATE TABLE note_diff_files ( id integer NOT NULL, - diff_note_id_convert_to_bigint integer DEFAULT 0 NOT NULL, diff text NOT NULL, new_file boolean NOT NULL, renamed_file boolean NOT NULL, @@ -22840,7 +22736,6 @@ CREATE TABLE snippet_statistics ( CREATE TABLE snippet_user_mentions ( id bigint NOT NULL, snippet_id integer NOT NULL, - note_id_convert_to_bigint integer, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -23113,7 +23008,6 @@ ALTER SEQUENCE subscriptions_id_seq OWNED BY subscriptions.id; CREATE TABLE suggestions ( id bigint NOT NULL, - note_id_convert_to_bigint integer DEFAULT 0 NOT NULL, relative_order smallint NOT NULL, applied boolean DEFAULT false NOT NULL, commit_id character varying, @@ -23136,7 +23030,6 @@ ALTER SEQUENCE suggestions_id_seq OWNED BY suggestions.id; CREATE TABLE system_note_metadata ( id integer NOT NULL, - note_id_convert_to_bigint integer DEFAULT 0 NOT NULL, commit_count integer, action character varying, created_at timestamp without time zone NOT NULL, @@ -23296,7 +23189,6 @@ CREATE TABLE timelogs ( issue_id integer, merge_request_id integer, spent_at timestamp without time zone DEFAULT now(), - note_id_convert_to_bigint integer, project_id integer, summary text, note_id bigint, @@ -23323,7 +23215,6 @@ CREATE TABLE todos ( state character varying NOT NULL, created_at timestamp without time zone, updated_at timestamp without time zone, - note_id_convert_to_bigint integer, commit_id character varying, group_id integer, resolved_by_action smallint, @@ -24523,7 +24414,6 @@ ALTER SEQUENCE vulnerability_statistics_id_seq OWNED BY vulnerability_statistics CREATE TABLE vulnerability_user_mentions ( id bigint NOT NULL, vulnerability_id bigint NOT NULL, - note_id_convert_to_bigint integer, mentioned_users_ids integer[], mentioned_projects_ids integer[], mentioned_groups_ids integer[], @@ -24941,6 +24831,8 @@ CREATE SEQUENCE zoom_meetings_id_seq ALTER SEQUENCE zoom_meetings_id_seq OWNED BY zoom_meetings.id; +ALTER TABLE ONLY abuse_events ALTER COLUMN id SET DEFAULT nextval('abuse_events_id_seq'::regclass); + ALTER TABLE ONLY abuse_report_events ALTER COLUMN id SET DEFAULT nextval('abuse_report_events_id_seq'::regclass); ALTER TABLE ONLY abuse_reports ALTER COLUMN id SET DEFAULT nextval('abuse_reports_id_seq'::regclass); @@ -26657,6 +26549,9 @@ ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_ ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_63 ADD CONSTRAINT product_analytics_events_experimental_63_pkey PRIMARY KEY (id, project_id); +ALTER TABLE ONLY abuse_events + ADD CONSTRAINT abuse_events_pkey PRIMARY KEY (id); + ALTER TABLE ONLY abuse_report_events ADD CONSTRAINT abuse_report_events_pkey PRIMARY KEY (id); @@ -30000,6 +29895,12 @@ CREATE INDEX idx_vulnerability_reads_project_id_scanner_id_vulnerability_id ON v CREATE UNIQUE INDEX idx_work_item_types_on_namespace_id_and_name_null_namespace ON work_item_types USING btree (btrim(lower(name)), ((namespace_id IS NULL))) WHERE (namespace_id IS NULL); +CREATE INDEX index_abuse_events_on_abuse_report_id ON abuse_events USING btree (abuse_report_id); + +CREATE INDEX index_abuse_events_on_category_and_source ON abuse_events USING btree (category, source); + +CREATE INDEX index_abuse_events_on_user_id ON abuse_events USING btree (user_id); + CREATE INDEX index_abuse_report_events_on_abuse_report_id ON abuse_report_events USING btree (abuse_report_id); CREATE INDEX index_abuse_report_events_on_user_id ON abuse_report_events USING btree (user_id); @@ -35156,40 +35057,14 @@ CREATE TRIGGER trigger_023e82d8e257 BEFORE INSERT OR UPDATE ON ci_pipeline_varia CREATE TRIGGER trigger_080e73845bfd BEFORE INSERT OR UPDATE ON notes FOR EACH ROW EXECUTE FUNCTION trigger_080e73845bfd(); -CREATE TRIGGER trigger_0e214b8a14f2 BEFORE INSERT OR UPDATE ON vulnerability_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_0e214b8a14f2(); - -CREATE TRIGGER trigger_17c3a95ee58a BEFORE INSERT OR UPDATE ON commit_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_17c3a95ee58a(); - CREATE TRIGGER trigger_1a857e8db6cd BEFORE INSERT OR UPDATE ON vulnerability_occurrences FOR EACH ROW EXECUTE FUNCTION trigger_1a857e8db6cd(); -CREATE TRIGGER trigger_3dc62927cae8 BEFORE INSERT OR UPDATE ON design_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_3dc62927cae8(); - -CREATE TRIGGER trigger_428d92773fe7 BEFORE INSERT OR UPDATE ON timelogs FOR EACH ROW EXECUTE FUNCTION trigger_428d92773fe7(); - -CREATE TRIGGER trigger_482bac5ec48a BEFORE INSERT OR UPDATE ON system_note_metadata FOR EACH ROW EXECUTE FUNCTION trigger_482bac5ec48a(); - -CREATE TRIGGER trigger_775287b6d67a BEFORE INSERT OR UPDATE ON note_diff_files FOR EACH ROW EXECUTE FUNCTION trigger_775287b6d67a(); - -CREATE TRIGGER trigger_909cf0a06094 BEFORE INSERT OR UPDATE ON award_emoji FOR EACH ROW EXECUTE FUNCTION trigger_909cf0a06094(); - CREATE TRIGGER trigger_b2d852e1e2cb BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_b2d852e1e2cb(); -CREATE TRIGGER trigger_bfc6e47be8cc BEFORE INSERT OR UPDATE ON snippet_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_bfc6e47be8cc(); - -CREATE TRIGGER trigger_bfcbace4260d BEFORE INSERT OR UPDATE ON merge_request_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_bfcbace4260d(); - -CREATE TRIGGER trigger_c2051020aa8b BEFORE INSERT OR UPDATE ON issue_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_c2051020aa8b(); - -CREATE TRIGGER trigger_c5a5f48f12b0 BEFORE INSERT OR UPDATE ON epic_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_c5a5f48f12b0(); - CREATE TRIGGER trigger_cd1aeb22b34a BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE FUNCTION trigger_cd1aeb22b34a(); -CREATE TRIGGER trigger_dca935e3a712 BEFORE INSERT OR UPDATE ON todos FOR EACH ROW EXECUTE FUNCTION trigger_dca935e3a712(); - 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_ee7956d805e6 BEFORE INSERT OR UPDATE ON suggestions FOR EACH ROW EXECUTE FUNCTION trigger_ee7956d805e6(); - 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(); CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON integrations FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker(); @@ -36171,6 +36046,9 @@ ALTER TABLE p_ci_builds_metadata ALTER TABLE ONLY gitlab_subscriptions ADD CONSTRAINT fk_e2595d00a1 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; +ALTER TABLE ONLY abuse_events + ADD CONSTRAINT fk_e5ce49c215 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; + ALTER TABLE ONLY merge_requests ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL; @@ -36888,6 +36766,9 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams ALTER TABLE ONLY geo_node_namespace_links ADD CONSTRAINT fk_rails_546bf08d3e FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE; +ALTER TABLE ONLY abuse_events + ADD CONSTRAINT fk_rails_55101e588c FOREIGN KEY (abuse_report_id) REFERENCES abuse_reports(id); + ALTER TABLE ONLY issuable_metric_images ADD CONSTRAINT fk_rails_56417a5a7f FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE; @@ -38080,37 +37961,37 @@ ALTER TABLE product_analytics_events_experimental ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; ALTER TABLE ONLY ci_build_pending_states - ADD CONSTRAINT temp_fk_861cd17da3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_861cd17da3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_build_trace_chunks - ADD CONSTRAINT temp_fk_89e29fa5ee_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_89e29fa5ee_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_unit_test_failures - ADD CONSTRAINT temp_fk_9e0fc58930_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_9e0fc58930_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_sources_pipelines - ADD CONSTRAINT temp_fk_be5624bf37_p FOREIGN KEY (source_partition_id, source_job_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_be5624bf37_p FOREIGN KEY (source_partition_id, source_job_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_resources - ADD CONSTRAINT temp_fk_e169a8e3d5_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID; + ADD CONSTRAINT temp_fk_e169a8e3d5_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE SET NULL; ALTER TABLE ONLY ci_builds_metadata ADD CONSTRAINT temp_fk_e20479742e_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; ALTER TABLE ONLY ci_build_report_results - ADD CONSTRAINT temp_fk_rails_16cb1ff064_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_rails_16cb1ff064_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_build_needs - ADD CONSTRAINT temp_fk_rails_3cf221d4ed_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_rails_3cf221d4ed_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_builds_runner_session - ADD CONSTRAINT temp_fk_rails_70707857d3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_rails_70707857d3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_pending_builds - ADD CONSTRAINT temp_fk_rails_725a2644a3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_rails_725a2644a3_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_build_trace_metadata - ADD CONSTRAINT temp_fk_rails_aebc78111f_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT temp_fk_rails_aebc78111f_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY ci_job_artifacts ADD CONSTRAINT temp_fk_rails_c5137cb2c1_p FOREIGN KEY (partition_id, job_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index b4d5531b984..e86726524d0 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -406,7 +406,8 @@ domain as a custom domain to their project. If your user base is private or otherwise trusted, you can disable the verification requirement: -1. On the top bar, select **Main menu > Admin**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. 1. On the left sidebar, select **Settings > Preferences**. 1. Expand **Pages**. 1. Clear the **Require users to prove ownership of custom domains** checkbox. @@ -423,7 +424,8 @@ sites served under a custom domain. To enable it: 1. Choose an email address on which you want to receive notifications about expiring domains. -1. On the top bar, select **Main menu > Admin**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. 1. On the left sidebar, select **Settings > Preferences**. 1. Expand **Pages**. 1. Enter the email address for receiving notifications and accept Let's Encrypt's Terms of Service. @@ -476,8 +478,9 @@ pre-existing applications must modify the GitLab Pages OAuth application. Follow this: 1. Enable [access control](#access-control). -1. On the top bar, select **Main menu > Admin**. -1. On the left sidebar, select **Settings > Applications**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. +1. On the left sidebar, select **Applications**. 1. Expand **GitLab Pages**. 1. Clear the `api` scope's checkbox and select the desired scope's checkbox (for example, `read_api`). @@ -495,7 +498,8 @@ This can be helpful to restrict information published with Pages websites to the of your instance only. To do that: -1. On the top bar, select **Main menu > Admin**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. 1. On the left sidebar, select **Settings > Preferences**. 1. Expand **Pages**. 1. Select the **Disable public access to Pages sites** checkbox. @@ -664,7 +668,8 @@ Prerequisite: To set the global maximum pages size for a project: -1. On the top bar, select **Main menu > Admin**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. 1. On the left sidebar, select **Settings > Preferences**. 1. Expand **Pages**. 1. In **Maximum size of pages**, enter a value. The default is `100`. @@ -678,7 +683,7 @@ Prerequisite: To set the maximum size of each GitLab Pages site in a group, overriding the inherited setting: -1. On the top bar, select **Main menu > Groups** and find your group. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your group. 1. On the left sidebar, select **Settings > General**. 1. Expand **Pages**. 1. Enter a value under **Maximum size** in MB. @@ -692,7 +697,7 @@ Prerequisite: To set the maximum size of GitLab Pages site in a project, overriding the inherited setting: -1. On the top bar, select **Main menu > Projects** and find your project. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project. 1. On the left sidebar, select **Settings > Pages**. If this path is not visible, select **Deployments > Pages**. @@ -708,7 +713,8 @@ Prerequisite: To set the maximum number of GitLab Pages custom domains for a project: -1. On the top bar, select **Main menu > Admin**. +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. 1. On the left sidebar, select **Settings > Preferences**, and expand **Pages**. 1. Enter a value for **Maximum number of custom domains per project**. Use `0` for unlimited domains. 1. Select **Save changes**. diff --git a/doc/user/clusters/agent/ci_cd_workflow.md b/doc/user/clusters/agent/ci_cd_workflow.md index effbd5be7ec..a0b42101dd5 100644 --- a/doc/user/clusters/agent/ci_cd_workflow.md +++ b/doc/user/clusters/agent/ci_cd_workflow.md @@ -64,7 +64,7 @@ Authorization configuration can take one or two minutes to propagate. To authorize the agent to access the GitLab project where you keep Kubernetes manifests: -1. On the top bar, select **Main menu > Projects** and find the project that contains the [agent configuration file](install/index.md#create-an-agent-configuration-file) (`config.yaml`). +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains the [agent configuration file](install/index.md#create-an-agent-configuration-file) (`config.yaml`). 1. Edit the `config.yaml` file. Under the `ci_access` keyword, add the `projects` attribute. 1. For the `id`, add the path to the project. Do not wrap the path in quotation marks. @@ -89,7 +89,7 @@ Choose the context to run `kubectl` commands from your CI/CD scripts. To authorize the agent to access all of the GitLab projects in a group or subgroup: -1. On the top bar, select **Main menu > Projects** and find the project that contains the [agent configuration file](install/index.md#create-an-agent-configuration-file) (`config.yaml`). +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains the [agent configuration file](install/index.md#create-an-agent-configuration-file) (`config.yaml`). 1. Edit the `config.yaml` file. Under the `ci_access` keyword, add the `groups` attribute. 1. For the `id`, add the path: diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md index 12600747fad..76fcc73504c 100644 --- a/doc/user/clusters/agent/install/index.md +++ b/doc/user/clusters/agent/install/index.md @@ -80,10 +80,10 @@ Prerequisites: You must register an agent before you can install the agent in your cluster. To register an agent: -1. On the top bar, select **Main menu > Projects** and find your project. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project. If you have an [agent configuration file](#create-an-agent-configuration-file), it must be in this project. Your cluster manifest files should also be in this project. -1. From the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. Select **Operate > Kubernetes clusters**. 1. Select **Connect a cluster (agent)**. - If you want to create a configuration with CI/CD defaults, type a name. - If you already have an [agent configuration file](#create-an-agent-configuration-file), select it from the list. diff --git a/doc/user/clusters/agent/vulnerabilities.md b/doc/user/clusters/agent/vulnerabilities.md index a71eea82df5..cb12b23bcfb 100644 --- a/doc/user/clusters/agent/vulnerabilities.md +++ b/doc/user/clusters/agent/vulnerabilities.md @@ -100,8 +100,8 @@ You can view the complete schema within the [scan execution policy documentation To view vulnerability information in GitLab: -1. On the top bar, select **Main menu > Projects** and find the project that contains the agent configuration file. -1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains the agent configuration file. +1. Select **Operate > Kubernetes clusters**. 1. Select the **Agent** tab. 1. Select an agent to view the cluster vulnerabilities. diff --git a/doc/user/clusters/agent/work_with_agent.md b/doc/user/clusters/agent/work_with_agent.md index 2b69141d9c5..8bf9ac7cf06 100644 --- a/doc/user/clusters/agent/work_with_agent.md +++ b/doc/user/clusters/agent/work_with_agent.md @@ -18,9 +18,9 @@ Prerequisite: To view the list of agents: -1. On the top bar, select **Main menu > Projects** and find the project that contains your agent configuration file. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains your agent configuration file. You cannot view registered agents from a project that does not contain the agent configuration file. -1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. Select **Operate > Kubernetes clusters**. 1. Select **Agent** tab to view clusters connected to GitLab through the agent. On this page, you can view: @@ -40,8 +40,8 @@ is shared with a project, it automatically appears in the project agent tab. To view the list of shared agents: -1. On the top bar, select **Main menu > Projects** and find the project. -1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project. +1. Select **Operate > Kubernetes clusters**. 1. Select the **Agent** tab. The list of shared agents and their clusters are displayed. @@ -54,8 +54,8 @@ The activity logs help you to identify problems and get the information you need for troubleshooting. You can see events from a week before the current date. To view an agent's activity: -1. On the top bar, select **Main menu > Projects** and find the project that contains your agent configuration file. -1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains your agent configuration file. +1. Select **Operate > Kubernetes clusters**. 1. Select the agent you want to see activity for. The activity list includes: @@ -114,8 +114,8 @@ An agent can have only two active tokens at one time. To reset the agent token without downtime: 1. Create a new token: - 1. On the top bar, select **Main menu > Projects** and find your project. - 1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. + 1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project. + 1. Select **Operate > Kubernetes clusters**. 1. Select the agent you want to create a token for. 1. On the **Access tokens** tab, select **Create token**. 1. Enter token's name and description (optional) and select **Create token**. @@ -136,8 +136,8 @@ clean up those resources manually. To remove an agent from the UI: -1. On the top bar, select **Main menu > Projects** and find the project that contains the agent configuration file. -1. From the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find the project that contains the agent configuration file. +1. Select **Operate > Kubernetes clusters**. 1. In the table, in the row for your agent, in the **Options** column, select the vertical ellipsis (**{ellipsis_v}**). 1. Select **Delete agent**. diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md index 0ad3fdbef2e..ff6cf6bb1a8 100644 --- a/doc/user/clusters/management_project.md +++ b/doc/user/clusters/management_project.md @@ -61,7 +61,10 @@ To associate a cluster management project with your cluster: **Infrastructure > Kubernetes clusters** page. - [Group-level cluster](../group/clusters/index.md), go to your group's **Kubernetes** page. - - [Instance-level cluster](../instance/clusters/index.md), on the top bar, select **Main menu > Admin > Kubernetes**. + - [Instance-level cluster](../instance/clusters/index.md): + 1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). + 1. Select **Admin Area**. + 1. Select **Kubernetes**. 1. Expand **Advanced settings**. 1. From the **Cluster management project** dropdown list, select the cluster management project you created in the previous step. diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md index 4b6c8dcac4c..f6bcff0481a 100644 --- a/doc/user/clusters/management_project_template.md +++ b/doc/user/clusters/management_project_template.md @@ -45,8 +45,7 @@ If you have already configured the agent and connected a cluster with GitLab: To create a project from the cluster management project template: -1. In GitLab, on the top bar, select **Main menu > Projects > View all projects**. -1. On the right of the page, select **New project**. +1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**. 1. Select **Create from template**. 1. From the list of templates, next to **GitLab Cluster Management**, select **Use template**. 1. Enter the project details. diff --git a/doc/user/okrs.md b/doc/user/okrs.md index dcfeb276b63..f2e49b44154 100644 --- a/doc/user/okrs.md +++ b/doc/user/okrs.md @@ -222,7 +222,8 @@ To set health status of an OKR: ## Promote a key result to an objective -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386877) in GitLab 16.0. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386877) in GitLab 16.0. +> - Quick action `/promote_to` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/412534) in GitLab 16.1. Prerequisites: @@ -234,6 +235,8 @@ To promote a key result: 1. In the top right corner, select the vertical ellipsis (**{ellipsis_v}**).. 1. Select **Promote to objective**. +Alternatively, use the `/promote_to objective` [quick action](../user/project/quick_actions.md). + ## Close an OKR When an OKR is achieved, you can close it. diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 8e135e6d187..3e8ce009740 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -164,6 +164,7 @@ The following quick actions can be applied through the description field when ed | `/weight ` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set weight. Valid options for `` include `0`, `1`, and `2`. | `/clear_weight` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Clear weight. | `/type` | **{check-circle}** Yes | **{dotted-circle}** Yes | **{dotted-circle}** Yes | Converts work item to specified type. Available options for `` include `Issue`, `Task`, `Objective` and `Key Result`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385227) in GitLab 16.0. +| `/promote_to ` | **{check-circle}** Yes | **{dotted-circle}** No | **{check-circle}** Yes | Promotes work item to specified type. Available options for ``: `issue` (promote a task) and `objective` (promote a key result). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/412534) in GitLab 16.1. ## Commit messages diff --git a/doc/user/project/repository/code_suggestions.md b/doc/user/project/repository/code_suggestions.md index 8526f032941..90330d5f130 100644 --- a/doc/user/project/repository/code_suggestions.md +++ b/doc/user/project/repository/code_suggestions.md @@ -134,6 +134,14 @@ In VS Code: To confirm that your account is enabled, go to [https://gitlab.com/api/v4/ml/ai-assist](https://gitlab.com/api/v4/ml/ai-assist). A response of `user_is_allowed` should return `true`. +### Authentication troubleshooting + +If the above steps do not solve your issue, the problem may be related to the recent changes in authentication, specifically the token system. To resolve the issue, please follow these troubleshooting steps: + +- Remove the existing PAT from your GitLab account settings. +- Reauthorize your GitLab account in VSCode using OAuth. +- Test the code suggestions feature with different file extensions to verify if the issue is resolved. + ## Stability and performance This feature is currently in [Beta](/ee/policy/experiment-beta-support.md#beta). diff --git a/doc/user/tasks.md b/doc/user/tasks.md index fc232ee298e..dc40c7e654a 100644 --- a/doc/user/tasks.md +++ b/doc/user/tasks.md @@ -130,6 +130,16 @@ To edit the description of a task: 1. Above the text box, select **Rich text**. 1. Make your changes, and select **Save**. +## Promote a task to an issue + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/412534) in GitLab 16.1. + +Prerequisites: + +- You must have at least the Reporter role for the project. + +To promote a task to an issue, use the `/promote_to issue` [quick action](../user/project/quick_actions.md). + ## Remove a task from an issue Prerequisites: diff --git a/lib/gitlab/quick_actions/work_item_actions.rb b/lib/gitlab/quick_actions/work_item_actions.rb index 69a49d214ff..5664410f3ca 100644 --- a/lib/gitlab/quick_actions/work_item_actions.rb +++ b/lib/gitlab/quick_actions/work_item_actions.rb @@ -14,37 +14,92 @@ module Gitlab types WorkItem params 'Task | Objective | Key Result | Issue' command :type do |type_name| - work_item_type = ::WorkItems::Type.find_by_name(type_name) - errors = validate_type(work_item_type) + @execution_message[:type] = update_type(type_name, :type) + end - if errors.present? - @execution_message[:type] = errors - else - @updates[:issue_type] = work_item_type.base_type - @updates[:work_item_type] = work_item_type - @execution_message[:type] = _('Type changed successfully.') - end + desc { _('Promote work item') } + explanation do |type_name| + format(_("Promotes work item to %{type}."), type: type_name) + end + types WorkItem + params 'issue | objective' + condition { supports_promotion? } + command :promote_to do |type_name| + @execution_message[:promote_to] = update_type(type_name, :promote_to) end end private + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def update_type(type_name, command) + new_type = ::WorkItems::Type.find_by_name(type_name.titleize) + error_message = command == :type ? validate_type(new_type) : validate_promote_to(new_type) + return error_message if error_message.present? + + @updates[:issue_type] = new_type.base_type + @updates[:work_item_type] = new_type + + success_msg[command] + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + def validate_type(type) - return type_error(:not_found) unless type.present? - return type_error(:same_type) if quick_action_target.work_item_type == type - return type_error(:forbidden) unless current_user.can?(:"create_#{type.base_type}", quick_action_target) + return error_msg(:not_found) unless type.present? + return error_msg(:same_type) if quick_action_target.work_item_type == type + return error_msg(:forbidden) unless current_user.can?(:"create_#{type.base_type}", quick_action_target) nil end - def type_error(reason) + def validate_promote_to(type) + return error_msg(:not_found, action: 'promote') unless type && supports_promote_to?(type.name) + + unless current_user.can?(:"create_#{type.base_type}", quick_action_target) + return error_msg(:forbidden, action: 'promote') + end + + validate_hierarchy + end + + def validate_hierarchy + return unless current_type.task? && quick_action_target.parent_link + + error_msg(:hierarchy, action: 'promote') + end + + def current_type + quick_action_target.work_item_type + end + + def supports_promotion? + current_type.base_type.in?(promote_to_map.keys) + end + + def supports_promote_to?(type_name) + type_name == promote_to_map[current_type.base_type] + end + + def promote_to_map + { issue: 'Incident', task: 'Issue' }.with_indifferent_access + end + + def error_msg(reason, action: 'convert') message = { not_found: 'Provided type is not supported', same_type: 'Types are the same', - forbidden: 'You have insufficient permissions' + forbidden: 'You have insufficient permissions', + hierarchy: 'A task cannot be promoted when a parent issue is present' }.freeze - format(_("Failed to convert this work item: %{reason}."), { reason: message[reason] }) + format(_("Failed to %{action} this work item: %{reason}."), { action: action, reason: message[reason] }) + end + + def success_msg + { + type: _('Type changed successfully.'), + promote_to: _("Work Item promoted successfully.") + } end end end diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml index f76da9b4277..69f92ac5c0a 100644 --- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml +++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml @@ -135,3 +135,5 @@ aggregation: weekly - name: i_quickactions_unlink aggregation: weekly +- name: i_quickactions_promote_to + aggregation: weekly diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b4fe97b5cc4..a82528ec300 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -9635,6 +9635,9 @@ msgstr "" msgid "CiCatalog|This project will be marked as a CI/CD Catalog resource and will be visible in the CI/CD Catalog. This action is not reversible." msgstr "" +msgid "CiCatalog|Unreleased" +msgstr "" + msgid "CiCatalog|We want to help you create and manage pipeline component repositories, while also making it easier to reuse pipeline configurations. Let us know how we're doing!" msgstr "" @@ -18579,6 +18582,9 @@ msgstr[1] "" msgid "Failed on" msgstr "" +msgid "Failed to %{action} this work item: %{reason}." +msgstr "" + msgid "Failed to add a Zoom meeting" msgstr "" @@ -18623,9 +18629,6 @@ msgstr "" msgid "Failed to clone this issue: wrong parameters." msgstr "" -msgid "Failed to convert this work item: %{reason}." -msgstr "" - msgid "Failed to create a branch for this issue. Please try again." msgstr "" @@ -36748,6 +36751,9 @@ msgstr "" msgid "Promote to objective" msgstr "" +msgid "Promote work item" +msgstr "" + msgid "PromoteMilestone|Only project milestones can be promoted." msgstr "" @@ -36763,6 +36769,9 @@ msgstr "" msgid "Promotes issue to incident" msgstr "" +msgid "Promotes work item to %{type}." +msgstr "" + msgid "Promotion is not supported." msgstr "" @@ -51611,6 +51620,9 @@ msgstr "" msgid "Won't fix / Accept risk" msgstr "" +msgid "Work Item promoted successfully." +msgstr "" + msgid "Work Item type with id %{id} was not found" msgstr "" @@ -53429,7 +53441,7 @@ msgstr "" msgid "cannot be changed since member is associated with a custom role" msgstr "" -msgid "cannot be changed to %{new_type} with %{parent_type} as parent type." +msgid "cannot be changed to %{new_type} when linked to a parent %{parent_type}." msgstr "" msgid "cannot be changed to %{new_type} with these child item types." diff --git a/spec/factories/abuse/event.rb b/spec/factories/abuse/event.rb new file mode 100644 index 00000000000..4bd1b97410e --- /dev/null +++ b/spec/factories/abuse/event.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :abuse_event, class: 'Abuse::Event' do + user + category { :spam } + source { :spamcheck } + + trait(:with_abuse_report) do + abuse_report + end + end +end diff --git a/spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb index badc4a45c86..43da0131dd2 100644 --- a/spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb +++ b/spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb @@ -62,7 +62,7 @@ RSpec.describe BulkImports::Common::Pipelines::BoardsPipeline, feature_category: it 'imports issue boards into destination project' do expect { subject.run }.to change(::Board, :count).by(1) board = project.boards.find_by(name: board_data["name"]) - expect(board).to be + expect(board).to be_present expect(board.project.id).to eq(project.id) expect(board.lists.count).to eq(3) expect(board.lists.map(&:list_type).sort).to match_array(%w(backlog closed label)) @@ -87,7 +87,7 @@ RSpec.describe BulkImports::Common::Pipelines::BoardsPipeline, feature_category: it 'imports issue boards into destination group' do expect { subject.run }.to change(::Board, :count).by(1) board = group.boards.find_by(name: board_data["name"]) - expect(board).to be + expect(board).to be_present expect(board.group.id).to eq(group.id) expect(board.lists.count).to eq(3) expect(board.lists.map(&:list_type).sort).to match_array(%w(backlog closed label)) diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb index d8874cb811b..9f76e4131b2 100644 --- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb +++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb @@ -107,7 +107,7 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat last_commit = raw_repository(snippet).commit aggregate_failures do - expect(blob).to be + expect(blob).to be_present expect(blob.data).to eq content expect(last_commit.author_name).to eq user.name expect(last_commit.author_email).to eq user.email @@ -225,13 +225,13 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat it 'converts invalid filenames' do subject - expect(blob_at(snippet_with_invalid_path, converted_file_name)).to be + expect(blob_at(snippet_with_invalid_path, converted_file_name)).to be_present end it 'does not convert valid filenames on subsequent migrations' do subject - expect(blob_at(snippet_with_valid_path, file_name)).to be + expect(blob_at(snippet_with_valid_path, file_name)).to be_present end end end @@ -293,8 +293,8 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat it 'updates the file_name only when it is invalid' do subject - expect(blob_at(invalid_snippet, 'snippetfile1.txt')).to be - expect(blob_at(snippet, file_name)).to be + expect(blob_at(invalid_snippet, 'snippetfile1.txt')).to be_present + expect(blob_at(snippet, file_name)).to be_present end it_behaves_like 'migration_bot user commits files' do diff --git a/spec/lib/gitlab/lets_encrypt/client_spec.rb b/spec/lib/gitlab/lets_encrypt/client_spec.rb index 1baf8749532..2bed3d216e7 100644 --- a/spec/lib/gitlab/lets_encrypt/client_spec.rb +++ b/spec/lib/gitlab/lets_encrypt/client_spec.rb @@ -33,7 +33,7 @@ RSpec.describe ::Gitlab::LetsEncrypt::Client do saved_private_key = Gitlab::CurrentSettings.lets_encrypt_private_key - expect(saved_private_key).to be + expect(saved_private_key).to be_present expect(Acme::Client).to have_received(:new).with( hash_including(private_key: eq_pem(saved_private_key)) ) diff --git a/spec/lib/gitlab/search_context/builder_spec.rb b/spec/lib/gitlab/search_context/builder_spec.rb index 78799b67a69..4707299cc7d 100644 --- a/spec/lib/gitlab/search_context/builder_spec.rb +++ b/spec/lib/gitlab/search_context/builder_spec.rb @@ -75,7 +75,7 @@ RSpec.describe Gitlab::SearchContext::Builder, type: :controller do it 'delegates to `#with_group`' do expect(builder).to receive(:with_group).with(project.group) - expect(context).to be + expect(context).to be_present end it { is_expected.to be_search_context(project: project, group: project.group) } diff --git a/spec/models/abuse/event_spec.rb b/spec/models/abuse/event_spec.rb new file mode 100644 index 00000000000..02527bf80bf --- /dev/null +++ b/spec/models/abuse/event_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Abuse::Event, type: :model, feature_category: :insider_threat do + let_it_be(:event) { create(:abuse_event) } + let_it_be(:user, reload: true) { create(:admin) } + + subject { event } + + it { is_expected.to be_valid } + + describe "associations" do + it { is_expected.to belong_to(:user).class_name("User").inverse_of(:abuse_events) } + it { is_expected.to belong_to(:abuse_report).inverse_of(:abuse_events) } + end + + describe "validations" do + it { is_expected.to validate_presence_of(:source) } + it { is_expected.to validate_presence_of(:category) } + it { is_expected.to validate_presence_of(:user).on(:create) } + end + + describe 'enums' do + let(:categories) do + { + spam: 0, # spamcheck + virus: 1, # VirusTotal + fraud: 2, # Arkos, Telesign + ci_cd: 3 # PVS + } + end + + let(:sources) do + { + spamcheck: 0, + virus_total: 1, + arkose_custom_score: 2, + arkose_global_score: 3, + telesign: 4, + pvs: 5 + } + end + + it { is_expected.to define_enum_for(:source).with_values(**sources) } + it { is_expected.to define_enum_for(:category).with_values(**categories) } + end +end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 42b70cbb858..4e99419a7f2 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -896,7 +896,7 @@ RSpec.describe Issuable do let(:first_time_contributor_issue) { create(:issue, author: first_time_contributor, project: project) } it "is false even without merged MR" do - expect(merged_mr).to be + expect(merged_mr).to be_present expect(first_time_contributor_issue).not_to be_first_contribution expect(contributor_issue).not_to be_first_contribution end diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb index 124c54a2028..0bbf24534fb 100644 --- a/spec/models/identity_spec.rb +++ b/spec/models/identity_spec.rb @@ -88,7 +88,7 @@ RSpec.describe Identity do it 'finds any extern uids associated with a provider' do identity = described_class.with_any_extern_uid('test_provider').first - expect(identity).to be + expect(identity).to be_present end end diff --git a/spec/models/snippet_repository_spec.rb b/spec/models/snippet_repository_spec.rb index 050f99fd4d5..c2fbede8ea9 100644 --- a/spec/models/snippet_repository_spec.rb +++ b/spec/models/snippet_repository_spec.rb @@ -223,7 +223,7 @@ RSpec.describe SnippetRepository do snippet_repository.multi_files_action(user, [new_file], **commit_opts) - expect(blob_at(snippet, default_name)).to be + expect(blob_at(snippet, default_name)).to be_present end it 'reuses the existing file name' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d4c9df936d6..768198bc826 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -161,6 +161,7 @@ RSpec.describe User, feature_category: :user_profile do it { is_expected.to have_many(:reported_abuse_reports).dependent(:nullify).class_name('AbuseReport').inverse_of(:reporter) } it { is_expected.to have_many(:assigned_abuse_reports).class_name('AbuseReport').inverse_of(:assignee) } it { is_expected.to have_many(:resolved_abuse_reports).class_name('AbuseReport').inverse_of(:resolved_by) } + it { is_expected.to have_many(:abuse_events).class_name('Abuse::Event').inverse_of(:user) } it { is_expected.to have_many(:custom_attributes).class_name('UserCustomAttribute') } it { is_expected.to have_many(:releases).dependent(:nullify) } it { is_expected.to have_many(:metrics_users_starred_dashboards).inverse_of(:user) } diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb index 5a525d83c3b..e0ec54fd5ff 100644 --- a/spec/models/work_item_spec.rb +++ b/spec/models/work_item_spec.rb @@ -132,7 +132,7 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do subject { work_item.supported_quick_action_commands } it 'returns quick action commands supported for all work items' do - is_expected.to include(:title, :reopen, :close, :cc, :tableflip, :shrug, :type) + is_expected.to include(:title, :reopen, :close, :cc, :tableflip, :shrug, :type, :promote_to) end context 'when work item supports the assignee widget' do @@ -461,8 +461,13 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do it 'does not allow to change types' do expect(child.valid?).to eq(false) - expect(child.errors[:work_item_type_id]) - .to include("cannot be changed to #{new_type.name} with #{parent.work_item_type.name} as parent type.") + expect(child.errors[:work_item_type_id]).to include( + format( + "cannot be changed to %{type_name} when linked to a parent %{parent_name}.", + type_name: new_type.name.downcase, + parent_name: parent.work_item_type.name.downcase + ) + ) end end end diff --git a/spec/presenters/work_item_presenter_spec.rb b/spec/presenters/work_item_presenter_spec.rb new file mode 100644 index 00000000000..522ffd832c1 --- /dev/null +++ b/spec/presenters/work_item_presenter_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe WorkItemPresenter, feature_category: :portfolio_management do + let(:work_item) { build_stubbed(:work_item) } + + it 'presents a work item and uses methods defined in IssuePresenter' do + user = build_stubbed(:user) + presenter = work_item.present(current_user: user) + + expect(presenter.issue_path).to eq(presenter.web_path) + end +end diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb index 0f02b1b4f23..a6d727ae6d3 100644 --- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb @@ -178,7 +178,7 @@ RSpec.describe 'Creating a Snippet', feature_category: :source_code_management d it 'returns an error' do subject - expect(json_response['errors']).to be + expect(json_response['errors']).to be_present end end end diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb index ce1c2c01faa..60b5795ee9b 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb @@ -869,7 +869,7 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do let_it_be(:issue) { create(:work_item, project: project) } let_it_be(:link) { create(:parent_link, work_item_parent: issue, work_item: work_item) } - let(:error_msg) { 'Work item type cannot be changed to Issue with Issue as parent type.' } + let(:error_msg) { 'Work item type cannot be changed to issue when linked to a parent issue.' } it 'does not update the work item type' do expect do diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb index 9ca027c2edc..42d83ff8139 100644 --- a/spec/requests/api/pages_domains_spec.rb +++ b/spec/requests/api/pages_domains_spec.rb @@ -440,8 +440,8 @@ RSpec.describe API::PagesDomains, feature_category: :pages do expect(response).to have_gitlab_http_status(:ok) expect(response).to match_response_schema('public_api/v4/pages_domain/detail') expect(pages_domain_with_letsencrypt.auto_ssl_enabled).to be false - expect(pages_domain_with_letsencrypt.key).to be - expect(pages_domain_with_letsencrypt.certificate).to be + expect(pages_domain_with_letsencrypt.key).to be_present + expect(pages_domain_with_letsencrypt.certificate).to be_present end it 'updates pages domain with expired certificate', :aggregate_failures do diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 89114bf3fd0..22509885c92 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -567,6 +567,19 @@ RSpec.describe Notes::CreateService, feature_category: :team_planning do note_text = %(/close) described_class.new(project, user, opts.merge(note: note_text)).execute end + + it 'generates failed update error messages' do + note_text = %(/confidential) + service = double(:service) + issue.errors.add(:confidential, 'an error occurred') + allow(Issues::UpdateService).to receive(:new).and_return(service) + allow_next_instance_of(Issues::UpdateService) do |service_instance| + allow(service_instance).to receive(:execute).and_return(issue) + end + + note = described_class.new(project, user, opts.merge(note: note_text)).execute + expect(note.errors[:commands_only]).to contain_exactly('Confidential an error occurred') + end end end diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb index c65a077f907..cd3a4e8a395 100644 --- a/spec/services/notes/quick_actions_service_spec.rb +++ b/spec/services/notes/quick_actions_service_spec.rb @@ -248,6 +248,46 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do end end end + + describe '/promote_to' do + shared_examples 'promotes work item' do |from:, to:| + it 'leaves the note empty' do + expect(execute(note)).to be_empty + end + + it 'promotes to provided type' do + expect { execute(note) }.to change { noteable.work_item_type.base_type }.from(from).to(to) + end + end + + context 'on a task' do + let_it_be_with_reload(:noteable) { create(:work_item, :task, project: project) } + let_it_be(:note_text) { '/promote_to Issue' } + let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) } + + it_behaves_like 'promotes work item', from: 'task', to: 'issue' + + context 'when type name is lower case' do + let_it_be(:note_text) { '/promote_to issue' } + + it_behaves_like 'promotes work item', from: 'task', to: 'issue' + end + end + + context 'on an issue' do + let_it_be_with_reload(:noteable) { create(:work_item, :issue, project: project) } + let_it_be(:note_text) { '/promote_to Incident' } + let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) } + + it_behaves_like 'promotes work item', from: 'issue', to: 'incident' + + context 'when type name is lower case' do + let_it_be(:note_text) { '/promote_to incident' } + + it_behaves_like 'promotes work item', from: 'issue', to: 'incident' + end + end + end end describe '.supported?' do @@ -380,6 +420,87 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do end end + describe '#apply_updates' do + include_context 'note on noteable' + + let_it_be(:issue) { create(:issue, project: project) } + let_it_be(:work_item, reload: true) { create(:work_item, :issue, project: project) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + let_it_be(:issue_note) { create(:note_on_issue, project: project, noteable: issue) } + let_it_be(:work_item_note) { create(:note, project: project, noteable: work_item) } + let_it_be(:mr_note) { create(:note_on_merge_request, project: project, noteable: merge_request) } + let_it_be(:commit_note) { create(:note_on_commit, project: project) } + let(:update_params) { {} } + + subject(:apply_updates) { described_class.new(project, maintainer).apply_updates(update_params, note) } + + context 'with a note on an issue' do + let(:note) { issue_note } + + it 'returns successful service response if update returned no errors' do + update_params[:confidential] = true + expect(apply_updates.success?).to be true + end + + it 'returns service response with errors if update failed' do + update_params[:title] = "" + expect(apply_updates.success?).to be false + expect(apply_updates.message).to include("Title can't be blank") + end + end + + context 'with a note on a merge request' do + let(:note) { mr_note } + + it 'returns successful service response if update returned no errors' do + update_params[:title] = 'New title' + expect(apply_updates.success?).to be true + end + + it 'returns service response with errors if update failed' do + update_params[:title] = "" + expect(apply_updates.success?).to be false + expect(apply_updates.message).to include("Title can't be blank") + end + end + + context 'with a note on a work item' do + let(:note) { work_item_note } + + before do + update_params[:confidential] = true + end + + it 'returns successful service response if update returned no errors' do + expect(apply_updates.success?).to be true + end + + it 'returns service response with errors if update failed' do + task = create(:work_item, :task, project: project) + create(:parent_link, work_item: task, work_item_parent: work_item) + + expect(apply_updates.success?).to be false + expect(apply_updates.message) + .to include("A confidential work item cannot have a parent that already has non-confidential children.") + end + end + + context 'with a note on a commit' do + let(:note) { commit_note } + + it 'returns successful service response if update returned no errors' do + update_params[:tag_name] = 'test' + expect(apply_updates.success?).to be true + end + + it 'returns service response with errors if update failed' do + update_params[:tag_name] = '-test' + expect(apply_updates.success?).to be false + expect(apply_updates.message).to include('Tag name invalid') + end + end + end + context 'CE restriction for issue assignees' do describe '/assign' do let(:project) { create(:project) } diff --git a/spec/services/pages/delete_service_spec.rb b/spec/services/pages/delete_service_spec.rb index 590378af22b..488f29f6b7e 100644 --- a/spec/services/pages/delete_service_spec.rb +++ b/spec/services/pages/delete_service_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Pages::DeleteService, feature_category: :pages do service.execute expect(PagesDomain.find_by_id(domain.id)).to eq(nil) - expect(PagesDomain.find_by_id(unrelated_domain.id)).to be + expect(PagesDomain.find_by_id(unrelated_domain.id)).to be_present end it 'schedules a destruction of pages deployments' do diff --git a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb index 4348ce4a271..48690a035f5 100644 --- a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb +++ b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb @@ -58,7 +58,7 @@ RSpec.describe Pages::MigrateFromLegacyStorageService, feature_category: :pages expect(project.pages_metadatum.reload.pages_deployment).to eq(nil) expect(subject).to eq(migrated: 1, errored: 0) - expect(project.pages_metadatum.reload.pages_deployment).to be + expect(project.pages_metadatum.reload.pages_deployment).to be_present end context 'when deployed already exists for the project' do diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index a97369c4b08..a113f3506e1 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -95,7 +95,7 @@ RSpec.describe Projects::UpdatePagesService, feature_category: :pages do deployment = project.pages_deployments.last expect(deployment.size).to eq(file.size) - expect(deployment.file).to be + expect(deployment.file).to be_present expect(deployment.file_count).to eq(3) expect(deployment.file_sha256).to eq(artifacts_archive.file_sha256) expect(project.pages_metadatum.reload.pages_deployment_id).to eq(deployment.id) diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 71bff37b956..bd09dae0a5a 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -2417,54 +2417,7 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning end end - describe 'type command' do - let_it_be(:project) { create(:project, :private) } - let_it_be(:work_item) { create(:work_item, project: project) } - - let(:command) { '/type Task' } - - context 'when user has sufficient permissions to create new type' do - before do - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(current_user, :create_task, work_item).and_return(true) - end - - it 'populates :issue_type: and :work_item_type' do - _, updates, message = service.execute(command, work_item) - - expect(message).to eq(_('Type changed successfully.')) - expect(updates).to eq({ issue_type: 'task', work_item_type: WorkItems::Type.default_by_type(:task) }) - end - - it 'returns error with an invalid type' do - _, updates, message = service.execute('/type foo', work_item) - - expect(message).to eq(_("Failed to convert this work item: Provided type is not supported.")) - expect(updates).to eq({}) - end - - it 'returns error with same type' do - _, updates, message = service.execute('/type Issue', work_item) - - expect(message).to eq(_("Failed to convert this work item: Types are the same.")) - expect(updates).to eq({}) - end - end - - context 'when user has insufficient permissions to create new type' do - before do - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(current_user, :create_task, work_item).and_return(false) - end - - it 'returns error' do - _, updates, message = service.execute(command, work_item) - - expect(message).to eq(_("Failed to convert this work item: You have insufficient permissions.")) - expect(updates).to eq({}) - end - end - end + it_behaves_like 'quick actions that change work item type' end describe '#explain' do @@ -2955,6 +2908,28 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning end end end + + describe 'promote_to command' do + let(:content) { '/promote_to issue' } + + context 'when work item supports promotion' do + let_it_be(:task) { build(:work_item, :task, project: project) } + + it 'includes the value' do + _, explanations = service.explain(content, task) + expect(explanations).to eq(['Promotes work item to issue.']) + end + end + + context 'when work item does not support promotion' do + let_it_be(:incident) { build(:work_item, :incident, project: project) } + + it 'does not include the value' do + _, explanations = service.explain(content, incident) + expect(explanations).to be_empty + end + end + end end describe '#available_commands' do diff --git a/spec/support/shared_contexts/quick_actions/work_items_type_change_shared_context.rb b/spec/support/shared_contexts/quick_actions/work_items_type_change_shared_context.rb new file mode 100644 index 00000000000..fc51af899a0 --- /dev/null +++ b/spec/support/shared_contexts/quick_actions/work_items_type_change_shared_context.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +RSpec.shared_context 'with work item change type context' do + let_it_be(:project) { create(:project, :private) } + let_it_be(:work_item) { create(:work_item, project: project) } + let(:new_type) { 'Task' } + let(:with_access) { true } + + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(current_user, :"create_#{new_type.downcase}", work_item) + .and_return(with_access) + end + + shared_examples 'quick command error' do |error_reason, action = 'convert'| + let(:error) { format("Failed to %{action} this work item: %{reason}.", action: action, reason: error_reason) } + + it 'returns error' do + _, updates, message = service.execute(command, work_item) + + expect(message).to eq(error) + expect(updates).to eq({}) + end + end +end diff --git a/spec/support/shared_examples/graphql/notes_quick_actions_for_work_items_shared_examples.rb b/spec/support/shared_examples/graphql/notes_quick_actions_for_work_items_shared_examples.rb index 52908c5b6df..30212e44c6a 100644 --- a/spec/support/shared_examples/graphql/notes_quick_actions_for_work_items_shared_examples.rb +++ b/spec/support/shared_examples/graphql/notes_quick_actions_for_work_items_shared_examples.rb @@ -172,6 +172,25 @@ RSpec.shared_examples 'work item supports type change via quick actions' do expect(response).to have_gitlab_http_status(:success) end + context 'when update service returns errors' do + let_it_be(:issue) { create(:work_item, :issue, project: project) } + + before do + create(:parent_link, work_item: noteable, work_item_parent: issue) + end + + it 'mutation response include the errors' do + expect do + post_graphql_mutation(mutation, current_user: current_user) + noteable.reload + end.not_to change { noteable.work_item_type.base_type } + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']) + .to include('Validation Work item type cannot be changed to issue when linked to a parent issue.') + end + end + context 'when quick command for unsupported widget is present' do let(:body) { "\n/type Issue\n/assign @#{assignee.username}" } diff --git a/spec/support/shared_examples/quick_actions/work_item/type_change_quick_actions_shared_examples.rb b/spec/support/shared_examples/quick_actions/work_item/type_change_quick_actions_shared_examples.rb new file mode 100644 index 00000000000..9ccb7c0ae42 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/work_item/type_change_quick_actions_shared_examples.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'quick actions that change work item type' do + include_context 'with work item change type context' + + describe 'type command' do + let(:command) { "/type #{new_type}" } + + it 'populates :issue_type: and :work_item_type' do + _, updates, message = service.execute(command, work_item) + + expect(message).to eq(_('Type changed successfully.')) + expect(updates).to eq({ issue_type: 'task', work_item_type: WorkItems::Type.default_by_type(:task) }) + end + + context 'when new type is invalid' do + let(:command) { '/type foo' } + + it_behaves_like 'quick command error', 'Provided type is not supported' + end + + context 'when new type is the same as current type' do + let(:command) { '/type Issue' } + + it_behaves_like 'quick command error', 'Types are the same' + end + + context 'when user has insufficient permissions to create new type' do + let(:with_access) { false } + + it_behaves_like 'quick command error', 'You have insufficient permissions' + end + end + + describe 'promote_to command' do + let(:new_type) { 'issue' } + let(:command) { "/promote_to #{new_type}" } + + shared_examples 'action with validation errors' do + context 'when user has insufficient permissions to create new type' do + let(:with_access) { false } + + it_behaves_like 'quick command error', 'You have insufficient permissions', 'promote' + end + + context 'when new type is not supported' do + let(:new_type) { unsupported_type } + + it_behaves_like 'quick command error', 'Provided type is not supported', 'promote' + end + end + + context 'with issue' do + let(:new_type) { 'incident' } + let(:unsupported_type) { 'task' } + + it 'populates :issue_type: and :work_item_type' do + _, updates, message = service.execute(command, work_item) + + expect(message).to eq(_('Work Item promoted successfully.')) + expect(updates).to eq({ issue_type: 'incident', work_item_type: WorkItems::Type.default_by_type(:incident) }) + end + + it_behaves_like 'action with validation errors' + end + + context 'with task' do + let_it_be_with_reload(:task) { create(:work_item, :task, project: project) } + let(:work_item) { task } + let(:new_type) { 'issue' } + let(:unsupported_type) { 'incident' } + + it 'populates :issue_type: and :work_item_type' do + _, updates, message = service.execute(command, work_item) + + expect(message).to eq(_('Work Item promoted successfully.')) + expect(updates).to eq({ issue_type: 'issue', work_item_type: WorkItems::Type.default_by_type(:issue) }) + end + + it_behaves_like 'action with validation errors' + + context 'when task has a parent' do + let_it_be(:parent) { create(:work_item, :issue, project: project) } + + before do + create(:parent_link, work_item: task, work_item_parent: parent) + end + + it_behaves_like 'quick command error', 'A task cannot be promoted when a parent issue is present', 'promote' + end + end + end +end diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb index 3168f25e4fa..283ab565dc4 100644 --- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb @@ -119,7 +119,7 @@ RSpec.shared_examples 'job token for package uploads' do |authorize_endpoint: fa pkg = ::Packages::Package.order_created .last - expect(pkg.build_infos).to be + expect(pkg.build_infos).to be_present end end end diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb index 3340725dd6d..6d4843b6bbf 100644 --- a/spec/uploaders/file_uploader_spec.rb +++ b/spec/uploaders/file_uploader_spec.rb @@ -90,9 +90,9 @@ RSpec.describe FileUploader do shared_examples 'returns a valid uploader' do describe 'returned uploader' do it 'generates a new secret' do - expect(subject).to be + expect(subject).to be_present expect(described_class).to receive(:generate_secret).once.and_call_original - expect(moved).to be + expect(moved).to be_present end it 'creates new upload correctly' do diff --git a/spec/uploaders/namespace_file_uploader_spec.rb b/spec/uploaders/namespace_file_uploader_spec.rb index 99bf4e130f2..02381123ba5 100644 --- a/spec/uploaders/namespace_file_uploader_spec.rb +++ b/spec/uploaders/namespace_file_uploader_spec.rb @@ -73,9 +73,9 @@ RSpec.describe NamespaceFileUploader do shared_examples 'returns a valid uploader' do it 'generates a new secret' do - expect(subject).to be + expect(subject).to be_present expect(described_class).to receive(:generate_secret).once.and_call_original - expect(moved).to be + expect(moved).to be_present end it 'creates new upload correctly' do